### Paul Cowan

Nomadic cattle rustler and inventor of the electric lasso.
Company Website

# React hexagon component

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.

## Hexagon Maths

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:

1. First identify the number of sides n.
2. 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.

## Show me the code

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

## @VX

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.

## Code

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;

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