Last week I began a discussion about paths, mainly focusing on the different line commands you can use to draw lines and shapes. Today I want to continue the path discussion and talk about the different curve commands at your disposal.
The curve commands take a bit more explanation than the line commands so lets get right to it. I’ll assume you’ve read the previous post about line commands. If you haven’t you may want to read it first.
Curve Commands
There are three groups of curve commands and, just as with the line commands, the upper case letter is for absolute values and lower case is for relative values.
 Cubic bézier curve commands (C, c, S, s)
 Quadratic bézier curve commands (Q, q, T, t)
 Elliptical arc curve commands (A, a)
The Cubic Bézier Command
I assume you’re familiar with bézier curves. You’ve probably drawn some in a graphics editor. I won’t go into all the math behind them, but you draw a bézier curve by defining a start and end point as well as two control points, one for the start point and one for the end point.
The cubic bézier curve command will take the form:
C (or c) x1,y1 x2,y2 x,y 
where
 x1,y1 is the control point at beginning of curve
 x2,y2 is the control point at end of curve
 x,y is the end point for curve
The starting point for the curve is the end point from the previous command so we don’t need to set it again.
How about an example? Once again, I’ll use inline SVG for all the examples
<svg width="600" height="300">


<path d="M100,200


C100,100 400,100 400,200"


fill="none" stroke="#000" strokewidth="2px" /> 

</svg>

I start with an svg element, give it a width and height and also a fill and stroke. Hopefully these things have become familiar to you by now.
The path starts by moving to the point 100,200, which becomes the starting point for the curve. The cubic bézier curve command (C) then draws the curve. The first control point is 100,100. The second control point is 400,100. The end point of the curve is at 400,200
The curve starts in the direction of the first control point and then bends so it reaches the end of the curve in the direction of the second control point.
It’s not as easy for me to look at the bézier curve command and know what will happen. I’m guessing it’s the same for you. You’ll probably have to experiment on your own and try different values for the control points to get a better feel for them. I know I need to.
Like lines, you don’t have to stop at a single curve. You can connect one curve to another and create more complex curves.
<svg width="600" height="300">


<path d="M100,200 C100,100 400,100 400,200 c100,200 400,100 300,0" fill="none" stroke="#000" strokewidth="2px" />


</svg>

Here I added a second bézier curve connected to the first. You can see the connection between them isn’t very smooth.
Usually when connecting curves, the control point at the start of the second curve is a reflection of the control point at the end the first curve.
Fortunately you don’t have to figure out how to calculate the reflection of a control point. The S and s commands are shortcuts to let browsers work it out for you. It’s a lot easier that way.
<svg width="600" height="300">


<path d="M100,200


C100,100 400,100 400,200


s100,100 300,0"


fill="none" stroke="#000" strokewidth="2px" /> 

</svg>

Here I replaced the second curve with a relative shortcut (s) to match the curve that was using relative coordinates. You can see the point where the two curves connect is now much smoother.
Here are the two curves again, this time using the absolute shortcut.
<svg width="600" height="300">


<path d="M100,200


C100,100 400,100 400,200


S400,100 300,0"


fill="none" stroke="#000" strokewidth="2px" /> 

</svg>

You can see they don’t look quite the same, even if the connection between curves is still smooth. The joint might not be shallow, but it is smooth. You can see what I mean by drawing the individual curves again, only this time using an absolute curve for the second one.
<svg width="600" height="300">


<path d="M100,200


C100,100 400,100 400,200


C100,200 400,100 300,0"


fill="none" stroke="#000" strokewidth="2px" /> 

</svg>

It’s something to keep in mind if your curve doesn’t do what you think. You might be using absolute or relative coordinates when you meant to use the other.
The Quadratic Bézier Command
Your instinct might be to think the quadratic bézier command will be more complicated and add an additional control point. It’s actually the opposite.
The quadratic bézier command requires only a single control point, which is then used as the control point for both start and end points.
<svg width="600" height="300">


<path d="M100,200


Q250,100 400,200"


fill="none" stroke="#000" strokewidth="2px" /> 

</svg>

Once again, we start with a moveto command and then draw the quadratic bézier curve. The curve starts at 100,200 and ends at 400,200. Control points for both start and end are 250,100.
The quadratic bézier command also has a shortcut (T or t) to help smooth the connection between multiple curves. It works the same as the S or s shortcuts on the cubic bézier command and it too helps smooth the curve by using the reflection of the control point to start the second curve.
<svg width="600" height="300">


<path d="M100,200


Q250,100 400,200


T600 200"


fill="none" stroke="#000" strokewidth="2px" /> 

</svg>

The quadratic bézier command is a little easier to work with because it requires one fewer control point, however, the cubic bézier command offers more control, because of the extra control point.
Elliptical Arcs
The last of the three types of curve commands is the elliptical arc (A or a). The arc command draws a segment of an ellipse. It takes the most parameters of any of the curve commands and takes the following form.
A rx ry xaxisrotation largearcflag sweepflag x y 
where
 x,y is the end point for the arc
 rx is the xradius of the ellipse
 ry is the yradius of the ellipse
 xaxisrotation is the degrees to rotate the xaxis
The arc that is drawn will be a segment of this ellipse. Setting both x and y radius to the same value creates a circle instead of an ellipse.
The two flags will take a little more explanation. Given a start and end point and an ellipse with rx, ry, and xaxisrotation, there are actually four possible arcs than can be drawn. This is easier to see with an example.
<svg width="600" height="300">


<path d="M250,100 A120,80 0 0,0 250,200"


fill="none" stroke="red" strokewidth="5" />


<path d="M250,100 A120,80 0 1,1 250,200"


fill="none" stroke="green" strokewidth="5"/>


<path d="M250,100 A120,80 0 1,0 250,200"


fill="none" stroke="purple" strokewidth="5"/>


<path d="M250,100 A120,80 0 0,1 250,200"


fill="none" stroke="blue" strokewidth="5"/>


</svg>

The example looks like two multicolored ellipses of the exact same dimensions, but it’s really four different arcs as you can see in the code.
The two points at which all four arcs connect are the start point (higher) and end point (lower). All four ellipses have the same values for rx, ry, and xaxisrotation. As you can see four different arcs can be drawn from start to end point.
The difference in the four arcs are the values of the largearcflag and the sweepflag. Consider the red and purple arcs. Both have a value of 0 for the sweepflag. The red arc has a value of 0 for the largearcflag and the purple arc has a value of 1 for the same flag. They differ only in their values for the largearcflag.
Looking at the two arcs can you guess what the largearcflag does and what its values mean? A value of 0 means to use the smaller arc, while a value of 1 means use the larger arc.
Now compare the red and blue arcs. Both have a value of 0 for the largearcflag, so both are the smaller arcs. Where red also has a value of 0 for the sweepflag, the blue arc has a value of 1 for the flag.
The blue arc is a mirror of the red arc around the axis created by the start and end points. The sweepflag determines whether to use an arc (0) or its reflection around the axis (1).
I had to play around with the example I just presented to really understand the different arcs and flags. If you’re still a little confused don’t worry. Just play and experiment a bit. Copy my code and change a value here or there to see what happens. It all makes more sense with practice.
Closing Thoughts
As I mentioned at the close of last week’s post, paths are more powerful and more flexible than the basic shapes. They can take a little more work to create, but hardly a lot. Sometimes they’ll even take less work. They’re used for more than creating lines, curves, and shapes, but we’ll save those uses for another time.
Odds are any graphic editor you use to create SVG images will export the image using paths so it makes sense to understand and learn how to work with them even if you don’t usually end up drawing paths with code.
You have two sets of commands with paths, one for creating lines and one for creating curves. It shouldn’t take more than a few minutes to memorize the commands and start working with both. You’ll likely find lines easier to work with than curves, but with a little practice, curves will come too.
I think I’ll leave the SVG series here for a little while. I’ll come back to more SVG topics in the coming months, but after five weeks of SVG lets talk about something else for a little while.
Download a free sample from my book, Design Fundamentals.
Are arcs rendered faster than beziers in SVG?
I have no idea. It’s not something I’ve ever looked at or thought about. I wouldn’t imagine either takes long and I’m sure both render faster than the equivalent .jpg, .png, etc. image would take to render.
The coloured ellipses make up one of the classiest examples of code I have ever seen – simple and powerful.
Thanks Paul. I’m glad you liked it.
Change T command to Q command in SVG
This SVG file uses Command T (smooth quadratic Bezier curveto), but I like to change to command Q (quadratic Bezier curveto) which needs a control point. According to the document (http://tutorials.jenkov.com/svg/pathelement.html The control point is assumed to be the same as the last control point used. Which I think is NOT true. I played with few examples they do produce correct answer, but those examples consist of all point on the same line excluding control points) . In this example 383.05,399.92,Q383.05,402.63,381.85,403.27,T375.48,403.9. The points (383.05,399.92),(381.85,403.27)and(375.48,403.9) are not on the same line. Can someone point me how to resolve this problem? Any help will be very much appreciated.
Hello, and thank you for the site. Found you linked from
https://www.ericeastwood.com/blog/25/curvesandarcsquadraticcubicellipticalsvgimplementations
[NB: you may have some certification issues getting there]
I’m working with SVG to produce cycloidal curves (circles rotating around other circles and ellipses). I need to find a way to scale a pathgenerated ellipse into one of a smaller or larger size, so I need to know the the x & y radii / focal points. This has to be done with JS.
Would appreciate any advice / suggestions you might have on scaling ellipses this way.