DEV Community

Jess
Jess

Posted on

Getting Started with the Canvas API: Lines and Rectangles

What is the Canvas API?

The Canvas API consists of methods and properties that enable you to draw graphics with JavaScript. These graphics can be used for a variety of things, such as animations and game sprites.

Setup

In order to draw on the canvas, you first need to create one in your html file.

<canvas id="my-canvas" height="600" width="800"></canvas>
Enter fullscreen mode Exit fullscreen mode

You don't have to specify a height and width here. If you don't it will default to 300w x 150h, but you can set the dimensions using JavaScript.

Now you can get a reference to the canvas element and drawing context. When you draw with canvas, the drawing surface is actually the drawing context. The canvas element is like a container or frame for the drawing context. This post focuses on the 2D context, but there is a 3D context as well.

const canvas = document.getElementById('my-canvas'); 
const drawingContext = canvas.getContext('2d');
Enter fullscreen mode Exit fullscreen mode

Rectangles

To draw a rectangle, you use the fillRect method along with fillStyle.

fillRect(x, y, width, height)

The x/y values are the starting point of the rectangle and width/height are the dimensions of the rectangle.

drawingContext.fillStyle = 'red';
drawingContext.fillRect(canvas.width/2 - 10, canvas.height/2 - 10, 20, 20);
Enter fullscreen mode Exit fullscreen mode
red 20x20px square in the center of the canvas A red 20x20px square in the center of the canvas

You can also create a rectangle with an outline that isn't filled in.

drawingContext.strokeStyle = 'purple';
drawingContext.strokeRect(canvas.width/2 - 10, canvas.height/2 - 10, 20, 20);
Enter fullscreen mode Exit fullscreen mode
20x20px purple outlined square in the center of the canvas A 20x20px purple outlined square in the center of the canvas

Lines

Lines are slightly more complex than rectangles because you have to specify where their paths begin and end.

beginPath() starts a new drawing path.

moveTo() begins a new sub-path at the specified x,y coordinates. In other words, it's where you will begin your line.

lineTo() is used to connect a straight line to the last point in the sub-path and specifies the x,y coordinates where you want your line to end.

strokeStyle sets the color of the line. (default: black)

lineWidth sets the width of the line. (default: 1)

stroke() is used to actually draw the line.

Here are 2 different lines: A horizontal 1px wide purple line and a 3px wide diagonal red line.

drawingContext.beginPath();
drawingContext.strokeStyle = 'purple';
drawingContext.moveTo(10,15);
drawingContext.lineTo(290,15)
drawingContext.stroke();

drawingContext.beginPath();
drawingContext.lineWidth = 3;
drawingContext.strokeStyle = 'red';
drawingContext.moveTo(10,30);
drawingContext.lineTo(200,90)
drawingContext.stroke();
Enter fullscreen mode Exit fullscreen mode
A 1px wide horizontal purple line and a 3px wide diagonal red line

If you don't begin a new path, both of these lines would be red because the previous sub-path would still be part of the current path, and when you call stroke() it would essentially paint over the purple line.

// Example without beginPath()

drawingContext.strokeStyle = 'purple';
drawingContext.moveTo(10,15);
drawingContext.lineTo(290,15)
drawingContext.stroke();

drawingContext.lineWidth = 3;
drawingContext.strokeStyle = 'red';
drawingContext.moveTo(10,30);
drawingContext.lineTo(200,90)
drawingContext.stroke();

Enter fullscreen mode Exit fullscreen mode
2 red lines Both lines are red because a new path wasn't created

In some instances you might want this behavior. For example, if for some reason you want to create a stroke through a previous bigger stroke while also creating a new stroke:

drawingContext.lineWidth = 60;
drawingContext.strokeStyle = 'blue';
drawingContext.moveTo(0, canvas.height/2);
drawingContext.lineTo(canvas.width, canvas.height/2);
drawingContext.stroke();

drawingContext.lineWidth = 10;
drawingContext.strokeStyle = 'red';
drawingContext.moveTo(0, canvas.height/2 + 20);
drawingContext.lineTo(canvas.width, canvas.height/2 + 20);
drawingContext.stroke();
Enter fullscreen mode Exit fullscreen mode
2 red 10px lines inside a 60px blue line 2 red lines are created inside the thicker blue line, even though I only created 1 red line.

Since I didn't begin a new path, when I created the 10px red line it stroked the new path as well as the previous path with a 10px red line.

Line Caps

There are 3 options to alter the look of the ends of your lines: butt, round, or square. butt ends are default; the ends are squared off at the endpoints. round ends are, well, rounded, and a semicircle is added to the ends of the line. square adds a box with an equal width and half the height of the lines thickness to the ends. butt is the only end that stops at the exact points you specify; the others extend beyond your specified endpoints.

// default
drawingContext.beginPath();
drawingContext.lineWidth = 20;
drawingContext.moveTo(20, 20);
drawingContext.lineTo(canvas.width-20, 20);
drawingContext.stroke();

// round 
drawingContext.beginPath();
drawingContext.lineCap = 'round';
drawingContext.lineWidth = 20;
drawingContext.moveTo(20, 50);
drawingContext.lineTo(canvas.width-20, 50);
drawingContext.stroke();

// square 
drawingContext.beginPath();
drawingContext.lineCap = 'square';
drawingContext.lineWidth = 20;
drawingContext.moveTo(20, 80);
drawingContext.lineTo(canvas.width-20, 80);
drawingContext.stroke();

Enter fullscreen mode Exit fullscreen mode
3 lines with different end caps In order from top to bottom: butt, round, square

Next up: Complex Shapes

Top comments (0)