D3.js force limit panning

I am using d3.js with force layout to visualize a large number of nodes. I would like to apply a restriction to the zoom pan option. JSFiddle: https://jsfiddle.net/40z5tw8h/24/

The above script contains a simple version of what I'm working on. Since I would potentially have to visualize a very large dataset, I use the function to scale the group holding element ("g") after the forces are completed. Thus, I always have a complete visualization, visible afterwards.

I would like to limit the panning - when the graph is fully visible so that it can only be moved in the viewport. If the layout is enlarged, I would like to limit the pan as follows:

The group hold item must not go away:

  • down more than 20 pixels from the top of svg.
  • on the right is more than 20 px on the left side of svg.
  • above 20 pixels below svg.
  • more than 20 pixels left on the right side of svg.

I think the whole implementation should be in the scaling function, which at the moment:

function zoomed(){
        if (d3.event.sourceEvent == null){ //when fitFullGraph uses the zoom
            g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
        }
        else{
            var gElementBounds = g.node().getBoundingClientRect();
            var g_bottom = gElementBounds.bottom;
            var g_top = gElementBounds.top;
            var g_left = gElementBounds.left;
            var g_right = gElementBounds.right;
            var g_height = gElementBounds.height;
            var g_width = gElementBounds.width;

            var svg = g.node().parentElement;
            var svgElementBounds = svg.getBoundingClientRect();
            var svg_bottom = svgElementBounds.bottom;
            var svg_top = svgElementBounds.top;
            var svg_left = svgElementBounds.left;
            var svg_right = svgElementBounds.right;
            var svg_height = svgElementBounds.height;
            var svg_width = svgElementBounds.width;

            var t = d3.event.translate;
            var margin = 20;

            if(d3.event.sourceEvent.type == 'wheel'){//event is zoom
                g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");

            }
            else{//event is pan
                // if(t[0] < svg_left + margin) t[0]= svg_left + margin;
                //else if(t[0] > svg_width-g_width - margin) t[0] = svg_width-g_width - margin;
                // if(t[1] < g_height +margin) t[1] = g_height + margin;
                //else if (t[1] > svg_height - margin) t[1] = svg_height - margin;
               //.attr("transform", "translate(" + t+ ")scale(" + d3.event.scale + ")");
               //3.event.translate = t;
                g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
            }

        }

    }

The restrictions that I tried to implement are commented out because they do not work properly.

Anyone have a solution?

+1
source share
1 answer

.

X

var translate = d3.event.translate;
var translateX = translate[0];
var translateY = translate[1];
var scale = d3.event.scale;
var tX = translateX * scale;
var tY = translateY * scale;
console.log('tx', tX, 'ty', tY);
// Do not pan more to left
if (tX> 0) {
  g.attr("transform", "translate(" + d3.event.translate + ")  scale(" + d3.event.scale + ")");
} else {
  translate[0] = 0;
  g.attr("transform", "translate(" + translate + ")  scale(" + d3.event.scale + ")");
}

, . , , . , , .

0

Source: https://habr.com/ru/post/1648991/


All Articles