As mentioned in the other answer, I know this is a very old post but hopefully the following will help someone…
I made a pen that I think hits all the requirements mentioned. As I didn’t have a real API to use, I created some data using a json-generator (great tool), included it, and sorted it in descending order. Then I use the built in slice
and concat
methods to take bits of the array, data
, and add to the chart_data
variable (similarly to how one might use an api).
Important Sections:
Once you’ve created your scales, axes, and points (lines, bars, etc.), you need to create the zoom behavior. As mentioned in the question, keeping the scaleExtent limited to the same number on both sides prevents zooming:
var pan = d3.behavior.zoom()
.x(x_scale)
.scale(scale)
.size([width, height])
.scaleExtent([scale, scale])
.on('zoom', function(e) { ... });
Now that we’ve created the behavior, we need to call it. I’m also calculating what the x translation will be for this moment in time, now
, and programmatically panning there:
// Apply the behavior
viz.call(pan);
// Now that we've scaled in, find the farthest point that
// we'll allow users to pan forward in time (to the right)
max_translate_x = width - x_scale(new Date(now));
viz.call(pan.translate([max_translate_x, 0]).event);
Both preventing the user from scrolling past now and loading more data is all done in the zoom event handler:
...
.scaleExtent([scale, scale])
.on('zoom', function(e) {
var current_domain = x_scale.domain(),
current_max = current_domain[1].getTime();
// If we go past the max (i.e. now), reset translate to the max
if (current_max > now)
pan.translate([max_translate_x, 0]);
// Update the data & points once user hits the point where current data ends
if (pan.translate()[0] > min_translate_x) {
updateData();
addNewPoints();
}
// Redraw any components defined by the x axis
x_axis.call(x_axis_generator);
circles.attr('cx', function(d) {
return x_scale(new Date(d.registered));
});
});
The other functions are pretty straightforward and can be found at the bottom of the pen. I’m not aware of any built in D3 function to prevent panning past the present but I’m definitely open to feedback if I’ve missed an easier way to do some of this.
Let me know if you have trouble viewing the pen or need clarification on something. If I have time I’ll update this with another version demoing an infinite scrolling line chart.
P.S. In the pen, I’m consoling out the selection and data as they update. I suggest opening the console to see exactly what’s happening.