Jump to content
Search Community

Draw Bezier curve path with SVG

Legotin test
Moderator Tag

Go to solution Solved by GreenSock,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

I have a path for my animation. This path is Bezier curve which can be plotted by arbitrary number of points:

bezier:{
  curviness:1.25,
  values:[
    {x:100, y:250},
    {x:300, y:0},
    /* ... N more points ... */
    {x:500, y:400},
    {x:200, y:100}
  ]
}

I want depict this path with SVG <path/> element.

Path element uses M, C, Q, T and other parameters for plotting curve, for example:

<path d="M100,200 C100,100 250,100 250,200 S400,300 400,200" />

How can I convert my points to the terms of parameters used in SVG path?

Link to comment
Share on other sites

  • Solution

If I understand your objective correctly, you can use the BezierPlugin.bezierThrough() method and construct the string accordingly like this:

http://codepen.io/anon/pen/rLVzja?editors=1010

var values = [{x:0, y:0}, {x:100, y:100}, {x:50, y:200}, {x:40, y:30}, {x:200, y:50}];
var curviness = 1.25;

TweenLite.set("#path", {strokeWidth:5, stroke:"red", fill:"none"});

var data = BezierPlugin.bezierThrough(values, curviness);
var d = "M" + data.x[0].a + "," + data.y[0].a + " C" + segmentToString(data.x[0], data.y[0]); //the <path> data
for (var i = 1; i < data.x.length; i++) {
  d += "," + segmentToString(data.x[i], data.y[i]);
}
TweenLite.set("#path", {attr:{d:d}});
TweenLite.to("#circle", 5, {bezier:{values:values, curviness:curviness}, ease:Power1.easeInOut})

//this just helps consolidate some of the code, and ensure that the values are clipped to 2 decimal places. It could be done in a more performant way, avoiding toFixed(2), but my goal here was to keep things simple:
function segmentToString(x, y) {
  return [x.b.toFixed(2), y.b.toFixed(2), x.c.toFixed(2), y.c.toFixed(2), x.d.toFixed(2), y.d.toFixed(2)].join(",");
}

Docs for BezierPlugin.bezierThrough(): http://greensock.com/docs/#/HTML5/GSAP/Plugins/BezierPlugin/bezierThrough/

 

Does that help?

  • Like 4
Link to comment
Share on other sites

@OSUblake, no, it's not really based off of that. In my tests, that [relatively common] algorithm looked a little funky in some situations (especially when there's one anchor super close, and another very far away) so I crafted my own that I think looks more natural. 

Link to comment
Share on other sites

I've always assumed it was based off of that because of Rodrigo's

See the Pen kjmDo by rhernando (@rhernando) on CodePen

that shows how to create circular motion. That's pretty crazy to hear that you came up with your own solution. It takes mathematicians years to come up with a good way to fit a curve.

 

I was curious to see how your curves would compare to spiro curves, so I dropped it into one of my older demos. It can't handle long segments like spiro, but if you place the points close together, it does a really good job of following the spiro path. Probably the best I've ever seen. The blue curve is yours...

 

y1SwJr9.png

 

You can test it out here. Using a tension of 1.5 matches up the best.

See the Pen 7428401b65c8bf4b7e5f74e6baf211bc by osublake (@osublake) on CodePen

 

  • 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.
×
×
  • Create New...