餅狀圖是數據統計中常常用到的另外一類圖表,餅圖能夠直觀地顯示一個數據系列中各項的大小與各項總和的比例,本文將使用D3上手製做一個簡單的餅狀圖數組
佈局是D3中很是重要的內容,有了佈局D3才能畫出複雜的矢量圖。但佈局並非直接繪製圖形,只是將初始數據轉換成容易畫圖的圖形語言,畫圖工具能讀懂圖形語言來進行繪製。瀏覽器
在繪製餅狀圖中,例若有一組數據[1, 2, 3],只依靠這些數據是畫不出的,須要將這些數據轉化爲圓形的起始角度和終止角度,第一塊的角度區域爲[0, π/3],第二塊的角度區域爲[π/3, π]……繪製工具能根據這些角度值進行繪製。佈局只進行數據轉換app
D3還提供其餘經常使用圖表的佈局函數,好比力導向圖(Force)、弦圖(Chord)、樹狀圖(Tree)、直方圖(Histogram)、分區圖(Partition)等,每種佈局有對應的APIsvg
表格數據是來自w3schools的2016年9月的瀏覽器使用率函數
瀏覽器 | 佔比 |
---|---|
Chrome | 72.5% |
IE | 5.3% |
Firefox | 16.3% |
Safari | 3.5% |
Opera | 1.0% |
Others | 1.4% |
對此設定如下二維數組裝載這些數據工具
var dataset = [['Chrome', 72.5], ['IE', 5.3], ['Firefox', 16.3], ['Safari', 3.5], ['Opera', 1.0], ['Others', 1.4]];
複製代碼
構建一個餅佈局並接收數據佈局
var pie = d3.pie()
.sort(null) // 在建立佈局的時候,默認排序數據從大到小,設爲null能夠按照數組默認順序排序
.value(function(d){
return d[1]
});
複製代碼
把數據轉換爲餅圖繪製所須要的數據ui
var piedata = pie(dataset);
console.log(piedata);
複製代碼
在控制檯輸出piedata,看看轉換後的數據spa
能夠看到,原來的數據已經被轉換成6組適合畫圖的數據code
雖然有了角度,但目前仍是很難畫出咱們想要的餅圖,還要用到D3中的路徑生成器。在svg中,path標籤的路徑數值每每十分複雜,手動去生成是不現實的,尤爲是要生成各類複雜曲線的時候,好在D3提供了基本的路徑生成器,有線段、區域、弧生成器等。畫餅圖的時候須要用到弧生成器,幫助咱們把轉換後的數據真正繪製出來
這裏把畫布的四分之一做爲外部半徑,內部半徑設爲0就是餅圖,沒錯,設置大於0就是圓環圖
var outerRadius = width / 4;
var innerRadius = 0;
var arc = d3.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius);
複製代碼
跟以前同樣,建立g組合標籤後,把piedata數據綁定至g標籤,這裏要用到D3的內置顏色,d3.schemeCategory10選了10種顏色,方便咱們隨時使用,爲餅圖的不一樣區域填色,沒必要爲想不出好的顏色搭配而煩惱,固然也能夠自定義顏色
var arcs = svg.selectAll('g')
.data(piedata)
.enter()
.append('g')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
// 調用內置顏色序列
var colors = d3.schemeCategory10;
arcs.append('path')
.attr('fill', function(d, i){
return colors[i];
})
.attr('d', function(d){
return arc(d);
});
複製代碼
在path標籤中,給d屬性賦予數據通過弧生成器處理的值,這樣一個沒有標註的餅圖就完成了
接下來給餅圖加一些標註,以便更好地閱讀圖形,主要用到弧中心的概念,以下圖,黑點就是每一個弧的中心,利用**arc.centroid()**能夠獲取弧中心的座標,而且這個座標是相對圓形的相對座標。有了這個座標,能夠很方便地在每一個弧上添加文字標註
arc.centroid(d)是一個包含橫座標和縱座標的數組[x, y],給座標乘以2倍以上的數值就把文字移到圓形外邊
arcs.append('text')
.attr('transform', function(d, i){
var x = arc.centroid(d)[0] * 2.8;
var y = arc.centroid(d)[1] * 2.8;
return 'translate(' + x + ', ' + y + ')';
})
.attr('text-anchor', 'middle')
.text(function(d){
var percent = Number(d.value) / d3.sum(dataset, function(d){
return d[1];
}) * 100;
return d.data[0] + ' ' + percent.toFixed(1) + '%';
})
複製代碼
最後再加一些連線
arcs.append('line')
.attr('stroke', 'black')
.attr('x1', function(d){ return arc.centroid(d)[0] * 2; })
.attr('y1', function(d){ return arc.centroid(d)[1] * 2; })
.attr('x2', function(d, i){
return arc.centroid(d)[0] * 2.5;
})
.attr('y2', function(d, i){
return arc.centroid(d)[1] * 2.5;
});
複製代碼
因爲最後幾個數據過小,標註文字會重疊到一塊兒,這裏作了一個判斷處理來錯開數據值較小的文字,最後的效果圖以下所示