Jess F

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>
``````
``````const ctx = document.getElementById('canvas').getContext('2d');
``````

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)
``````

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.fill();
ctx.stroke();
``````

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))
``````

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.

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);
``````

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();
``````

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();
``````

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