Public
Edited
Nov 14, 2023
1 star
Insert cell
Insert cell
whratio = 6
Insert cell
context = {
return canvas.getContext("2d");
}
Insert cell
canvas = {
const canvas = d3
.create("canvas")
.attr("width", width)
.attr("height", height)
.node();
const context = canvas.getContext("2d");
//const context = DOM.context2d(width, height);
context.fillStyle = "black";
//context.fillRect(0, 0, width, height);
context.font = "bold 120px Helvetica";
context.fillText("Dot density maps", 10, 100);
return canvas;
}
Insert cell
context.getImageData(80, 80, 1, 1).data
Insert cell
viewof radius = Inputs.range([0.2, 5], {
value: 2,
step: 0.2,
label: "Dot radius"
})
Insert cell
{
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("width", width)
.attr("height", height);

let circles = svg
.selectAll("circle")
.data(points)
.enter()
.filter((d) => {
let x = Math.floor(d[0] * width),
y = Math.floor(d[1] * width);
var data = context.getImageData(x, y, 1, 1).data;
var rgb = [data[0], data[1], data[2]];
//console.log(x, y, rgb);
return data[3] !== 0;
})
.append("circle")
.attr("cx", (d) => d[0] * width)
.attr("cy", (d) => d[1] * width)
.attr("r", radius)
.attr("fill", (d) => dotColour(d[0]));

return svg.node();
}
Insert cell
height = width / whratio
Insert cell
width = 1050
Insert cell
count = 8500
Insert cell
points = makePoints(count)
Insert cell
function makePoints(count, numCandidates = 100) {
const pt = [Math.random(), Math.random()]; // First point
const points = [pt];
const qt = d3
.quadtree()
.extent([
[0, 0],
[1, 1 / whratio]
])
.add(pt);

while (points.length < count) {
points.push(sample(qt, numCandidates));
}
return points;
}
Insert cell
function sample(qt, numCandidates) {
var bestCandidate,
bestDistance = 0;
for (var i = 0; i < numCandidates; ++i) {
var c = [Math.random(), Math.random() / whratio], // New candidate point
d = distance(qt.find(...c), c); // Distance from closest point
if (d > bestDistance) {
bestDistance = d;
bestCandidate = c;
}
}
qt.add(bestCandidate);
return bestCandidate;
}
Insert cell
function distance(a, b) {
var dx = a[0] - b[0],
dy = a[1] - b[1];
return dx * dx + dy * dy; // Technically the distance is sqrt of this
}
Insert cell
function dotColour(t) {
return Math.random() < 0.1
? interpolateRainbow(t + 0.15)
: interpolateRainbow(t);
}
Insert cell
// https://observablehq.com/@mbostock/sinebow
function interpolateRainbow(t) {
return (
(t = (t + 0.2) % 1),
d3.cubehelix(
360 * t - 100,
1.5 - 1.5 * Math.abs(t - 0.5),
0.8 - 0.9 * Math.abs(t - 0.5)
)
);
}
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