zoukankan      html  css  js  c++  java
  • 【 D3.js 入门系列 --- 9.3 】 弦图生产

        我个人的博客: www.ourd3js.com 

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

        转载请注明出处,谢谢。


        弦图( Chord ),主要用于表示两个节点之间的联系。例如以下图:


        两点之间的连线表示。谁和谁具有联系:


        线的粗细表示权重:


        上面的介绍源于: http://circos.ca/guide/tables/  ,我就不具体介绍了,还是非常好理解的。

        那么在 D3 中怎么用 layout 转换出弦图所须要的数据。并作图呢?请耐心往下看。


        1. 首先给出数据

    		var city_name = [ "北京" , "上海" , "广州" , "深圳" , "香港"  ];
    		
    		var population = [
    		  [ 1000,  3045  , 4567 , 1234 , 3714 ],
    		  [ 3214,  2000  , 2060 , 124  , 3234 ],
    		  [ 8761,  6545  , 3000 , 8045 , 647  ],
    		  [ 3211,  1067  , 3214 , 4000  , 1006 ],
    		  [ 2146,  1034  , 6745 , 4764  , 5000 ]
    		];
        我们的数据是一些城市名和一大堆数字,这些数字表示城市人口的来源。如

      北京 上海
    北京 1000 3045
    上海 3214 2000

        左边第一列是被统计人口的城市,上边第一行是被统计的来源城市,即:

        北京市的人口有1000个人来自本地,有3045人是来自上海的移民,总人口为 1000 + 3045。
        上海市的人口有2000个人来自本地。有3214人是来自北京的移民,总人口为 3214 + 2000。

        好了!!!

    对于这样一组数据。怎么进行可视化。


        2. 转换数据

    var chord_layout = d3.layout.chord()
    			                 .padding(0.03)
    			                 .sortSubgroups(d3.descending)
    			                 .matrix(population);
        能够用 console.log 输出一下转换后的数据。

    转换后,population 实际分成了两个部分,groups 和 chords 。groups 就是上面图片中的节点。 chords 就是上面图片中的连线。chords 里面分为 source 和 target ,也就是连线的两端。下图为转换后的结果图:

        groups:

     

        chords:


        3. SVG,弦图。颜色函数的定义

    var width  = 600;
    		var height = 600;
    		var innerRadius = width/2 * 0.7;
    		var outerRadius = innerRadius * 1.1;
    
    		var color20 = d3.scale.category20();
    
    		var svg = d3.select("body").append("svg")
    			.attr("width", width)
    			.attr("height", height)
    		    .append("g")
    			.attr("transform", "translate(" + width/2 + "," + height/2 + ")");
        这里大家都非常熟悉了,就不用解释了。

    假设看不懂,请看前面章节。


        4. 绘制外部弦(即分组。有多少个城市画多少个弦),及绘制城市名称

    var outer_arc =  d3.svg.arc()
    					 .innerRadius(innerRadius)
    					 .outerRadius(outerRadius);
    		
    		var g_outer = svg.append("g");
    		
    		g_outer.selectAll("path")
    				.data(chord_layout.groups)
    				.enter()
    				.append("path")
    				.style("fill", function(d) { return color20(d.index); })
    				.style("stroke", function(d) { return color20(d.index); })
    				.attr("d", outer_arc );
    			
    		g_outer.selectAll("text")
    				.data(chord_layout.groups)
    				.enter()
    				.append("text")
    				.each( function(d,i) { 
    					d.angle = (d.startAngle + d.endAngle) / 2; 
    					d.name = city_name[i];
    				})
    				.attr("dy",".35em")
    				.attr("transform", function(d){
    					return "rotate(" + ( d.angle * 180 / Math.PI ) + ")" +
    						   "translate(0,"+ -1.0*(outerRadius+10) +")" +
    						    ( ( d.angle > Math.PI*3/4 && d.angle < Math.PI*5/4 ) ? "rotate(180)" : "");
    				})
    				.text(function(d){
    					return d.name;
    				});
        绘制外部弦的部分,事实上和绘制一个饼状图是一样的。能够參照9.1节。那么上面的代码不难理解。还有就是绘制弦外面的文字(即城市名称),请看最后一段代码:

        绑定数据后,有一个 each() 。这个函数是表示对于不论什么一个绑定的元素,都运行后面的无名函数 function 的代码,这里的代码为: 计算一个角度,赋值给 d.angle 。获取城市的名称。

        在用 transform 进行位移时,要注意转换的顺序: rotate -> translate。 还有就是转换的最后一行代码:

    ( ( d.angle > Math.PI*3/4 && d.angle < Math.PI*5/4 ) ? "rotate(180)" : "")
        这是表示,当角度在135°到225°之间时,旋转180°。

    否则下方的文字是倒的,不利于观看。


        5. 内部弦的绘制

    var inner_chord =  d3.svg.chord()
    						.radius(innerRadius);
    		
    		svg.append("g")
    			.attr("class", "chord")
    		    .selectAll("path")
    			.data(chord_layout.chords)
    		    .enter()
    			.append("path")
    			.attr("d", inner_chord )
    		    .style("fill", function(d) { return color20(d.source.index); })
    			.style("opacity", 1)
    			.on("mouseover",function(d,i){
    				d3.select(this)
    					.style("fill","yellow");
    			})
    			.on("mouseout",function(d,i) { 
    				d3.select(this)
    					.transition()
                        .duration(1000)
    					.style("fill",color20(d.source.index));
    			});
        绘制内部弦有专用的函数 d3.svg.chord() ,仅仅要将转换后的參数传给此函数。就可以做出内部弦。哈哈,方便吧。

        以下还有几句关于鼠标操作的代码: mouseover , mouseout 。 可參看第8节。


        结果例如以下图:


    对话操作的内容,请点击以下网址,把鼠标放在弦图上看看吧。

    http://www.ourd3js.com/demo/chord.html

    谢谢阅阅读。




    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    [BZOJ-1007&洛谷P3194][HNOI2008]水平可见直线--【半平面交(单调栈)】
    [BZOJ-1006&洛谷P3196][HNOI2008]神奇的国度--【图的染色-最大势MCS算法】
    [BZOJ-1005&洛谷P2624][HNOI2008]明明的烦恼-【Purfer序列】py+java
    [BZOJ1211 & 洛谷P2290] [HNOI2004]树的计数-【Purfer序列】py+Java
    【BZOJ-1004&洛谷P1446】[HNOI2008]Cards-置换群(burnside引理|DP)
    POJ-2409 Let it Bead 【置换群-Polya定理】
    Dijkstra--POJ 2502 Subway(求出所有路径再求最短路径)
    二分--LIGHTOJ 1088查找区间(水题)
    二分--1043
    二分---LIGHTOJ 1062
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4748832.html
Copyright © 2011-2022 走看看