Published
Edited
Aug 27, 2020
5 forks
12 stars
Insert cell
Insert cell
selection
Insert cell
viewof selection = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

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

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

svg.append("g")
.attr("font-family", "var(--sans-serif)")
.attr("text-anchor", "middle")
.attr("transform", `translate(${x.bandwidth() / 2},${height / 2})`)
.selectAll("text")
.data(x.domain())
.join("text")
.attr("x", d => x(d))
.attr("dy", "0.35em")
.text(d => d);

svg.append("g")
.call(brush);

function brushed({selection}) {
if (selection) {
const range = x.domain().map(x);
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", x.domain().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 = x.domain().map(x), dx = x.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
x = d3.scalePoint()
.domain(["XXS", "XS", "S", "M", "L", "XL", "XXL"])
.range([0, width])
.padding(0.5)
Insert cell
height = 60
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