Graphing Data to a Canvas
Tags: javascript
Published: 2021-01-17 00:49:13

Let's say we have a data structure similar to the following, and we want to graph each set of data for a visual comparison.

```javascript
const dataSets = [
    {
        color: "#00f",
        data: [5,10,25,15,20]
    },
    {
        color: "#f00",
        data: [0,20,15,25,10]
    }
];
```

I'll assume we have a reference to a canvas and context throughout this example. If you want to learn more about this, you can take a look at my previous entry [here](https://dev.to/brandonmweaver/introduction-to-the-html5-canvas-348a).

What will we need in order to create a visual representation of these two sets?

First, we'll need to find the highest and lowest value among all sets.

```javascript
let yHigh = Number.MIN_VALUE;
let yLow = Number.MAX_VALUE;
for (const dataSet of dataSets) {
    for (const datum of dataset.data) {
        if (datum > yHigh) yHigh = datum;
        if (datum < yLow) yLow = datum;
    }
}
```

Next, we'll need to iterate over each set and figure out the x, and y-axis of each initial value as it relates to our canvas.

The x-axis is easy enough, as it's simply 0. We will, however, also need to divide the canvas width by one less than our set length (since the first value of x will be 0), and add this value to x as we draw the set.

```javascript
for (const dataSet of dataSets) {
    let x = 0;
    const xStep = canvas.width / (dataSet.data.length - 1);

    ...
```

Now, we need to figure out the y value; this involves finding the percentage of each value between the highest and lowest values, and setting y to the value of that percentage relative to our canvas height.

```javascript
    ...

    let yPercentage = (dataSet.data[0] - yLow) / (yHigh - yLow) * 100;
    let y = canvas.height - canvas.height / 100 * yPercentage;

    ...
```

Notice that we're also subtracting the value of `yLow` from the datum before calculating the percentage; this ensures that, if our lowest value is 10, and our canvas height is 100, our lowest value will be drawn to 100 on the canvas, rather than 90. Without this subtraction our data will be drawn to the canvas as if the lowest value is 0. We also subtract our y value from the canvas height to prevent our graph from being inverted since we're drawing the low datum on what is technically high on the canvas.

We'll set `strokeStyle` of our context to the sets color, and call `beginPath` to prevent our lines from being redrawn using the last stroke style.

```javascript
    ...

    context.strokeStyle = dataSet.color;
    context.beginPath();

    ...
```

Next, we simply iterate over the data, starting from the second index (since we already have the first point), stepping along the x-axis by adding the value of `xStep` to x, and finding y for each datum just as we did with the first.

```javascript
    ...

    for (let i = 1; i < dataSet.data.length; i++) {
        context.moveTo(x, y);
        x += xStep;

        yPercentage = (dataSet.data[i] - yLow) / (yHigh - yLow) * 100;
        y = canvas.height - canvas.height / 100 * yPercentage;

        context.lineTo(x, y);
        context.stroke();
    }
}
```

Below is a nearly identical example I made, which uses the resize event of the window to allow the canvas to fill its container by setting the width and height to the offset width and height, and redrawing the data.

{% codepen https://codepen.io/brandonmweaver/pen/ExgGGNP %}