Published
Edited
Jun 30, 2020
1 star
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
svg.append("g")
.call(yAxis);
svg.append("g")
.selectAll("circle")
.data(dodge(data, radius * 2 + padding))
.join("circle")
.attr("cx", d => margin.left + radius + padding + d.x)
.attr("cy", d => d.y)
.attr("r", radius)
.append("title")
.text(d => `${d.data.name} (${d.data.value})`);

return svg.node();
}
Insert cell
dodge = (data, radius) => {
const radius2 = radius ** 2;
const circles = data.map(d => ({y: y(d.value), data: d})).sort((a, b) => a.y - b.y);
const epsilon = 1e-3;
let head = null, tail = null;
// Returns true if circle ⟨x,y⟩ intersects with any circle in the queue.
function intersects(x, y) {
let a = head;
while (a) {
if (radius2 - epsilon > (a.x - x) ** 2 + (a.y - y) ** 2) {
return true;
}
a = a.next;
}
return false;
}

// Place each circle sequentially.
for (const b of circles) {

// Remove circles from the queue that can’t intersect the new circle b.
while (head && head.y < b.y - radius2) head = head.next;

// Choose the minimum non-intersecting tangent.
if (intersects(b.x = 0, b.y)) {
let a = head;
b.x = Infinity;
do {
let x = a.x + Math.sqrt(radius2 - (a.y - b.y) ** 2);
if (x < b.x && !intersects(x, b.y)) b.x = x;
a = a.next;
} while (a);
}

// Add b to the queue.
b.next = null;
if (head === null) head = tail = b;
else tail = tail.next = b;
}

return circles;
}
Insert cell
data = d3.csvParse(await FileAttachment("cars-2.csv").text(), ({Name: name, Weight_in_lbs: value}) => ({name, value: +value}))
Insert cell
y = d3.scaleLinear()
.domain(d3.extent(data, d => d.value))
.range([height - margin.bottom, margin.top])
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).tickSizeOuter(0))
Insert cell
height = 600
Insert cell
radius = 3
Insert cell
padding = 1.5
Insert cell
margin = ({top: 20, right: 20, bottom: 30, left: 40})
Insert cell
d3 = require("d3@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