Signal Plot III (zoom)
This interactive line chart visualizes accelerometer readings across x, y, and z axes, with a focus on zooming and panning along the time axis. The chart, rendered as SVG with D3 v4, plots data from a CSV file and extends an earlier version by adding d3.zoom functionality for granular inspection while preserving line highlighting and tooltip interactions. Users can zoom up to 50x, with the transformation rescaling the x-domain and redrawing paths and axes in real time.
AI-generated descriptionSignal Plot III
Line chart that displays three dimensions of data taken from an accelerometer. This example is designed to implement zooming, while still maintaining the highlighting and tooltips from <a href='http://bl.ocks.org/lwthatcher/1ecdd35bdf2c96630bf98112ec0344a1'>Signal Plot II</a>.
Zooming
The chart uses d3.zoom to implement zooming and panning for the x-axis. Adding the zoom can be done with relatively few steps:
Create the Zoom Behavior:
// setup zoom
var zoom = d3.zoom()
.scaleExtent([1, 50])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
The callback function zoomed will also need to be defined. Below shows the callback for rescaling only in the x dimension, as well as redrawing the x-axis:
function zoomed() {
var t = d3.event.transform;
x.domain(t.rescaleX(x0).domain());
dims.forEach(dim => {
var selector = ".line--" + dim;
svg.select(selector)
.attr("d", lines[dim]);
});
svg.select(".axis--x").call(d3.axisBottom(x));
}
Note how the x0 scale is also needed for a point of reference:
var x0 = d3.scaleLinear().range([0, width]);
...
x0.domain(x.domain());
Create the Zoom Portal:
// create zoom portal in background
var rect = svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
Note: Make sure that this section goes after the zoom behavior definition, but before drawing any of the lines or axes. This will position the zoom portal in the back, allowing the highlighting and tooltip events to still propagate.
Add the Clip-Path:
// Create clip-path
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
Styling:
Make sure that zoom portal accepts pointer-events, and that the lines use the clip-path.
.zoom {
fill: none;
cursor: move;
pointer-events: all;
}
.line {
fill: none;
opacity: 0.9;
stroke-width: 1.5px;
clip-path: url(#clip);
}
Set initial zoom/position: (optional)
This little snippet sets the initial zoom to x2 and sets the position to the start of the data:
// Set initial zoom/position
zoom.scaleBy(rect, 2);
zoom.translateBy(rect, width);
Note: The order matters here: scale then translate.
Highlighting:
Highlighting follows a pattern inspired by <a href='http://bl.ocks.org/lwthatcher/'>lwthatcher</a>'s block: <a href='http://bl.ocks.org/lwthatcher/a6c886b1081857a7198807617f183283'>Multi y-axis with mouseover</a>, where when a line is moused-over the line is highlighted, while other lines are dimmed.
Tooltips:
The tooltips are implemented based off of <a href='http://bl.ocks.org/d3noob/'>d3noob</a>'s block: <a href='http://bl.ocks.org/d3noob/257c360b3650b9f0a52dd8257d7a2d73'>Simple tooltips in v4</a>, with some additional css styling changes.
Built with blockbuilder.org
forked from <a href='http://bl.ocks.org/lwthatcher/'>lwthatcher</a>'s block: <a href='http://bl.ocks.org/lwthatcher/94c246de1032f09b32742edfc30c54b1'>Signal Plot I</a>
forked from <a href='http://bl.ocks.org/lwthatcher/'>lwthatcher</a>'s block: <a href='http://bl.ocks.org/lwthatcher/1ecdd35bdf2c96630bf98112ec0344a1'>Signal Plot II (highlighting + tooltips)</a>
forked from <a href='http://bl.ocks.org/lwthatcher/'>lwthatcher</a>'s block: <a href='http://bl.ocks.org/lwthatcher/d6eb019c470bf3c9ca6df94213a111a0'>Signal Plot III (zoom)</a>