Published
Edited
Feb 22, 2022
3 stars
Insert cell
Insert cell
ditheredHeatmap(values, { width, px, extent: [0, 1] })
Insert cell
Insert cell
ditheredHeatmap = (values, { width, px = 1, ...options }) => {
const [lo, hi] = d3.extent(values);
const r = 1 / (hi - lo);
return heatmap(
values.map((d, i) => {
const x = Math.floor((i % width) / px);
const y = Math.floor(Math.floor(i / width) / px);
if (px > 1) d = values[(x + y * width) * px]; // note: the image looks much nicer without this line!
return interleavedGradientNoise(x, y) < (d - lo) * r;
}),
{ width, ...options }
);
}
Insert cell
values = Float64Array.from({ length: width * height }, (_, i) => {
const x = (i % width) / width,
y = Math.floor(i / width) / width;
return (
Math.cos(145 * x * x * x * x - 400 * x * y + 300 * y * y) /
(2 + Math.sin(115 * y * y - 25 * x * x))
);
})
Insert cell
import { heatmap } from "@fil/heatmap"
Insert cell
// Extracted from the great notebook by Job van der Zwan
// https://observablehq.com/@jobleonard/pseudo-blue-noise
function interleavedGradientNoise(x, y) {
// http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
// https://bartwronski.com/2016/10/30/dithering-part-three-real-world-2d-quantization-dithering/
const v = 52.9829189 * (0.06711056 * x + 0.00583715 * y);
return v - Math.floor(v);
}
Insert cell
height = 500
Insert cell
Insert cell
heatmap(values, { width })
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