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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more