Production and scaling (Zoom) D3 data visualization force directing FIG mouse right-click menu and drag (Drag) applications

The first wave of final results show

final effect

Here Insert Picture Description

This time to learn D3, force Roadmap

FIG directed force (Force-Directed Graph), is an algorithm drawing. Arranged in two or three dimensional space nodes, connected by lines between the nodes, referred to as a connection. Nearly equal length of each connection, and do not intersect as possible. Nodes and links have been applied force, the force is calculated based on the relative position of the node and connection. The force to calculate the trajectory of nodes and links, and to continue to reduce their energy, ultimately to achieve a stable low energy state.

FIG force directed shows a relationship between the nodes can-many.

The key layout method defines a force directed graph Force ()
D3 v3 and v4 on the version for Force () This method is a great change

Man of few words said, the code is as follows: (Note: D3.js version this time using the V3)

Page code

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>The END</title>
  <script src="http://d3js.org/d3.v3.min.js"></script>
  <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
  <script src="./js/smartMenu.js"></script>
  <script src="./fun.js"></script>
  <link rel="stylesheet" href="./css/smartMenu.css">
</head>
<body>
  <div id="tpContainer">

  </div>   
 
</body>
</html>

FIG force directed codes fun.js

//获取数据
d3.json('./preson.json', function(error,data){
  if (error) {
      return console.log(error);
    }
  // console.log(data);
  drawToPofun(data.nodes,data.lines);
});

function drawToPofun(nodes,edges){
  
  //定义初始变量
  var width  = 1503;
  var height = 654;
  var img_w = 40;
  var img_h = 40;
  var text_dx = -20;
  var text_dy = 20;
  var i = 0;

  //初始化拖拽方法
  var drag = d3.behavior.drag()
    .origin(function(d) {
      return d;
    })
    .on("dragstart", dragstarted)
    .on("drag", dragged)
    .on("dragend", dragended);

  //初始化缩放方法
  var zoom=d3.behavior.zoom()
    .scaleExtent([-10,10]).on("zoom",zoomed);

  //定义画布
  var svg = d3.select("#tpContainer")
  .append("svg")
  .attr("width",width)
  .attr("height",height)
  .call(zoom)
  .on("dblclick.zoom", () => {});//禁止双击放大
  
  //拆分子节点
  var view = svg.append("g")
  .attr("class","graphCon");
  
  var node = view.selectAll("g.node").data(nodes,function (d) {
    return d.id || (d.id = ++i);
  });

  var nodeEnter = node
  .enter()
  .append("g")
  .attr("class","node")
  .attr("id",d=>d.id)//添加节点,以自定义图标代替
  var nodes_img = nodeEnter.append("image")
  .data(nodes)
  .attr("width",function(d){
      return img_w;
    })
  .attr("height",function(d){
      return img_h;
    })
  .attr("xlink:href",function(d){
    return d.image;
    })
  .call(drag)//开始拖拽方法
  
  //添加连线
  var edges_line = nodeEnter.append("line")
  .data(edges)
  .attr("class","line")
  .style("stroke","#ccc")
  .style("stroke-width",1);

  //添加节点说明(文本)
  var nodes_text = nodeEnter.append("text")
  .data(nodes)
  .attr("class","nodetext")
  .attr("dx",text_dx)
  .attr("dy",text_dy)
  .text(function(d){
    return d.name;
  });

  //定义力学图布局
   var force  = d3.layout.force().nodes(nodes)
    .links(edges)
    .size([width,height])
    .linkDistance(200)
    .charge(-800)
    .start()
    .on("tick", function(){
      
      //限制结点的边界
      nodes.forEach(function(d,i){
        d.x = d.x - img_w/2 < 0? img_w/2 : d.x ;
        d.x = d.x + img_w/2 > width ? width - img_w/2 : 
        d.x ; 
        d.y = d.y - img_h/2 < 0? img_h/2 : d.y ;
        d.y = d.y + img_h/2 + text_dy > height ? 
        height - img_h/2 - text_dy : d.y ;
      });

      //更新连接线的位置
      edges_line.attr("x1",function(d){ return d.source.x; });
      edges_line.attr("y1",function(d){ return d.source.y; });
      edges_line.attr("x2",function(d){ return d.target.x; });
      edges_line.attr("y2",function(d){ return d.target.y; });
      //更新结点图片和文字
      nodes_img.attr("x",function(d){
        return d.x - img_w/2; 
      });
      nodes_img.attr("y",function(d){ 
        return d.y - img_h/2; 
      });                  
      nodes_text.attr("x",function(d){ return d.x; });
      nodes_text.attr("y",function(d){ 
        return d.y + img_h/2; 
      });
    }); 

    // 定义菜单选项
    var userMenuData = [
      [{
          text: "菜单1",
          func: function () {
            var id = Number($(this).attr("id"))
            alert("菜单1"+",No."+ id)
          }
        },
        {
          text: "菜单2",
          func: function () {
            var id = Number($(this).attr("id"))
            alert("菜单2"+",No."+ id)
          }
        },
        {
          text: "菜单3",
          func: function () {
            var id = Number($(this).attr("id"))
            alert("菜单3"+",No."+ id)
          }
        } 
      ]
    ];
    // 事件监听方式添加事件绑定
    $("body").smartMenu(userMenuData, {
      name: "chatRightControl",
      container: "g.node"
    });
    
    function zoomed(){
      view.attr("transform",
      "translate("+d3.event.translate+")scale(" +
      d3.event.scale + ")");
    }
    function dragstarted(d) {
      d3.event.sourceEvent.stopPropagation();
      d3.select(this).classed("dragging", true);
      force.start();
    }
    function dragged(d) {
      d.x = d3.event.x;
      d.y = d3.event.y;
    }
    function dragended(d) {
      d3.select(this).classed("dragging", false);
    }
}

Data format preson.json

{
  "nodes": [
    {"name": "preson1", "image": "./person.png"}, 
    {"name": "preson2", "image": "./person.png"}, 
    {"name": "preson3", "image": "./person.png"}, 
    {"name": "preson4", "image": "./person.png"}, 
    {"name": "preson5", "image": "./person.png"}, 
    {"name": "preson6", "image": "./person.png"},
    {"name": "preson7", "image": "./person.png"},
    {"name": "preson8", "image": "./person.png"},
    {"name": "preson9", "image": "./person.png"},
    {"name": "preson10","image": "./person.png"}
],
"lines": [
  { "source": 0 , "target": 1 },
  { "source": 0 , "target": 2 },
  { "source": 0 , "target": 3 },
  { "source": 1 , "target": 4 },
  { "source": 1 , "target": 5 },
  { "source": 1 , "target": 6 },
  { "source": 0 , "target": 7 },
  { "source": 7 , "target": 8 },
  { "source": 7 , "target": 9 }
]
}

I use the menu jQuery plugin downloaded, js / css code is not demonstrated.

Published 79 original articles · won praise 89 · views 20000 +

Guess you like

Origin blog.csdn.net/qq_39141486/article/details/102940383
Recommended