【 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

謝謝閱讀。





注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com