withZoom = {
const zoomExtent = [
[-20, -20],
[950, 320]
];
const vd = (d) => d.year;
const vLeft = (d) => d.sales;
const vRight = (d) => d.efficiency;
const sl = d3.scaleLinear();
const xDataExtent = d3.extent(cars, vd);
const yLeftDataExtent = d3.extent(cars, vLeft);
const yRightDataExtent = d3.extent(cars, vRight);
const renderPlot = (xDomain, yDomain, ticks) => {
const y2 = d3.scaleLinear(yRightDataExtent, yLeftDataExtent);
const marks = [
Plot.axisY(y2.ticks(ticks), {
color: "steelblue",
anchor: "right",
label: "efficiency (mpg)",
y: y2,
tickFormat: ".1f",
ticks
}),
Plot.lineY(cars, { x: "year", y: vLeft, tip: true }),
Plot.lineY(
cars,
Plot.mapY((d) => d.map(y2), {
x: "year",
y: vRight,
stroke: "steelblue",
tip: true
})
)
];
return Plot.plot({
width: 700,
height: 300,
x: { domain: xDomain, tickFormat: "", ticks: 10 },
y: {
axis: "left",
label: "sales (M)",
ticks: 10,
tickFormat: "s",
domain: yDomain
},
grid: true,
tooltip: true,
marks
});
};
const insertPlot = (xDomain, yDomain, ticks) => {
const chart = renderPlot(xDomain, yDomain, ticks);
div.html("").append(() => chart);
return [chart.scale("x"), chart.scale("y")];
};
const zoomed = (e) => {
const x = sl.domain(xScale.domain).range(xScale.range);
const xDomain = e.transform.rescaleX(x).domain();
const y = sl.domain(yScale.domain).range(yScale.range);
const yDomain = e.transform.rescaleY(y).domain();
const ticks = Math.round(10 * e.transform.k);
insertPlot(xDomain, yDomain, ticks);
};
const div = d3.create("div");
const [xScale, yScale, legend] = insertPlot(xDataExtent, yLeftDataExtent, 10);
const zoom = d3
.zoom()
.translateExtent(zoomExtent)
.scaleExtent([1, 10])
.on("zoom", zoomed);
div.call(zoom);
return div.node();
}