Let’s take a deeper look at some of the other methods we can use to draw paths on the canvas, including arcs and curves that can be combined to create complex images.

There are four functions we can use to draw arcs and curves onto the canvas. An arc can be a complete circle or any part of a circle

context.arc(x, y, radius, startAngle, endAngle, anticlockwise)

The `x`

and `y`

values define the center of our circle,
and the `radius`

will be the radius
of the circle upon which our arc will be drawn. `startAngle`

and `endAngle`

are in radians, not degrees.
`anticlockwise`

is a `true`

or `false`

value that defines the direction of
the arc.

For example, if we want to draw a circle with a center point at
position 100,100 and with a radius of 20, as shown in Figure 2-4, we could use the code below for the
contents of `drawScreen()`

:

context.arc(100, 100, 20, (Math.PI/180)*0, (Math.PI/180)*360, false);

Example 2-4 illustrates the code necessary to create a simple circle.

Example 2-4. A circle arc

function drawScreen() { context.beginPath(); context.strokeStyle = "black"; context.lineWidth = 5; context.arc(100, 100, 20, (Math.PI/180)*0, (Math.PI/180)*360, false); //full circle context.stroke(); context.closePath(); }

Notice that we have to convert our start angle (`0`

) and our end angle (`360`

) into radians by multiplying them by
(`Math.PI/180`

). By using `0`

as the start angle and `360`

as the end, we create a full
circle.

We can also draw a segment of a circle by not specifying the
entire 0 to 360 start and stop angles. This code for `drawScreen()`

will create one-quarter of a
circle drawn clockwise, as shown in Figure 2-5:

context.arc(100, 200, 20, (Math.PI/180)*0, (Math.PI/180)*90, false);

If we want to draw everything *but* the 0–90
angle, as shown in Figure 2-6, we
can employ the `anticlockwise`

argument and set it to `true`

:

context.arc(100, 200, 20, (Math.PI/180)*0, (Math.PI/180)*90, true);

context.arcTo(x1, y1, x2, y2, radius)

The `arcTo`

method has only
been implemented in the latest browsers—perhaps because its
capabilities can be replicated by the `arc()`

function. It takes in a point
(`x1`

,`y1`

) and draws a straight line from the
current path position to this new position. Then it draws an arc from
that point to the `y1`

,`y2`

point using the given radius.

The `context.arcTo`

method will
work only if the current path has at least one subpath. So, let’s
start with a line from position 0,0 to position 100,200. Then we will
build our small arc. It will look a little like a bent wire coat
hanger (for lack of a better description), as shown in Figure 2-7:

context.moveTo(0,0); context.lineTo(100, 200); context.arcTo(350,350,100,100,20);

Bezier curves, which are far more flexible than arcs, come in both the cubic and quadratic types:

`context.`

`bezierCurveTo`

`(`

`cp1x, cp1y, cp2x, cp2y, x, y`

`)`

`context.`

`quadraticCurveTo`

`(`

`cpx, cpy, x, y`

`)`

The Bezier curve is defined in 2D space by a “start point,” an “end point,” and one or two “control” points, which determine how the curve will be constructed on the canvas. A normal cubic Bezier curve uses two points, while a quadric version uses a single point.

The quadratic version, shown in Figure 2-8, is the simplest, only needing the end point (last) and a single point in space to use as a control point (first):

context.moveTo(0,0); context.quadraticCurveTo(100,25,0,50);

This curve starts at `0,0`

and
ends at `0,50`

. The point in space we
use to create our arc is `100,25`

. This
point is roughly the center of the arc vertically. The `100`

value for the single control point pulls
the arc out to make an elongated curve.

The cubic Bezier curve offers more options because we have two control points to work with. The result is that curves—such as the classic “S” curve shown in Figure 2-9—are easier to make:

context.moveTo(150,0); context.bezierCurveTo(0,125,300,175,150,300);

Combining the `save()`

and
`restore()`

functions with the Canvas
clip region limits the drawing area for a path and its subpaths. We do
this by first setting `rect()`

to a
rectangle that encompasses the region we would like to draw in, and then
calling the `clip()`

function. This
will set the clip region to be the rectangle we defined with the
`rect()`

method call. Now, no matter
what we draw onto the current context, it will only display the portion
that is in this region. Think of this as a sort of mask that you can use
for your drawing operations. Example 2-5 shows how this works,
producing the clipped result shown in Figure 2-10.

Example 2-5. The Canvas clipping region

function drawScreen() { //draw a big box on the screen context.fillStyle = "black"; context.fillRect(10, 10, 200, 200); context.save(); context.beginPath(); //clip the canvas to a 50×50 square starting at 0,0 context.rect(0, 0, 50, 50); context.clip(); //red circle context.beginPath(); context.strokeStyle = "red"; //need list of available colors context.lineWidth = 5; context.arc(100, 100, 100, (Math.PI/180)*0, (Math.PI/180)*360, false); //full circle context.stroke(); context.closePath(); context.restore(); //reclip to the entire canvas context.beginPath(); context.rect(0, 0, 500, 500); context.clip(); //draw a blue line that is not clipped context.beginPath(); context.strokeStyle = "blue"; //need list of available colors context.lineWidth = 5; context.arc(100, 100, 50, (Math.PI/180)*0, (Math.PI/180)*360, false); //full circle context.stroke(); context.closePath(); }

Example 2-5 first draws a
large 200×200 black rectangle onto the canvas. Next, we set our Canvas
clipping region to `rect(0,0,50,50)`

.
The `clip()`

call then clips the canvas
to those specifications. When we draw our full red circle arc, we only
see the portion inside this rectangle. Finally, we set the clipping
region back to `rect(0,0,500,500)`

and
draw a new blue circle. This time, we can see the entire circle on the
canvas.

Start Free Trial

No credit card required