Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Legotin

Draw Bezier curve path with SVG

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

I can show how to do this later.

 

Quick question. Is the SVG going to be part of the finished product, or are you just trying to visualize it for testing purposes.

  • Like 2
Link to comment
Share on other sites

Great!

And yes, it will be a part of the finished product.

  • Like 1
Link to comment
Share on other sites

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

Yes, this is it! Thanks!

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.
×