delayChart = {
const predicates = {
dist: (d) => true,
hour: (d) => true,
date: (d) => true,
delay: (d) => true
};
function getSpec(data) {
return {
height: height,
y: {
grid: true,
tickFormat: "~s"
},
x: {
label: "Arrival delay (min) →",
domain: delayScaleDomain
},
marks: [
Plot.rectY(
data,
Plot.binX(
{ y: "count" },
{
x: (d) => delay(d),
thresholds: 80
}
)
),
Plot.ruleY([0])
]
};
}
let chart = Plot.plot(getSpec(data));
const x = chart.scale("x"),
[x1, x2] = x.range;
const y = chart.scale("y"),
[y1, y2] = y.range;
let domain = x.domain;
const wrapper = svg`<svg viewBox="${chart.getAttribute("viewBox")}">${chart}`;
const redraw = function () {
chart.replaceWith(
(chart = Plot.plot(
getSpec(
data.filter((d) => combinePredicates(...Object.values(predicates))(d))
)
))
);
};
const brush = d3
.brushX()
.extent([
[x1, y2],
[x2, y1]
])
.on("brush end", (event) => {
const { selection, sourceEvent } = event;
domain = selection && selection.map(x.invert);
if (sourceEvent) dispatch.call("delayBrush", wrapper, domain);
});
d3.select(wrapper).call(brush);
dispatch.on("distBrush.delay", function (domain) {
predicates.dist =
domain === null ? (d) => true : (d) => inDomain(d.distance, domain);
redraw();
});
dispatch.on("hourBrush.delay", function (domain) {
predicates.hour =
domain === null ? (d) => true : (d) => inDomain(hour(d), domain);
redraw();
});
dispatch.on("dateBrush.delay", function (domain) {
predicates.date =
domain === null ? (d) => true : (d) => inDomain(d.date, domain);
redraw();
});
return wrapper;
}