Jump to content
GreenSock

Andy Bui

DrawSVG keep drawing even through it already finished

Go to solution Solved by GreenSock,

Recommended Posts

Hi all,

 

First time working with DrawSVG so I don't fully understand how it works with drawing. As you can see from my codepen, I set the time for 10s but it only takes about 2-3s to finish drawing the house and when I check on browser, the stroke value is still running even through the house and tree is already completed. Can anyone help me set up the correct time for the img to draw exactly with the time set ?

 

Thanks a lot

See the Pen poKrOXN by tcb2307 (@tcb2307) on CodePen

Link to comment
Share on other sites

  • Solution

Yeah, the problem is actually your artwork - you've got a single <path> that has a bunch of different segments (indicated by "M" commands). If you getTotalLength() on the path, you'll see that it's like 1157, so drawSVG correctly animates the stroke according to that length (as you can see in Dev Tools), but the browser doesn't render it correctly because it's not like there's a single stroke that can go through all of those segments. If anything, it's a browser issue. 

 

Normally, people use DrawSVG on single-segment <path> elements. 

 

So you'd need to bust the multi-segment <path> into a separate <path> for each segment. Sounds painful, right? Don't worry - I spent some time tonight writing this helper function for you that automates it all (and requires MotionPathPlugin): 

// helper function that busts apart a single <path> that has multiple segments into a <path> for each segment (indicated by an "M" command);
function splitPaths(paths) {
  let toSplit = gsap.utils.toArray(paths),
      newPaths = [];
  if (toSplit.length > 1) {
    toSplit.forEach(path => newPaths.push(...splitPaths(path)));
  } else {
    let path = toSplit[0],
        rawPath = MotionPathPlugin.getRawPath(path),
        parent = path.parentNode,
        attributes = [].slice.call(path.attributes);
    newPaths = rawPath.map(segment => {
      let newPath = document.createElementNS("http://www.w3.org/2000/svg", "path"),
          i = attributes.length;
      while (i--) {
        newPath.setAttributeNS(null, attributes[i].nodeName, attributes[i].nodeValue);
      }
      newPath.setAttributeNS(null, "d", "M" + segment[0] + "," + segment[1] + "C" + segment.slice(2).join(",") + (segment.closed ? "z" : ""));
      parent.insertBefore(newPath, path);
      return newPath;
    });
    parent.removeChild(path);
  }
  return newPaths;
}

Usage: 

let newPaths = splitPaths("path"); // or any selector text or element
// returns an Array of the newly created <path> elements

See the Pen RwJZEOv?editors=1010 by GreenSock (@GreenSock) on CodePen

 

You could split a single path and then create a sequenced set of tweens if you want it to go from start to finish across all those segments too. Lots of options. 

 

Does that clear things up? 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

By the way, here's an isolated CodePen that shows how to sequence all the segments in a linear fashion that maintains a consistent speed too: 

See the Pen yLEzJNE?editors=0010 by GreenSock (@GreenSock) on CodePen

  • Like 2
Link to comment
Share on other sites

Thanks a lot @GreenSock. This is exactly the answer I am looking for and it also helps me understand how svg works. I really appreciate you spending time writing that function to clear up the problem I face.

 

Hope you have a great day

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×