大資料視覺化第三天——D3.js初探:餅形圖
阿新 • • 發佈:2018-12-26
在找了許多參考資料後,我發現大部分關於D3.js的講解不滿足我的需求,有些講的太過冗長,舉了很多不需要的點,比如用D3來做排序過濾這種分析階段就應該做完的事;有些又太簡單,很多省略的細節讓人看的似是而非。這篇我在網上找了一個餅狀圖的小例子來幫助自己理解D3一般圖形繪製過程,在程式碼中涉及到某個知識點時再有針對性的學習。
首先來定義四個類別,每個類別中有不同數目的樣本。
然後定義幾個常量,主要是繪製時使用。var dataset = [{ label: "A", count: 10 }, { label: "B", count: 20 }, { label: "C", count: 30 }, { label: "D", count: 40 } ];
var width = 360;
var height = 360;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal(d3.schemeCategory20);
其中寬、高是svg的屬性,radiu是圓的半徑。這裡因為width和heigtht是一樣的,所以不用Math.min也沒關係。color這裡構建了一個顏色的標度,d3.scaleOrdinal()函式對
d3.schemeCategory20中的20個顏色構建了一個有序的顏色列表。
var svg = d3.select("#chart")
.append('svg')
.attr('width',width)
.attr('height',height)
.append('g')
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')');
這裡首先用d3提供的select方式選中了以ID"chart"命名的標籤(這是我們預先定義的一個<div>標籤)。
d3提供了兩種select方法,select()和selectAll(),前面一種方法返回匹配這個選擇器的第一個元素,後面一種方法返回匹配這個選擇器的所有元素,前面加#代表了選擇ID,加.代表了選擇類。
然後在被選中的<div>標籤中,通過.append()方法增加了一個svg區域用來繪製圖形,隨後的兩個.attr()給這個svg區域加入了寬高的屬性。這裡有一個連續呼叫函式的方法成為“連綴語法”。在設定完svg區域的屬性後,又在svg區域中加入了一個<g>標籤,用來劃定一個區域,設定了這個區域的transform屬性,屬性的值為translate(180,180),作用是把<g>標籤所劃定的區域先向右,再向左分別移動180的位置。
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius);
var pie = d3.pie()
.value(function(d) { return d.count; })
.sort(null);
上面這段是定義了d3中的兩個圖形,一個是圓形arc(),一個是餅圖pie(),這兩個函式後面所append()的是一些針對這個圖形的特殊設定函式,現在不必太過深究,到使用的時候再查文件也可以。這裡簡單介紹一下,innerRadius()和outerRadius()設定了圓環的內徑和外徑,假如innerRadius()裡面引數不為0,將畫出一個圓環;d3.pie().value()則通過接受一組資料來返回餅狀圖幾條線的角度,並且不進行排序
var path = svg.selectAll('path')
.data(pie(dataset))
.enter()
.append('path')
.attr('d',arc)
.attr('fill',function(d,i){
return color(d.data.label);
})
上面這段是D3的核心,主要做了下面幾件事,按行來講解:
- 選擇了SVG中的所有<path>標籤,但是我們之前並沒有在<svg>區域中設定<path>標籤,所以將返回一個空值,但是隨後將通過enter()建立這些<path>
- 我們將資料通過data()函式繫結到<path>上,這裡涉及到D3的資料繫結機制,有datum()和data()兩種方法,前者將被選中的所有物件都繫結同一個值,後者則按照被選中物件與data()中引數資料的數量對比進行不同處理:如果兩者相等,直接執行後面的語句,也稱作update();如果元素不夠,比如現在的情況,將一直增加元素到與資料匹配為止,也稱作enter(),每次enter增加一個標籤然後執行update()的操作,所以在我們的例子中,將執行四次enter(),如果元素多餘,則刪除元素,也叫exit().
- 每次enter()會執行append('path')也就是增加一個<path>標籤
- 然後增加一個path的屬性d,這是SVG作圖中一個相當複雜的屬性,包含了許多svg的移動劃線等操作,其屬性值為d3的arc()函式所返回的path data.
- 然後每次enter()的過程fill一個不同的顏色,這個function(d,i)可能有些費解,這是由d3.js提供的變數,分別代表了數值和數值的索引。
效果圖如下:
全部程式碼如下:
<div id="chart">
</div>
<script src="d3/d3.js"></script>
<script>
var dataset = [{
label: "A",
count: 10
},
{
label: "B",
count: 20
},
{
label: "C",
count: 30
},
{
label: "D",
count: 40
}
];
var width = 360;
var height = 360;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var svg = d3.select("#chart")
.append('svg')
.attr('width',width)
.attr('height',height)
.append('g')
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')');
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius);
var pie = d3.pie()
.value(function(d) { return d.count; })
.sort(null);
var path = svg.selectAll('path')
.data(pie(dataset))
.enter()
.append('path')
.attr('d',arc)
.attr('fill',function(d,i){
return color(d.data.label);
})
</script>