# Hexagons are the Bestagons (JS edition) · Part one

As we all know, Hexagons are the Bestagons - we see them in honeycombs, they are in snowflakes and pencils, there’s one on Saturn, and they are... *(math incoming)* the only regular polygon to tile a plane without resorting to debasing self-divison 😅.

When I started rebuilding my website, I knew I wanted a live, configurable background and it quickly became clear it’ll be rendered on a **canvas**. I was playing around, drawing various 2D shapes, when I remembered the CGP Grey video - hexagons... The Bestagons were the obvious choice!

In this series of tutorials I’ll show you how I built this background.

## Part one: how to render a hexagon?

OK, so how do we render a regular hexagon? We want to draw 6 straight lines of equal length. To form a hexagon, the angle between every two sides has to be 120°.

Let’s explore our options for drawing stuff on a canvas. Here's some API methods from CanvasRenderingContext2D, the interface from the Canvas API that we use to draw in two dimensions:

- arc() - creates a circular arc. Hexagons only have straight walls,
`arc`

is definitely not our thing; - ellipse() - creates an ellipse. Same as above, cool, but not for us;
- rect() - adds a rectangle to the current path. Finally, some straight lines. Still won’t work for us though - rectangles are obviously the inferior choice... and we can't really draw a hex using a full reactangle;
- lineTo() - adds a straight line to the current sub-path. This is our thing!

Unfortunately, there doesn’t seem to be anything more convenient in the API. No `fillHex()`

function yet 🙄. We’ll have to draw our hexagons line by line.

So, let’s take a look at the `lineTo()`

method - it accepts an `x`

and a `y`

coordinate. Here’s the example from MDN:

```
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.beginPath(); // Start a new path
ctx.moveTo(30, 50); // Move the pen to (30, 50)
ctx.lineTo(150, 100); // Draw a line to (150, 100)
ctx.stroke(); // Render the path
```

OK, so in order to draw a hex, we need to figure out the coordinates of all its vertices.

## Computing the vertices

Let’s give the vertices of our future Hex names - A, B, C, D, E, F:

And let’s say we start from vertex A. Our code will then look something like this:

```
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.beginPath(); // Start a new path
ctx.moveTo(vertexA.x, vertexA.y); // move the pen to vertex A
ctx.lineTo(vertexB.x, vertexB.y); // draw a line from A to B
ctx.lineTo(vertexC.x, vertexC.y); // draw a line from B to C
ctx.lineTo(vertexD.x, vertexD.y); // draw a line from C to D
ctx.lineTo(vertexE.x, vertexE.y); // draw a line from D to E
ctx.lineTo(vertexF.x, vertexF.y); // draw a line from E to F
ctx.lineTo(vertexA.x, vertexA.y); // ...and finally, from F to A to finish the hex
ctx.closePath();
ctx.stroke(); // Render the path
```

The next question we have to answer is - if vertex A has coordinates `(0, 0)`

, where is vertex B?

First, we need to define the length of our hex’s side. Let’s hardcode it to `10px`

. Then, figure out where B is.

Let’s call the coordinates of A `(ax, by)`

, and of B `(bx, by)`

. We draw a line between A and C and the height of the ABC triangle - BH.

We can now see that:

`bx == ax + length(AH)`

- B is straight on top of H, so`bx`

is the same as the`x`

coordinate of H (`hx`

); H is`length(AH)`

away from A, so`hx`

is`ax + length(AH)`

`by == ay - length(BH)`

- B is`length(BH)`

away from H, so`by = hy - length(BH)`

; and because A and H are on the same`y`

→`hy`

is the same as`ay`

.

If we find the lengths of AH and BH, we’re good to go. To find them, we need a bit of math “magic”:

`∠AHB`

is**90°**.`∠ABH`

is half of`∠ABC`

, so it’s**60°**, therefore`∠HAB`

is 180 - (90 + 60) =**30°**.- From trigonometry, we know that
`length(AH) = cos(∠HAB) * length(AB)`

, and`length(BH) = sin(∠AHB) * length(AB)`

Let's call the length of AB `hexSide`

, then:

`length(AH) = cos(30°) * hexSide`

`length(BH) = sin(30°) * hexSide`

## Math over!

We’re mostly done with the math. Back to code!

```
const COS_30 = Math.cos(Math.PI / 6);
const SIN_30 = Math.sin(Math.PI / 6);
const hexSide: number = 10; // the side of our hex is hardcoded to 10px
// Note: in real life, lacking the diagram above, `AH` means nothing.
// I would keep this as `COS_30 * hexSide` or try to give a more
// meaningful name.
const AH = COS_30 * hexSide;
const BH = SIN_30 * hexSide;
const vertexA = { x: 0, y: 0 };
const vertexB = { x: vertexA.x + AH, y: vertexA.y - BH };
```

And we have our vertex B!

At this point I suggest you pause for a bit and try to figure out the coordinates of C, D, E, and F. Use what we already know - the coordinates of A and B, `hexSide`

, `AH`

, and `BH`

.

Here’s the solution:

```
const vertexA = { x: 0, y: 0 };
const vertexB = { x: vertexA.x + AH, y: vertexA.y - BH };
const vertexC = { x: vertexB.x + AH, y: vertexA.y };
const vertexD = { x: vertexC.x, y: vertexC.y + hexSide };
const vertexE = { x: vertexB.x, y: vertexD.y + BH };
const vertexF = { x: vertexA.x, y: vertexD.y };
```

So, now that we have all vertex coordinates, we're finally ready to render our hexagon:

```
<html>
<body>
<canvas id="canvas"></canvas>
<script>
const COS_30 = Math.cos(Math.PI / 6);
const SIN_30 = Math.sin(Math.PI / 6);
// Coords of our first vertex.
const start = { x: 100, y: 100 };
// Length of our hex's side.
const hexSide = 100;
// Find or create a canvas.
const canvas = document.querySelector('#canvas');
canvas.width = 400;
canvas.height = 400;
const ctx = canvas.getContext('2d');
// Compute the vertices (same as above).
const vertexA = start;
const vertexB = {
x: vertexA.x + hexSide * COS_30,
y: vertexA.y - hexSide * SIN_30
};
const vertexC = { x: vertexB.x + hexSide * COS_30, y: vertexA.y };
const vertexD = { x: vertexC.x, y: vertexC.y + hexSide };
const vertexE = { x: vertexB.x, y: vertexD.y + hexSide * SIN_30 };
const vertexF = { x: vertexA.x, y: vertexA.y + hexSide };
// List all vertices. Remember - we have to `lineTo()` to vertex A to
// finish the hex.
const vertices = [
vertexA, vertexB, vertexC,
vertexD, vertexE, vertexF, vertexA
];
// Begin a new sub-path at vertex0.
ctx.moveTo(vertices[0].x, vertices[0].y);
ctx.beginPath();
// Add line to the sub-path from each vertex to the next one.
vertices.forEach(({ x, y }) => ctx.lineTo(x, y));
// End the sub-path.
ctx.closePath();
// Set the stroke color for our hex.
ctx.strokeStyle = 'rgb(0, 0, 0)';
// And finally, our Bestagon:
ctx.stroke();
</script>
</body>
</html>
```

And the outcome is:

This is it for Part one! Thank you for reading!

In Part two we will continue with rendering multiple hexes on a grid. Stay tuned 😉