【 D3.js 入门系列 --- 9.3 】 弦图的制作

来源:互联网 发布:修改棋牌游戏数据 编辑:程序博客网 时间:2024/04/29 15:21

    本人的个人博客为: 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 ]];
    我们的数据是一些城市名和一大堆数字,这些数字表示城市人口的来源。如

 北京上海北京10003045上海32142000

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

    北京市的人口有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

谢谢阅读。




4 1