Getting Started with the Canvas API: Complex Shapes
Tags: html, javascript
Published: 2020-10-05 19:55:03

---
title: Getting Started with the Canvas API: Complex Shapes
published: true
description: Create complex shapes with canvas api
tags: html5, javascript
series: Canvas API
//cover_image: https://direct_url_to_image.jpg
---

In Part 1 of [*Getting Started with the Canvas API*](https://dev.to/robotspacefish/getting-started-with-the-canvas-api-lines-and-squares-db7) I went over the basics of creating lines and rectangles. Here I'm going to discuss creating more complex shapes.

First, I'm going to create a 300x300 canvas element and get a reference to it in JavaScript.

```
<canvas id="canvas" height="300" width="300"></canvas>
```

```
const ctx = document.getElementById('canvas').getContext('2d');
```

## Connecting Lines
As I explained in Part I, you can create lines by beginning a path (using `beginPath()`), plotting the x,y values of the beginning and end of your line using the `moveTo()` and `lineTo()` methods, and creating the line `stroke()`. You can actually continue plotting points for your line before creating the stroke.

When `lineTo()` is used, it creates an x,y end point for the line. When it is used again along the same path, the line extends from the previous end point.

```
ctx.lineWidth = 3; // just making it a little more visible
ctx.beginPath();
ctx.moveTo(20,20);
ctx.lineTo(20,100);
ctx.lineTo(100,100);
ctx.lineTo(20,200);
ctx.lineTo(100,200);
ctx.lineTo(200, 20);
ctx.lineTo(200, 200);
ctx.stroke();
```

<center>
	<img src="https://github.com/robotspacefish/blog-photos/blob/master/canvas_basics/continuous-line.png?raw=true
" alt="A line zig-zagging in different directions">
</center>


### Triangles

In order to create a closed shape, you can create a `lineTo()` back to the starting point. 

```
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(ctx.canvas.width/2, 20);
ctx.lineTo(20, ctx.canvas.height - 20);
ctx.lineTo(ctx.canvas.width - 20, ctx.canvas.height - 20);
ctx.lineTo(ctx.canvas.width/2,20);
ctx.stroke();
```

<center>
	<img src="https://github.com/robotspacefish/blog-photos/blob/master/canvas_basics/triangle-1.png?raw=true
" alt="outline of a triangle with a disjointed connection">
</center>

But ew, what's going on here?

<center>
	<img src="https://github.com/robotspacefish/blog-photos/blob/master/canvas_basics/triangle-1b.png?raw=true
" alt="An outline of a triangle with the top disjointed connection circled">
</center>

You can fix this by changing the `fillCap` of your line, but then it doesn't quite match the other pivot points.

```
ctx.fillCap = 'round';
```

<center>
	<img src="https://github.com/robotspacefish/blog-photos/blob/master/canvas_basics/triangle-1-rounded.png?raw=true
" alt="An outline of a triangle with the top connection rounded">
</center>

Instead of changing the `fillCap`, here's a better option:

Use `closePath()` in place of the final `lineTo()` point connection and it will automatically connect those points neatly.

```
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(ctx.canvas.width/2, 20);
ctx.lineTo(20, ctx.canvas.height - 20);
ctx.lineTo(ctx.canvas.width - 20, ctx.canvas.height - 20);
ctx.closePath(); // <--- replaced the final lineTo with closePath
ctx.stroke();
```

<center>
	<img src="https://github.com/robotspacefish/blog-photos/blob/master/canvas_basics/triangle-2-closed-path.png?raw=true
" alt="An outline of a triangle with each segment connection point matching">
</center>

## Line Joins
There are also `lineJoin` options to style your segment connections: `bevel`, `miter`, and `round`. `round` rounds off the corners, `miter` joins the outside edges of the line segments to a single point and is the default, and `bevel` fills the endpoint of the connected line segments and flattens it off.

<center>
	<img src="https://github.com/robotspacefish/blog-photos/blob/master/canvas_basics/lineJoins.png?raw=true" alt="A red filled triangle with black outline">
</center>

## Filling Shapes

You can fill in the shape by using `fillStyle` and `fill()`.

```
ctx.fillStyle = 'red'; < --- set the color
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(ctx.canvas.width/2, 20);
ctx.lineTo(20, ctx.canvas.height - 20);
ctx.lineTo(ctx.canvas.width - 20, ctx.canvas.height - 20);
ctx.fill(); < --- fill the shape
ctx.closePath();
ctx.stroke();
```

<center>
	<img src="https://github.com/robotspacefish/blog-photos/blob/master/canvas_basics/triangle-3-filled.png?raw=true" alt="A red filled triangle with black outline">
</center>

Order matters here. If you `fill()` after `stroke()`, the outline will appear thinner because the fill is on top.

```
ctx.fillStyle = 'red';
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(ctx.canvas.width/2, 20);
ctx.lineTo(20, ctx.canvas.height - 20);
ctx.lineTo(ctx.canvas.width - 20, ctx.canvas.height - 20);
ctx.closePath();
ctx.stroke();
ctx.fill(); < --- fill the shape after creating the stroke

```

<center>
	<img src="https://github.com/robotspacefish/blog-photos/blob/master/canvas_basics/triangle-3-filled-after.png?raw=true" alt="A red filled triangle with black outline">
</center>