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);
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);
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();
}