Published
Edited
Sep 27, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const t = performance.now();

// Clear pixels
cg.clear([1, 1, 1, 1]);

const { xs, ys, colors } = data;

const hexagons = candygraph.createShapes(cg, hexagon, xs, ys, {
colors,
scales: [radius * dpr, radius * dpr]
});

const hexagonBorders = candygraph.createShapes(cg, hexagonBorder, xs, ys, {
colors: [0, 0, 0, 0.1],
scales: [radius * dpr, radius * dpr]
});

// Render axes and hexbins
cg.render(coords, viewport, [grid, hexagons, hexagonBorders, xAxis, yAxis]);

// Copy rendered image to the canvas element
cg.copyTo(viewport, canvas);

const dt = performance.now() - t;

yield `Rendering took ${d3.format(".0f")(dt)} msec`;
}
Insert cell
hexagon = {
const x = Math.sqrt(0.75);
yield candygraph.createDataset(
cg,
// prettier-ignore
[
// right-top
0, 1, x, 0.5, 0, 0,
// right-middle
x, 0.5, x, -0.5, 0, 0,
// right-bottom
x, -0.5, 0, -1, 0, 0,
// left-bottom
0, -1, -x, -0.5, 0, 0,
// left-middle
-x, -0.5, -x, 0.5, 0, 0,
// left-top
-x, 0.5, 0, 1, 0, 0,
]
);
}
Insert cell
hexagonBorder = {
const w = borderWidth / radius;

const v =
borderAlign === "inner" ? 1 : borderAlign === "outer" ? 1 + w : 1 + w / 2;
const vI = v - w;

const h = v / 2;
const hI = h - w / 2;

const x = Math.sqrt(v ** 2 - h ** 2);
const xI = Math.sqrt(vI ** 2 - hI ** 2);

const top = [0, v];
const topInner = [0, vI];
const rightTop = [x, h];
const rightTopInner = [xI, hI];
const rightBottom = [x, -h];
const rightBottomInner = [xI, -hI];
const bottom = [0, -v];
const bottomInner = [0, -vI];
const leftBottom = [-x, -h];
const leftBottomInner = [-xI, -hI];
const leftTop = [-x, h];
const leftTopInner = [-xI, hI];

yield candygraph.createDataset(
cg,
// prettier-ignore
[
// right-top
...top, ...rightTopInner, ...topInner,
...top, ...rightTop, ...rightTopInner,
// right-middle
...rightTop, ...rightBottomInner, ...rightTopInner,
...rightTop, ...rightBottom, ...rightBottomInner,
// right-bottom
...rightBottom, ...bottomInner, ...rightBottomInner,
...rightBottom, ...bottom, ...bottomInner,
// left-bottom
...bottom, ...leftBottomInner, ...bottomInner,
...bottom, ...leftBottom, ...leftBottomInner,
// left-middle
...leftBottom, ...leftTopInner, ...leftBottomInner,
...leftBottom, ...leftTop, ...leftTopInner,
// left-top
...leftTop, ...topInner, ...leftTopInner,
...leftTop, ...top, ...topInner,
]
);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = {
yield bins.reduce(
(out, bin) => {
out.xs.push(bin.x);
out.ys.push(bin.y);
out.colors.push(...rgbStringToNormRgba(color(bin.length)));
return out;
},
{ xs: [], ys: [], colors: [] }
);
}
Insert cell
hexbin = d3.hexbin()
.x(d => x(d.x))
.y(d => y(d.y))
.radius(radius * width / (height - 1))
.extent([[margin.left, margin.top], [width - margin.right, height - margin.bottom]])
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more