Using paths in Canvas
We've seen how powerful D3 is for transforming a dataset into an SVG path
. For example, give it a radius and angle, and it can easily generate an arc path.
But how can we use this same data to draw the shape with canvas? Letβs explore.
Remember the area chart?
Before we start using canvas, let's remind quickly how to build an area chart with react and d3.
Everything starts with a dataset.
const data = [
{x:1, y: 90},
{x: 2, y: 12},
{x: 3, y: 34},
{x: 4, y: 53},
{x: 5, y: 98},
]
Then, d3.area()
is used to create an area generator. This generator (called areaBuilder
below) transforms a blob of data into a string
that can be used as the d
argument of a path
SVG shape.
// create a shape generator.
// areaBuilder will be a function that takes data as input and returns a SVG path
const areaBuilder = d3
.area()
.x(d => xScale(d.x))
.y1(d => yScale(d.y))
.y0(yScale(0));
// call the function with the dataset
const areaPath = areaBuilder(data);
// M0,0 L57.778,277.333 L115.556,199.111 ... Z
The output areaPath
can now be passed to a path
SVG element!
<path d={areaPath} fill="#9a6fb0" />
It results in a cool area chart:
A very basic area chart made using react and the area()
function of d3.js
π The Problem
D3 does an amazing job here! It transforms our dataset into a string like M0,0 L57,277 L115,199 ... Z
, which we can directly pass to an SVG path
element. π
But how can we use this path data to draw on a canvas instead of SVG?
Path2D
to the rescue! πΎ
Luckily, there's a lifesaving feature in the Canvas API: Path2D.
Path2D
allows you to take any SVG path string and easily draw it on the canvas. It simplifies the process considerably:
// areaPath is computed with d3: M0,0 L57.778,277.333 L115.556,199.111 ... Z
// Then in the useEffect:
const ctx = canvas.getContext('2d');
const path = new Path2D(areaPath); // Convert to Path2D
ctx.fill(path); // Now you can fill or stroke the path
Let's see it in action on a full chart:
A minimal area chart made in canvas thanks to d3.area()
and Path2D
Too easy!
That makes it a breeze!
Let's try on a donut chart to see if it works the same:
A minimal donut chart made in canvas