DEV Community

Jess
Jess

Posted on

Getting Started with the Canvas API: Arcs

CanvasRenderingContext2d.arc() is a method used to create a circle, or a curved segment of a circle.

Let's grab a reference to our 300x300 canvas:

<canvas id="canvas" height="300" width="300"></canvas>
Enter fullscreen mode Exit fullscreen mode
const ctx = document.getElementById('canvas').getContext('2d');
Enter fullscreen mode Exit fullscreen mode

In order to create an arc, you need the x,y coordinate of the arc's center, the radius, the starting angle, the ending angle, and the optional anticlockwise boolean value (default false).

ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise)
Enter fullscreen mode Exit fullscreen mode

This seems simple enough. To create a full circle, your start angle would be 0 and your end angle would be 2*Math.PI, or if you prefer degrees to radians, 360*(Math.PI/180). You can omit a value for anticlockwise since it's a full circle and it doesn't matter whether it's true or false.

This creates a grey circle with a 3px black border in the center of the canvas. I created grid lines so it's easier to see what's going on.

const radius = 40;

ctx.lineWidth = 3;
ctx.strokeStyle = 'black';
ctx.fillStyle = 'grey';

ctx.beginPath();
ctx.arc(canvas.width/2, canvas.height/2, radius, 0, 2*Math.PI)

ctx.fill();
ctx.stroke();
Enter fullscreen mode Exit fullscreen mode
centered circle

I found creating arcs a little confusing at first and I'll explain why. Take 90° for example:

ctx.arc(50, 90, 40, 0, 90*(Math.PI/180))
Enter fullscreen mode Exit fullscreen mode

I expected the arc to match up with the 90° on the unit circle in the positive y direction but instead it arcs down into the negative y direction. I know the direction it's moving is clockwise and 0 is the starting point, but I still thought it would move clockwise along an invisible circle from 0 to 90°, and fill in the arc between 90° and 0. I'm thinking it creates the arc opposite to what I expect because with HTML Canvas the top of the grid is the negative y direction and the bottom is the positive y direction. If you have a better understanding, please leave a comment.

What I expected the 90 degree arc to be What the 90 degree arc actually is
unit circle

Here are some more examples so you can see different degrees clockwise and counterclockwise. Pretend each arc is created separately, using ctx.beginPath() and ctx.stroke() for each one as shown in the first example. For the image, I also created a point (which is just a mini filled-in arc) in the center x,y of each arc and changed the strokeStyle (color) of each one so it's easier to visualize.

// clockwise
no need for anticlockwise value since false is default
ctx.arc(50, 90, 40, 0, 90*(Math.PI/180));
ctx.arc(150, 90, 40, 0, 180*(Math.PI/180));
ctx.arc(250, 90, 40, 0, 270*(Math.PI/180));
ctx.arc(50, 90, 210, 0, 360*(Math.PI/180));

// counterclockwise - same as above except anticlockwise is true
ctx.arc(50, 90, 40, 0, 90*(Math.PI/180), true);
ctx.arc(150, 90, 40, 0, 180*(Math.PI/180), true);
ctx.arc(250, 90, 40, 0, 270*(Math.PI/180), true);
ctx.arc(50, 90, 210, 0, 360*(Math.PI/180), true);
Enter fullscreen mode Exit fullscreen mode
90, 180, 270, and 360 degree arcs clockwise 90, 180, 270, and 360 degree arcs counterclockwise

You can also use closePath() to connect the endpoints:

// 90deg example
ctx.beginPath();
ctx.arc(50, 90, 40, 0, 90*(Math.PI/180));
ctx.closePath();
ctx.stroke();
Enter fullscreen mode Exit fullscreen mode
closed path arcs

You can fill in the arcs:

// 90deg example
ctx.beginPath();
ctx.arc(50, 90, 40, 0, 90*(Math.PI/180));
ctx.closePath();
ctx.fill();
ctx.stroke();
Enter fullscreen mode Exit fullscreen mode
closed path arcs

Hopefully this is helpful to someone else who may not have understood why they weren't getting the results they might have expected.

Top comments (0)