SVG Basics—Creating Paths With Curve Commands

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:

1
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

1
2
3
4
5
<svg width="600" height="300">
  <path d="M100,200
           C100,100  400,100  400,200"
   fill="none" stroke="#000" stroke-width="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.

1
2
3
<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" stroke-width="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.

1
2
3
4
5
6
<svg width="600" height="300">
    <path d="M100,200
             C100,100  400,100  400,200
             s100,100 300,0"
     fill="none" stroke="#000" stroke-width="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.

1
2
3
4
5
6
<svg width="600" height="300">
    <path d="M100,200
             C100,100 400,100 400,200
             S400,100 300,0"
    fill="none" stroke="#000" stroke-width="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.

1
2
3
4
5
6
<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" stroke-width="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.

1
2
3
4
5
<svg width="600" height="300">
    <path d="M100,200
             Q250,100 400,200"
     fill="none" stroke="#000" stroke-width="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.

1
2
3
4
5
6
<svg width="600" height="300">
  <path d="M100,200
           Q250,100 400,200
           T600 200"
    fill="none" stroke="#000" stroke-width="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.

1
A rx ry  x-axis-rotation  large-arc-flag  sweep-flag  x y

where

  • x,y is the end point for the arc
  • rx is the x-radius of the ellipse
  • ry is the y-radius of the ellipse
  • x-axis-rotation is the degrees to rotate the x-axis

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 x-axis-rotation, there are actually four possible arcs than can be drawn. This is easier to see with an example.

1
2
3
4
5
6
7
8
9
10
11
12
13
<svg width="600" height="300">
<path d="M250,100  A120,80 0 0,0 250,200"
    fill="none" stroke="red" stroke-width="5" />

<path d="M250,100  A120,80 0 1,1 250,200"
    fill="none" stroke="green" stroke-width="5"/>

<path d="M250,100  A120,80 0 1,0 250,200"
    fill="none" stroke="purple" stroke-width="5"/>

<path d="M250,100  A120,80 0 0,1 250,200"
    fill="none" stroke="blue" stroke-width="5"/>
</svg>

The example looks like two multi-colored 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 x-axis-rotation. 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 large-arc-flag and the sweep-flag. Consider the red and purple arcs. Both have a value of 0 for the sweep-flag. The red arc has a value of 0 for the large-arc-flag and the purple arc has a value of 1 for the same flag. They differ only in their values for the large-arc-flag.

Looking at the two arcs can you guess what the large-arc-flag 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 large-arc-flag, so both are the smaller arcs. Where red also has a value of 0 for the sweep-flag, 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 sweep-flag 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.

5 comments

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

  1. 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/path-element.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.

Leave a Reply

Your email address will not be published. Required fields are marked *