首页 > 代码库 > 【 D3.js 入门系列 --- 9.2 】 力学图的制作

【 D3.js 入门系列 --- 9.2 】 力学图的制作

    本人的个人博客为: www.ourd3js.com 

    csdn博客为: blog.csdn.net/lzhlzz 

    转载请注明出处,谢谢。


    力学图( Force ),也有被翻译做力导向图等。这种图很有意思,先从初始数据开始,看下面代码:

		var nodes = [ { name: "GuiLin"    }, 
					  { name: "GuangZhou" },
					  { name: "XiaMen"    },
					  { name: "HangZhou"   },
					  { name: "ShangHai"   },
					  { name: "QingDao"    },
					  { name: "TianJin"    },
					  { name: "BeiJing"    },
					  { name: "ChangChun"  },
					  { name: "XiAn"       },
					  { name: "WuluMuQi"  },
					  { name: "LaSa"       },
					  { name: "ChengDu"    } ];
					 
		var edges = [  { source : 0  , target: 1 } ,
					   { source : 1  , target: 2 } ,
					   { source : 2  , target: 3 } ,
					   { source : 3  , target: 4 } ,
					   { source : 4  , target: 5 } ,
					   { source : 5  , target: 6 } ,
					   { source : 6  , target: 7 } ,
					   { source : 7  , target: 8 } ,
					   { source : 8  , target: 9 } ,
					   { source : 9  , target: 10 } ,
					   { source : 10 , target: 11 } ,
					   { source : 11 , target: 12 } ,
					   { source : 12 , target: 0 } ];	
    这里有顶点( nodes )和边( edges ),这里的顶点是一些城市名称,边是两个顶点之间的连线。我们现在要用这些数据来做力学图。但是这样的数据不适合做力学图,比如不知道每一个顶点画在哪个坐标等。所以需要先用 Layout 来转换数据,我们说过, D3 中的 Layout 就是用来转换数据的。 force 的 layout 为:

var force = d3.layout.force()
							.nodes(nodes)
							.links(edges)
							.size([width,height])
							.linkDistance(200)
							.charge([-100])
							.start();
    在上面的代码中:

  • d3.layout.force() 是力学图 Layout 的函数
  • nodes() 里传入顶点的数组
  • links() 里放入边的数组
  • size() 是作用域的大小
  • linkDistance() 用于设定两个顶点之间的长度
  • charge() 是设定弹力的大小。
  • start() 表示开始转换
    调用这个函数后,数据就已经被转换了,我们看看数据从什么转换成什么了:

    顶点(转换前):


    顶点(转换后):

    可以看到,转换后,多了 index , px , py 等。

    再来看看边的数据:
    边(转换前):


    边(转换后):

    可以看到,边数据的两个索引号直接被转换成了两个顶点的数据。

    好了,有了这些数据,我们就可以作图了。我们用 SVG 中的 line 画边,用 SVG 中的 circle 画顶点。
var svg_edges = svg.selectAll("line")
							.data(edges)
							.enter()
							.append("line")
							.style("stroke","#ccc")
							.style("stroke-width",1);
		
		var color = d3.scale.category20();
							
		var svg_nodes = svg.selectAll("circle")
							.data(nodes)
							.enter()
							.append("circle")
							.attr("r",10)
							.style("fill",function(d,i){
								return color(i);
							})
							.call(force.drag);
    这样的代码我们已经很熟悉了,只有最后一句代码没出现过, call( force.drag ) 是设定我们可以拖动顶点。这个 call 函数我们前面说过,这个 call 是用于将当前选择的元素传到 force.drag 函数中。
    最后,我们还需要一段代码,如下:
		force.on("tick", function(){
		
			 svg_edges.attr("x1",function(d){ return d.source.x; });
			 svg_edges.attr("y1",function(d){ return d.source.y; });
			 svg_edges.attr("x2",function(d){ return d.target.x; });
			 svg_edges.attr("y2",function(d){ return d.target.y; });
			 
			 svg_nodes.attr("cx",function(d){ return d.x; });
			 svg_nodes.attr("cy",function(d){ return d.y; });
		});
    tick 指的是时间间隔,也就是每一个时间间隔之后就刷新一遍画面,刷新的内容写在后面的无名函数 function 中, function 函数中写上作图的内容。
    我们来看看最终效果图:

    拖动的效果图片显现不出来,请看这里:
    http://www.ourd3js.com/demo/force.html
    代码请右键点浏览器查看。



【 D3.js 入门系列 --- 9.2 】 力学图的制作