Public
Edited
Jul 27, 2023
Insert cell
Insert cell
selection
Insert cell
viewof selection = {
const svg = d3
.create("svg")
.attr("height", height)
.attr("width", width)
.attr("style", "border: 1px solid black;");

const brush = d3
.brushX()
.on("start brush end", brushed)
.on("end.snap", brushended);

/** Bands **/
const bar = svg
.append("g")
.attr("stroke", "#fafafa")
.attr("fill", "steelblue")
.attr("fill-opacity", "0.3")
.selectAll("rect")
.data(barsScale.domain())
.join("rect")
.attr("x", (d) => barsScale(d) - barsScale.step() / 2)
.attr("height", height)
.attr("width", barsScale.step());

svg
.append("g")
.selectAll("text")
.data(data)
.join("text")
.attr("style", "fill: black; font-size: 8px; text-anchor: middle;")
.attr("x", (d, i) => barsScale(i))
.attr("y", height / 2)
.attr("dy", "1em")
.text((d) => d);

/** org data + band scale **/
svg
.append("g")
.selectAll("circle")
.data(data)
.join("circle")
.attr("style", "fill: black")
.attr("cx", (d, i) => i * barsScale.step() + barsScale.step() / 2)
.attr("cy", (d) => y(d))
.attr("r", 2);

svg
.append("g")
.append("path")
.attr("style", "fill: none; stroke: black;")
.attr("d", () => lineBand(data));

svg.append("g").call(brush);
function brushed({ selection }) {
if (selection) {
const range = barsScale.domain().map(barsScale);
const i0 = d3.bisectRight(range, selection[0]);
const i1 = d3.bisectRight(range, selection[1]);
bar.attr("fill", (d, i) => (i0 <= i && i < i1 ? "orange" : null));
svg.property("value", data.slice(i0, i1)).dispatch("input");
} else {
bar.attr("fill", null);
svg.property("value", []).dispatch("input");
}
}

function brushended({ selection, sourceEvent }) {
if (!sourceEvent || !selection) return;
const range = barsScale.domain().map(barsScale),
dx = barsScale.step() / 2;
const x0 = range[d3.bisectRight(range, selection[0])] - dx;
const x1 = range[d3.bisectRight(range, selection[1]) - 1] + dx;
d3.select(this)
.transition()
.call(brush.move, x1 > x0 ? [x0, x1] : null);
}

return svg.property("value", []).node();
}
Insert cell
y = d3.scaleLinear().domain(d3.extent(data)).range([0, height])
Insert cell
x = d3
.scaleLinear()
.domain([0, data.length - 1])
.range([0, width])
Insert cell
barsScale = d3
.scalePoint()
.domain(
Array(data.length)
.fill(0)
.map((d, i) => i)
)
.range([0, width])
.padding(0.5)
Insert cell
data = penguins
.map((d) => d.body_mass_g)
.filter((d) => !isNaN(d))
.slice(0, 20)
Insert cell
line = d3
.line()
.x((d, i) => x(i))
.y((d) => y(d))
Insert cell
lineBand = d3
.line()
.x((d, i) => i * barsScale.step() + barsScale.step() / 2)
.y((d) => y(d))
Insert cell
height = 200
Insert cell
width = 800
Insert cell
d3 = require("d3@6")
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