I have an array of control points that represent a high-order Bezier curve.
How can I draw this curve using a single SVG-path?
UPD:
For example, I have a set of points: (x1, y1) (x2, y2) (x3, y3) (x4, y4) (x5, y5).
How SVG-path will look like in the terms of C
, S
, Q
or T
?
UPD 2: SOLUTION
I asked this question to depict a object path animated with TweenMax.
Later I received reply on GreenSock forum.
Here's CodePen example.
The other type of curved line that can be created using SVG is the arc, called with the A command. Arcs are sections of circles or ellipses. For a given x-radius and y-radius, there are two ellipses that can connect any two points (as long as they're within the radius of the circle).
To draw a line using this equation, one can divide the curve into smaller segments, calculate the end points of each segment using the Bezier cubic equation and draw the line for the segment. For instance, one can draw a line between the points defined by t = 0 and t = 0.01, then t = 0.01 and t = 0.02, and so on.
The bezierCurveTo() method adds a point to the current path by using the specified control points that represent a cubic Bézier curve. A cubic bezier curve requires three points. The first two points are control points that are used in the cubic Bézier calculation and the last point is the ending point for the curve.
Short answer: you can't.
SVG only has built in Quadratic (2nd order) and Cubic curves (3rd order), whereas the curve you're showing is Quartic (4th order). SVG has no generic "N term Bezier" draw instruction, so you're going to have to compromise here.
Some options:
toDataURL
function and then load that image as image in your SVG. This will work perfectly fine, but if you use created SVG path styling, making the canvas generate the same style could be a challenge.Bottom line: if you need to show higher order Bezier curves, SVG is not an appropriate technology to use (I'd recommend just doing your animation using the canvas, or better yet, something like d3.js or paper.js. Probably the latter).
And if you end up rolling your own, the sampling function is ludicrously simple. Curves are parametric, controlled by a value t
that runs from 0 to 1 (inclusive), and can be written as a nested linear interpolation:
getCurvePoint(t, points) {
if (points.length === 1) return points[0];
var newpoints = [];
for(var i=0,j=1; j<points.length; i++,j++) {
newpoints[i] = lerp2d(t, points[i], points[j]);
}
return getCurvePoint(t,newpoints);
}
with the lerp
function being the standard linear interpolation function:
lerp(ratio, start, end) {
return ratio*start + (1-ratio)*end;
}
lerp2d(ratio, start, end) {
return {
x: lerp(ratio, start.x, end.x),
y: lerp(ratio, start.y, end.y)
};
}
And a simple jsbin example: http://jsbin.com/pesutibefu/edit?html,js,output using points
var points = [
{x:50, y:100},
{x:50, y:250},
{x:210, y:250},
{x:250, y:50},
{x:380, y:150}
];
gives us:
Although a Paper.js sketch would be easier to work with if you need animated pretty paths, with draggable control points, etc.
SVG does not support Bezier curves other than Quadratic and Cubic. So there is no representation in terms of commands(C, S, Q or T).
A Bezier curve can be defined in two ways: With a "C" command for cubic or with a "Q" command for quadratic. Those command have fixed length of parameters which is 4 for quadratic and 6 for cubic so an example SVG string will look like "Q 150,-300 300,0" you can see an SVG string like that "Q 150,-300 300,0 50,150 100,200" but that is just two quad curves one after another and the number of parameters will always be always multiple of 4 for "Q" and multiple of 6 for "C".
Every command in the list:
M = moveto
L = lineto
H = horizontal lineto
V = vertical lineto
C = curveto
S = smooth curveto
Q = quadratic Bézier curve
T = smooth quadratic Bézier curveto
A = elliptical Arc
Z = closepath
has a representation in JavaScript or in fact in any other standard API (.NET Drawing, Core Graphics, Android Canvas) but in all of them there is no method for anything other than Cubic or Quad. Also in my experience I have never seen a drawing application that has a feature to draw a higher order Bezier curve. So your best option is to simplify the high order curve to a Q or C.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With