d3js Node&行拖动,缩放工作正常,但平移所有图形 - 正在晃动

时间:2014-10-22 07:16:30

标签: json d3.js drag

我尝试通过d3js可视化网络图 - 以json文件的形式加载它,使用简单的视图函数 - 拖动节点,缩放整个图形和全景图。前两个功能工作正常,但全景...如果我做全图(特别是,当我慢慢地)时 - 所有图片都在颤抖。节点拖动足够顺畅。

这是我的代码:

<html>
  <title>dynamic JSON Data</title>
<body id="posts-show">



  <header class="post title">

 </header>

    <style scoped></style>
    <style>
svg {
  vertical-align: middle;
  background: rgba(255,255,255, 0.2);
  box-shadow: inset 0 0 3px 0px #CECECE;
}

svg circle {
       fill: #AFF;
        stroke: steelblue;
        stroke-width: 2px;
  cursor: pointer;
}


svg line {
  stroke-width: 2px;
  stroke: #79A32B;
  fill: transparent;
  cursor: pointer;
}

text {
  font: 10px sans-serif;
  pointer-events: none;
}


svg circle:active {
  stroke: #45D3C7;
       fill: #AAA;
}
.action-button {
  border-radius: 2px;
  border: 1px solid #19380D;
  padding: 3px 12px;
  background-color: rgba(175, 209, 183, 0.6);
}

.action-button:active {
  box-shadow: inset 0 0 3px 0px #868686;
}

.action-button.destroy {
  border: 1px solid #863636;
  background-color: rgba(197, 86, 86, 0.6);
}


</style>
<script src="d3.js" type="text/javascript"></script>
<script>
var xFn = function(d) { return d.x }
var yFn = function(d) { return d.y }
</script>
<div id="demo" style="text-align: center;">
</div>
<script>


d3.json("Graph_source.json", function(json) {

var zoom = d3.behavior.zoom()
    .scaleExtent([-5, 20])
    .on("zoom", zoomed);

function zoomed() {
  g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
};

function dragstarted(d) {
  d3.event.sourceEvent.stopPropagation();
  d3.select(this).classed("dragging", true);
};

function dragended(d) {
  d3.select(this).classed("dragging", false);
};


    var canvas_size = json['canvas'];
    var nodes_list = json['nodes'];
    var links_list = json['edges'];
    var width = canvas_size[0].width;
    var height = canvas_size[0].height;

var drag2 = d3.behavior.drag()
    .origin(function(d) { return d; })
    .on("dragstart", dragstarted)
    .on('drag', function (d,i) {
        g.attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
    console.log(d.id + ";" + d.x + ";" + d.y + ";")
    })
    .on("dragend", dragended);

var svg = d3.select("#demo").append("svg")
    .attr("width", width)
    .attr("height", height)


var g = svg.append("g")
    .attr("transform", "translate(" + 0 + "," + 0 + ")")
    .call(zoom)
    .call(drag2);

var rect = g.append("rect")
    .attr("class", "background")
    .attr("width", width)
    .attr("height", height) 
    .style("fill", "none")
    .style("pointer-events", "all");



    /* Define the data for the circles */
    var nodes = g.selectAll("g")
        .data(nodes_list)


    /* Define the data for the lines */
    var links = g.selectAll("link").data(links_list)


 /* var xScale = d3.scale.linear()
    .range([50, 750])
    .domain(d3.extent(nodes_list, xFn));

  var yScale = d3.scale.linear()
    .range([50, 550])
    .domain(d3.extent(nodes_list, yFn));*/



var drag = d3.behavior.drag()
    .origin(function(d) { return d; })
    .on("dragstart", dragstarted)
    .on('drag', function (d,i) {
        d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
    console.log(d.id + ";" + d.x + ";" + d.y + ";")
        d3.select(this).attr("transform", function (d, i) {
            return "translate(" + [d.x,d.y] + ")";

        })
    links
        .attr("x1", function(d) { return get_node_x(d.source); })
        .attr("y1", function(d) { return get_node_y(d.source); })
        .attr("x2", function(d) { return get_node_x(d.target); })
        .attr("y2", function(d) { return get_node_y(d.target); });

    })
    .on("dragend", dragended);




function get_node_x(search_key)
{

    for (var i = 0; i < nodes_list.length; i++) 
    {
        if(search_key.localeCompare(nodes_list[i].id) == 0)
            {
            return nodes_list[i].x;
            }
    }

};


function get_node_y(search_key)
{

    for (var i = 0; i < nodes_list.length; i++) 
    {
        if(search_key.localeCompare(nodes_list[i].id) == 0)
            {
            return nodes_list[i].y;
            }
    }

};



    links.enter()
        .append("line")
        .attr("class", "link")
        .attr("x1", function(d) { return get_node_x(d.source); })
        .attr("y1", function(d) { return get_node_y(d.source); })
        .attr("x2", function(d) { return get_node_x(d.target); })
        .attr("y2", function(d) { return get_node_y(d.target); });



    /*Create and place the "blocks" containing the circle and the text */  
    var elemEnter = nodes.enter()
        .append("g")
         .attr("transform", function(d){return "translate("+ d.x +","+ d.y +")"})
     .on("mouseover", function(d) {      
        console.log(d.id + ";" + d.x + ";" + d.x + ";" + d3.event.dx + ";" + d.y + ";" + d.y + ";" + d3.event.dy + ";")
     }) 
    .call(drag);




    /*Create the circle for each block */
    var circle = elemEnter.append("circle")
        .attr("r", 10)




    /* Create the text for each block */
    elemEnter.append("text")
        .attr("text-anchor", "middle")
        .text(function(d){return d.label});



  console.log(json);
  console.log(svg);


});






</script>
</body>
</html> 

和源文件Graph_source.json:

{
"canvas":[
    {"width": 721, "height": 352}
    ],
    "nodes":[
    {"id": "MPLS-BH-01", "label": "MPLS-BH-01" , "Host_IP": "10.158.20.3" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 396 , "y": 60 },
    {"id": "MPLS-BH-02", "label": "BH-02" , "Host_IP": "10.158.20.6" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 192 , "y": 292 },
    {"id": "MPLS-BH-03", "label": "BH-03" , "Host_IP": "10.158.20.4" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 601 , "y": 93 },
    {"id": "MPLS-BH-04", "label": "BH-04" , "Host_IP": "10.158.20.5" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 333 , "y": 291 },
    {"id": "MPLS-BH-05", "label": "BH-05" , "Host_IP": "10.158.20.1" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 121 , "y": 191 },
    {"id": "MPLS-BH-06", "label": "BH-06" , "Host_IP": "10.158.20.2" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 241 , "y": 67 }
    ],
"edges":[
    {"source": "MPLS-BH-02", "target": "MPLS-BH-04", "weight": "1.0" , "Host_A": "MPLS-BH-02" , "Interface_A": "GigabitEthernet1/2/0" , "Host_B": "MPLS-BH-04" , "Interface_B": "GigabitEthernet1/2/1" , "BW": "100" },
    {"source": "MPLS-BH-03", "target": "MPLS-BH-04", "weight": "1.0" , "Host_A": "MPLS-BH-03" , "Interface_A": "GigabitEthernet1/2/1" , "Host_B": "MPLS-BH-04" , "Interface_B": "GigabitEthernet1/2/0" , "BW": "100" },
    {"source": "MPLS-BH-05", "target": "MPLS-BH-06", "weight": "1.0" , "Host_A": "MPLS-BH-05" , "Interface_A": "GigabitEthernet2/0/0" , "Host_B": "MPLS-BH-06" , "Interface_B": "GigabitEthernet2/0/0" , "BW": "100" }  
    ]

}

2 个答案:

答案 0 :(得分:1)

在包含的组元素上调用缩放,但实际上会转换包含的组元素。

var gContainer = svg.append("g");
  .attr("transform", "translate(" + 0 + "," + 0 + ")")
  .call(zoom)

var g = gContainer.append("g")


// the following stays the same
function zoomed() {
   g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
};

答案 1 :(得分:0)

我花了大约两天时间来解决摇晃问题。请参阅Plunker。 http://plnkr.co/edit/D6JU88?p=preview

<html>
  <title>dynamic JSON Data</title>
<body id="posts-show">

  <header class="post title">

 </header>

    <style scoped></style>
    <style>
svg {
  vertical-align: middle;
  background: rgba(255,255,255, 0.2);
  box-shadow: inset 0 0 3px 0px #CECECE;
}

svg circle {
       fill: #AFF;
        stroke: steelblue;
        stroke-width: 2px;
  cursor: pointer;
}


svg line {
  stroke-width: 2px;
  stroke: #79A32B;
  fill: transparent;
  cursor: pointer;
}

text {
  font: 10px sans-serif;
  pointer-events: none;
}


svg circle:active {
  stroke: #45D3C7;
       fill: #AAA;
}
.action-button {
  border-radius: 2px;
  border: 1px solid #19380D;
  padding: 3px 12px;
  background-color: rgba(175, 209, 183, 0.6);
}

.action-button:active {
  box-shadow: inset 0 0 3px 0px #868686;
}

.action-button.destroy {
  border: 1px solid #863636;
  background-color: rgba(197, 86, 86, 0.6);
}


</style>
  <script src="http://d3js.org/d3.v3.js"></script>
<script>
  var xFn = function(d) { return d.x }
  var yFn = function(d) { return d.y }
</script>
<div id="demo" style="text-align: center;">
</div>
<script>


d3.json("Graph_source.json", function(json) {

  var canvas_size = json['canvas'];
  var nodes_list = json['nodes'];
  var links_list = json['edges'];
  var width = canvas_size[0].width;
  var height = canvas_size[0].height;

  var zoom = d3.behavior.zoom()
      .scaleExtent([-5, 20])
      .size([width,height])
      .on("zoom", zoomed);

  function zoomed() {
    container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
  };

  function dragstarted(d) {
    d3.event.sourceEvent.stopPropagation();
    // d3.select(this).classed("dragging", true);
  };

  function dragended(d) {
    // d3.select(this).classed("dragging", false);
  };

var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + 0 + "," + 0 + ")")
  .call(zoom);

var rect = svg.append("rect")
  .attr("width", width)
  .attr("height", height)
  .style("fill", "none")
  .style("pointer-events", "all");

var container = svg.append("g");



      /* Define the data for the circles */
      var nodes = container.selectAll("g")
          .data(nodes_list)


      /* Define the data for the lines */
      var links = container.selectAll("link").data(links_list)


   /* var xScale = d3.scale.linear()
      .range([50, 750])
      .domain(d3.extent(nodes_list, xFn));

    var yScale = d3.scale.linear()
      .range([50, 550])
      .domain(d3.extent(nodes_list, yFn));*/



  var drag = d3.behavior.drag()
      .origin(function(d) { return d; })
      .on("dragstart", dragstarted)
      .on('drag', function (d,i) {
          d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
          console.log(d.id + ";" + d.x + ";" + d.y + ";")
          d3.select(this).attr("transform", function (d, i) {
              return "translate(" + [d.x,d.y] + ")";

          })
          links
              .attr("x1", function(d) { return get_node_x(d.source); })
              .attr("y1", function(d) { return get_node_y(d.source); })
              .attr("x2", function(d) { return get_node_x(d.target); })
              .attr("y2", function(d) { return get_node_y(d.target); });

      })
      .on("dragend", dragended);


  function get_node_x(search_key)
  {

      for (var i = 0; i < nodes_list.length; i++) 
      {
          if(search_key.localeCompare(nodes_list[i].id) == 0)
              {
              return nodes_list[i].x;
              }
      }

  };


  function get_node_y(search_key)
  {

      for (var i = 0; i < nodes_list.length; i++) 
      {
          if(search_key.localeCompare(nodes_list[i].id) == 0)
              {
              return nodes_list[i].y;
              }
      }

  };

      links.enter()
          .append("line")
          .attr("class", "link")
          .attr("x1", function(d) { return get_node_x(d.source); })
          .attr("y1", function(d) { return get_node_y(d.source); })
          .attr("x2", function(d) { return get_node_x(d.target); })
          .attr("y2", function(d) { return get_node_y(d.target); });



      /*Create and place the "blocks" containing the circle and the text */  
      var elemEnter = nodes.enter()
          .append("g")
          .attr("transform", function(d){return "translate("+ d.x +","+ d.y +")"})
          .on("mouseover", function(d) {      
              console.log(d.id + ";" + d.x + ";" + d.x + ";" + d3.event.dx + ";" + d.y + ";" + d.y + ";" + d3.event.dy + ";")
          }) 
          .call(drag);




      /*Create the circle for each block */
      var circle = elemEnter.append("circle")
          .attr("r", 10)




      /* Create the text for each block */
      elemEnter.append("text")
          .attr("text-anchor", "middle")
          .text(function(d){return d.label});



    console.log(json);
    console.log(svg);


  }
);

</script>
</body>
</html>