2015-09-25 74 views
2

我已經創建了一些基本節點和鏈接,用D3創建一個有向圖。我已經在我的拖動功能上設置了一些基本的邏輯,這樣當一個節點被拖動時,它將返回到它原來的起始位置。這很好,直到我把它們連在一起。如何讓鏈中的所有節點在dragend之後返回原來的位置?D3強制定向佈局+所有節點到原始位置

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

    .Properties{ 
     fill: yellow; 
     stroke: black; 
     stroke-width: 2px; 
    } 
    .link { 
    stroke: #777; 
    stroke-width: 2px; 
    } 


</style> 
<body> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> 
<script> 
     //Most of these variables are just used to calculate original position 
     var width = 960, height = 500, colors = d3.scale.category10(); 
     var svg = null, force = null; 
     var circle = null, path = null; 
     var nodes = null, links = null; 
     var nodesArray = null, linkArray = null; 
     var count = 0; 
     var element = "body"; var numEdges = 4, numNodes = 5; 
     var i = 0; var L = 16, r = 12, lineLimit = 10; 
     var d = 2 * r + L; 
     var R = (count - 1) * d; 
     var m = width/2; 
     var X; 

     svg = d3.selectAll(element).append('svg').attr('width', width).attr('height', height); 

     //Load nodes and links original positions 
     nodes = d3.range(numNodes).map(function() { 
      X = m - (R/2) + (i * d); 
      ++i; 
      return { 
       x: X, 
       y: (height)/3, 
       fx: X, 
       fy: height/3, 
       id: i-1, 
       reflexive: true, 
       r: 12 
      };   
     }); 
     for (var i = 0; i < numNodes; ++i) { 
      d3.select(element).append("h3").text("Node " + i + ": " + nodes[i].id); 
     } 

     i = -1; 
     links = d3.range(numEdges).map(function() { 
      i++; 
      return { 
       // 
       source: nodes[i], 
       target: nodes[i+1], 
       left: false, 
       right: true 
      } 
     }); 
     for (var i = 0; i < numEdges; ++i) { 
      d3.select(element).append("h3").text("Source: " + links[i].source.id + " Target: " + links[i].target.id); 
     } 

     force = d3.layout.force().size([width, height]).nodes(nodes).links(links).linkDistance(40).linkStrength(0.1).charge(-300); 
     var drag = force.drag() 
        .on('dragstart', dragstart) 
        .on('drag', drag) 
        .on('dragend', dragend); 
     linkArray = svg.selectAll('.link').data(links).enter().append('line').attr('class', 'link') 
      .attr('x1', function (d) { 
       return nodes[d.source.id].x; 
      }) 
      .attr('y1', function (d) { return nodes[d.source.id].y; }) 
      .attr('x2', function (d) { return nodes[d.target.id].x; }) 
      .attr('y2', function (d) { return nodes[d.target.id].y; }); 


     var circleGroup = svg.selectAll("g").data(nodes); 
     var groupEnter = circleGroup.enter().append("g").attr("transform", function(d){return "translate("+[d.x,d.y]+")";}).call(drag); 
     var circle = groupEnter.append("circle").attr("cx", 0).attr("cy", -4).attr("r", function(d){return d.r;}).attr("class", "Properties"); 
     var label = circleGroup.append("text").text(function(d){return d.id;}).attr({"alignment-baseline": "middle", "text-anchor": "middle" }).attr("class", "id");  


     force.on('tick', tick); 
     force.start(); 
     var originalPosition = []; 
     function dragstart(d) { 
      originalPosition[0] = d.x; 
      originalPosition[1] = d.y; 
      console.log("Start: ", originalPosition[0], originalPosition[1]); 
     } 
     function drag() { 
      var m = d3.mouse(this); 
      d3.select(this) 
        .attr('cx', m[0]) 
        .attr('cy', m[1]); 
     } 

     function dragend(d) { 
      console.log("End: ", d.x, d.y); 
      d3.select(this).transition().attr('cx', originalPosition[0]).attr('cy', originalPosition[1]); 
     } 

     function tick() { 

      circleGroup.attr('transform', function(d) { 
       return 'translate(' + d.x + ',' + d.y + ')'; 
      }); 

      linkArray 
       .attr('x1', function (d) { return d.source.x; }) 
       .attr('y1', function (d) { return d.source.y; }) 
       .attr('x2', function (d) { return d.target.x; }) 
       .attr('y2', function (d) { return d.target.y; }); 

     } 

</script> 

回答

2

我做了這樣的事情上拖拽開始保持原有的圖形數據的這樣的克隆:

function dragstart(d) { 
    clone1 = JSON.parse(JSON.stringify(graph)); 
} 

上拖動結束時,我複製存儲克隆X/Y/PX/PY屬性回在圖節點,使其返回到老位置是這樣的:

function dragend(d) { 
    clone1.nodes.forEach(function(n,i){ 
     graph.nodes[i].px=n.px 
     graph.nodes[i].py=n.py 
     graph.nodes[i].x=n.x 
     graph.nodes[i].y=n.y 
    }); 
} 

工作代碼here

相關問題