focus = {
const spec = {
width,
height: 360,
marks: [
Plot.areaY(aapl, {
x: "Date",
y: "Close",
fill: "steelblue",
clip: true
})
],
x: { type: "utc" }
};
let chart = Plot.plot(spec);
const wrapper = svg`<svg viewBox="${chart.getAttribute("viewBox")}">${chart}`;
const x = chart.scale("x");
const y = chart.scale("y");
let domain = x.domain;
const redraw = () =>
chart.replaceWith(
(chart = Plot.plot({ ...spec, x: { type: "utc", domain }, y }))
);
const X0 = d3.scaleUtc(x.domain, x.range);
const E = [[x.range[0], 0], [x.range[1], 0]];
const zoom = d3
.zoom()
.scaleExtent([1, 100])
.extent(E)
.translateExtent(E)
.on("zoom end", (event) => {
const { transform, sourceEvent } = event;
domain = transform.rescaleX(X0).domain();
redraw();
if (sourceEvent) dispatch.call("timeWindow", wrapper, domain);
});
d3.select(wrapper).call(zoom);
dispatch.on("timeWindow.details", function (value) {
if (this === wrapper) return;
domain = (value == null ? x.domain : value).slice();
d3.select(wrapper).call(
zoom.transform,
d3.zoomIdentity
.translate(x.range[0], 0)
.scale(
Math.min(100, (x.domain[1] - x.domain[0]) / (domain[1] - domain[0]))
)
.translate(-X0(domain[0]), 0)
);
});
return wrapper;
}