Nomadic cattle rustler and inventor of the electric lasso.

Company Website**Follow me on twitter**

Contact me for frontend answers.

September 06, 2018

I am writing this because I could not find anything adequate in my interweb searches for how to draw a hexagon using a svg polygon

What I wanted to do was create an svg polygon in the guise of a react component. I wanted to supply a size property and the component would magically know how to create the coordinates that can be used for the points attribute of the polygon.

In the figure above, the angles `a`

, `b`

, `c`

, `d`

,`e`

and `f`

are the *central angles* of a hexagon. The number of central angles of a polygon is always the same as the number of sides.

As you can see above all the central angles of the polygon will always form a complete circle. Hence the central angles will always add up to 360∘. Since a regular polygon has all equal sides, then the central angles of the polygon are equal.

To find the central angles of a polygon:

- First identify the number of sides
`n`

. - Then divide by 360∘.

The central angle of a hexagon is therefore 60∘

I create coordinates at 0, 60, 120, 180, 240 and 360 and the `<polygon />`

component will join the vertices to create a hexagon.

I can use the trigonometry functions of `cos`

and `sin`

to get a coordinate or point if I know the **central angle** of the polygon and the length of each side of the polygon. `cosine`

can give me the `x`

coordinate and `sine`

can give me the `y`

coordinate.

Armed with this knowledge I can now work out the points by just knowing the length of a side and an optional central `point`

object that gives me a starting position to place the `polygon`

.

```
export const getPoints = (
hexagonType: HexagonType,
size: number,
center: Point
): Point[] => {
return [0, 1, 2, 3, 4, 5].map((n) => {
const turnHexagon = hexagonType === HexagonType.pointy ? 30 : 0;
const degrees = 60 _ n - turnHexagon;
const radians = (Math.PI / 180) _ degrees;
return new Point({
x: center.x + size * Math.cos(radians),
y: center.y + size * Math.sin(radians)
});
});
};
```

The function takes a `HexagonType`

typescript enum as an argument and on **line 3**, I create a `turnHexagon`

variable that adds an offset (or not) to have the hexagon positioned with a point:

or flat

Line 4 - `const degrees = 60 * n - turnHexagon;`

will give the angle of the next central angle for each coordinate by increasing the angle by 60∘ each time.

Line 5 - `const radians = (Math.PI / 180) * degrees;`

converts degrees into radians. `Math.cos`

and `Math.sin`

expect the argument to be in radians and not degrees. I initially got this wrong.

The code below will work out the `x`

and `y`

coordinates of each of the six points.

```
return new Point({
x: center.x + size _ Math.cos(radians),
y: center.y + size _ Math.sin(radians)
});
```

I ended up creating a PR for the excellent VX library which was accepted and my `<Polygon />`

is now part of the @vx/shape package with a demo here.

Here is a jsfiddle with a plain js version and below is the react component in it’s entirety:

```
import * as React from 'react';
import { range } from 'lodash';
import { Point } from '../../model/point';
import { degreesToRadians } from '../../util/trigonometry';
export enum HexagonType {
flat = 'flat',
pointy = 'pointy'
}
export interface HexagonProps {
size: number;
hexagonType?: HexagonType;
center?: Point;
className?: string;
}
export const getPoints = (hexagonType: HexagonType, size: number, center: Point): Point[] => {
return range(0, 6).map((n) => {
const turnHexagon = hexagonType === HexagonType.pointy ? 30 : 0;
const degrees = 60 \* n - turnHexagon;
const radians = degreesToRadians(degrees);
return new Point({
x: center.x + size * Math.cos(radians),
y: center.y + size * Math.sin(radians)
});
});
};
export const Hexagon: React.SFC<HexagonProps> = ({
hexagonType = HexagonType.pointy,
size = 25,
center = new Point({ x: 0, y: 0 }),
className
}) => {
const points = getPoints(hexagonType, size, center)
.map((p) => p.toArray())
.join(' ');
return <polygon points={points} className={className} />;
};
```

Nomadic cattle rustler and inventor of the electric lasso.

Company Website**Follow me on twitter**

Contact me for frontend answers.

- ← Narrowing a union type in typescript and a gotcha with callbacks
- SVG transformations with affine matrices →