使用D3js绘制Force-Directed Graph(力导向图)

Force-directed(力导向)图形绘制算法通过图形本身的结构(图中顶点与边的拓扑关系)计算出图形的层次,而不依赖于特定领域的知识。使用力导向算法绘制的平面图形通常比较美观,并且图中各条边之间的交叉尽可能的少。

本文对使用D3js绘制Foorce-Directed Graph(力导向图)的过程进行简要的介绍,以下面的逻辑图(包含6个节点和5条边)为例。

import json
#nodes为图的节点集合
nodes = [{'name' : 'nodeA'}, 
         {'name' : 'nodeB'}, 
         {'name' : 'nodeC'}, 
         {'name' : 'nodeD'}, 
         {'name' : 'nodeE'}, 
         {'name' : 'nodeF'}]
#links为图的边集合,source为起点,target为终点
links = [{'source' : 0 , 'target' : 1}, 
         {'source' : 0 , 'target' : 2}, 
         {'source' : 0 , 'target' : 3}, 
         {'source' : 0 , 'target' : 4}, 
         {'source' : 0 , 'target' : 5}]
#graph为逻辑图,由节点集合和边集合组成
graph = {'nodes' : nodes , 'links' : links}
print json.dumps(graph)

上例的源码 force-directed-graph.html 及注释如下:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
.link {
  stroke : #CCC;
  stroke-width : 2;
}
.node text {
  pointer-events : none;
  font-size : 12px;
}
svg { overflow : hidden; }
</style>
<script src="http://libs.useso.com/js/jquery/1.11.1/jquery.min.js"></script>
<script src="http://libs.useso.com/js/d3/3.4.8/d3.min.js"></script>
<script>

var graph = {"nodes": [{"name": "nodeA"}, 
{"name": "nodeB"}, 
{"name": "nodeC"}, 
{"name": "nodeD"}, 
{"name": "nodeE"}, 
{"name": "nodeF"}], 
"links": [{"source": 0, "target":1}, 
{"source": 0, "target": 2}, 
{"source": 0, "target": 3}, 
{"source": 0, "target": 4}, 
{"source": 0, "target": 5}]};
//返回随机颜色代码
function random_color() {
    var letters = '0123456789ABCDEF'.split('');
    var color = '#';
    for (var i = 0; i < 6; i++ ) {
        color += letters[Math.round(Math.random() * 15)];
    }
    return color;
}
function draw() {
  var width = 400;
  var height = 300;
  //设置svg宽度和高度
  var svg = d3.select("#canvas svg")
    .attr("width", width)
    .attr("height", height);
  //设置Force-Directed力参数
  var force = d3.layout.force()
    .gravity(.05)
    .distance(120)
    .charge(-100)
    .size([width, height]);
  force
    .nodes(graph.nodes)
    .links(graph.links)
    .start();
  //选择边集合
  var link = svg.selectAll(".link")
    .data(graph.links)
    .enter().append("line")
    .attr("class", "link");
  //选择节点集合
  var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter().append("g")
    .attr("class", "node")
    .call(force.drag); //响应鼠标拖拽事件
  //节点添加圆形图案
  node.append("svg:circle").attr("r", 10)
    .style("fill", function(){
      return random_color();
    })
    .style("stroke", "#FFF").style("stroke-width", 3);
    node.append("text")
      .attr("dx", 12)
      .attr("dy", ".36em")
      .text(function(d) { return d.name });
  //绑定tick事件
  force.on("tick", function() {
    link.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; });
    node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
  });
}
$(function(){
  draw();
});
</script>
</head>
<body>
  <div id="canvas">
  <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300"></svg>
  </div>
</body>
</html>

 

本文链接:http://bookshadow.com/weblog/2014/11/04/d3js-force-directed-graph/
请尊重作者的劳动成果,转载请注明出处!书影博客保留对文章的所有权利。

如果您喜欢这篇博文,欢迎您捐赠书影博客: ,查看支付宝二维码