Jammer
Jammer

Reputation: 10208

d3 v2 Prevent Zooming and Panning Chart Outside Viewport

I've been looking at all the examples I can find that deal with this and I've been trying to get this to work with my chart with no success so far.

I have the chart panning and zooming behaviour working but at the moment I can pan and zoom the contents of the chart well outside the bounds of the viewport.

You can see a demo of this in this fiddle:

http://jsfiddle.net/Jammer/wvL422zq/

All I'm trying to do is prevent the extremes of data being scrolled completely out of view and their appears to be so many completely different examples of getting this to work that I'm struggling to get the method that will work for my chart.

The Panning and Zooming is handled with this at the moment:

var zoom = d3.behavior.zoom()
    .x(x)
    .scaleExtent([1, 30])
    .scale(2)
    .on("zoom", function () {
        svg.select(".x.axis").call(xAxis);
        svg.selectAll("path.lines")
           .attr("d", function(d) { return line(d.values); });
        svg.selectAll("circle")           
           .attr("cx", function(d) { return x(d.date); })                              
           .attr("cy", function(d) { return y(d.value); });
    });

A lot of the examples out there appear to be for older or newer versions of d3 as well.

How do I prevent the chart contents from being zoomed or panned out of the viewport?

Upvotes: 1

Views: 1523

Answers (1)

Peter Ambruzs
Peter Ambruzs

Reputation: 8213

You can restrict the panning in the zoom function. I only done on one side. You might want to use the scale for the other side. I leave it to you. Here is my solution. Edit: I done the other side also. It was tricky.

    var zoom = d3.behavior.zoom()
        .x(x)
        .scaleExtent([1, 30])
        .scale(2)
        .on("zoom", function () {
            var panX = d3.event.translate[0];
            var panY = d3.event.translate[1];
            var scale = d3.event.scale;

            panX = panX > 10 ? 10 : panX;
            var maxX = -(scale-1)*width-10;
            panX = panX < maxX ? maxX : panX;
            zoom.translate([panX, panY]);
            console.log("x: "+panX+" scale: "+scale);
            //console.log("x: "+(panX/scale));

            svg.select(".x.axis").call(xAxis);
            svg.selectAll("path.lines")
                .attr("d", function(d) { return line(d.values); });
            svg.selectAll("circle")           
                .attr("cx", function(d) { return x(d.date); })                              
                .attr("cy", function(d) { return y(d.value); });
        });

Upvotes: 2

Related Questions