0

I want to drag and zoom the force layout in the bound. Please check this link Here the Node are centered in the layout but how can i drag inside the bound. I even tried some thing like this

nodes.attr("cx", function(d) {
     return d.x = Math.max(60, Math.min($(window).width() - 60, d.x));
 })
 .attr("cy", function(d) {
     return d.y = Math.max(60, Math.min($(window).height() - 60, d.y));
 });

But it doesn't work out.

Gilsha
  • 14,431
  • 3
  • 32
  • 47
ferozcoder
  • 454
  • 5
  • 18

2 Answers2

0

Done :

node.attr("transform", function(d) {
        //Here i create a node radius so it doesnt go offscreen
        var nodeRadius = d.weight * 2 + 12

        //here I do checks to see if it goes offscreen
        if(d.x<= nodeRadius){
           d.x = nodeRadius;
           }
        if(d.y<= nodeRadius){
           d.y = nodeRadius;
           }7
        if(d.x>width - nodeRadius){
           d.x = width - nodeRadius;
           }
        if(d.y>height - nodeRadius){
           d.y = height - nodeRadius;
           }

        return "translate(" + d.x + "," + d.y + ")";

    });

This is done in the tick function, so it checks every frame. I created an actual tick function so it's reusable. Please check my changes in your JSFiddle as I've made quite a few. But everything seems to work fine.

Updated fiddle : http://jsfiddle.net/aVhd8/177/

If you want to move the nodes before it starts then the boundary has to remember that movement :

node.attr("transform", function(d) {
        //Here i create a node radius so it doesnt go offscreen
        var nodeRadius = d.weight * 2 + 12

        //here I do checks to see if it goes offscreen
        if(d.x<= nodeRadius-movement){ //have to take movement away as you have moved the nodes/links previously
           d.x = nodeRadius-movement;
           }
        if(d.y<= nodeRadius){
           d.y = nodeRadius;
           }
        if(d.x>width - nodeRadius-movement){
           d.x = width - nodeRadius-movement;
           }
        if(d.y>height - nodeRadius){
           d.y = height - nodeRadius;
           }

        return "translate(" + d.x + "," + d.y + ")";

    });

Notice here I have took movement into account. You also need to do the same for the links:

JSFiddle : http://jsfiddle.net/aVhd8/180/

AJ_91
  • 581
  • 4
  • 16
  • HI AJ you are genius :) . But what happen when i place the node in the center. Hope you remember in the given link ---http://jsfiddle.net/fekkyDev/aVhd8/174/ – ferozcoder Apr 08 '15 at 04:43
  • Done, all you needed to do is take the movement variable into account. I can't stress enough the fact you need to understand what your code is doing. I've noticed you've been asking questions on here which are fairly simple if you think about what the logic is doing. Here for example, you want to move you nodes at the start ? So you put in a translate function. But your boundary in your tick function works from that point the node is at not thinking about the previous translate. Hope this helps :) – AJ_91 Apr 08 '15 at 08:30
  • Sorry ive just reread the question.@Rouby just uncomment the zoom call on the SVG then you will be able to zoom/pan. Problem with this though is when you pan you alter the view of the force layout so the boundary's created in the tick function are off as youve moved your SVG. You can get around this by just scaling when calling the zoom rather than scaling and translating. Another problem with this is scale doesnt come into play in your boundaries : http://jsfiddle.net/aVhd8/182/. Or if you want to use pan + zoom youll have to adjust the boundary with the scale + translate values – AJ_91 Apr 08 '15 at 08:58
  • Hey AJ you did it again. Thank You :) – ferozcoder Apr 08 '15 at 11:27
0

Take a look at this : http://bl.ocks.org/mbostock/6123708

In that example Mike implemented the zoom behavior alongside a drag/drop behavior.

Jonathan
  • 3,614
  • 3
  • 21
  • 30