iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 25
1
Modern Web

React + D3 的正確姿勢系列 第 25

Day25-pie chart(using D3.js)

前言

今天要來介紹一個比較特別的圖表,在前天的文章提到長條圖,用來反映事物分布、集中情況,昨天的文章提到折線圖,用來顯示數據的變化趨勢,但是這些都無法得知單一數據佔全部數據的比例,如果今天想要從比例下手,長條圖跟折線圖可能就不太直觀,所以今天筆者要來介紹圓餅圖,一個負責用來看數據比例統計圖。

圓餅圖

若統計目的為觀察統計資料各分量佔總量的比例這時候就適用圓餅圖,在繪製圓餅圖的時候建議先把資料轉成百分比而不是用總量去繪製,這樣會讓圓餅圖中每個區塊的佔比最精準。

arc

想要把圓餅圖畫好, 弧(arc) 很重要,畢竟圓餅圖的本質其實就是一個圓,要如何畫這個弧呢?其實 D3 自己有一個 API 叫 d3.arc() ,透過這個 API 我們就可以很輕鬆地畫出一個弧形出來,要把弧形畫得好 半徑(radius) 也要設定好,在 d3.arc() 中會設定 innerRadius 以及 outerRadius 代表半徑的範圍,想當然圓餅圖一定會把 innerRadius 設為 0 ,而 outerRadius 設定為圖表寬度也就是直徑的一半,所以整體寫法會長的像這樣:

const arc = d3
  .arc()
  .innerRadius(0)
  .outerRadius(width / 2)

pie

設定好弧形之後接下來就是要畫出這個圓形出來了,這邊筆者要介紹一下 d3.pie() 這個 API ,透過這個 API 就可以很順利的初始化一張圓餅圖了,跟一開始我們設定 svg 容器一樣,這邊初始化圓餅圖一樣要餵資料進去才能順利畫出這張圖表,而胃資料的方式是透過 pie.value() 的方式,資料一樣要用陣列的型態,所以整體的寫法就會長這樣:

const pie = d3.pie().value(dataArray)

繪製流程

第一步相信大家都知道了,沒錯就是要先初始化 svg 容器,永遠都是這一千零一招XD

const width = document.querySelector(`#${root}`).clientWidth,
    height = width
    
const svg = d3
  .select(document.querySelector(`#${root}`))
  .append('svg')
  .attr('width', width)
  .attr('height', height)
  .append('g')
  .attr('transform', `translate(${width / 2}, ${height / 2})`)

這邊讀者應該有發現不一樣的地方了,這次竟然沒有用到 margin 反而是直接平移圖表寬高的一半,這是為什麼呢?由於圓餅圖不像長條圖或折線圖需要考慮到座標,這邊只要單純的讓圖表可以顯示到我們設定的容器正中央就行了,所以在平移的過程中就相對的單純很多,只要想辦法把圖表移到正中央就好,而正中央的寫法就是把圖表的寬高都除以 2 就會移動到正中央啦!


由於圓餅圖沒有座標,所以這邊就不用設定比例尺、輸出區域以及輸入區域了,是不是覺得輕鬆很多XD

為了讓文章的編排跟之前的文章一樣,所以筆者決定在這個段落來初始化弧線,寫法的部分就跟上面介紹的差不多,這邊一樣都會用個變數包裝起來,方便等等傳資料進去圖表的時候直接呼叫變數,就不用一直寫一堆一樣的程式碼。

const arc = d3
  .arc()
  .innerRadius(0)
  .outerRadius(width / 2)

設定好弧線之後再來就是初始化圓餅圖了,這邊一樣也會用個變數包裝起來,方便等等傳資料進去圖表的時候直接呼叫變數,跟上面不一樣的是這邊的 pie.value 會用 callback 的方式來傳入資料,畢竟真正傳資料到圖表的動作還是 d3.data()pie.value() 還是偏向接收資料而已,所以就會用個 callback 來取得陣列中的資料了。

const pie = d3.pie().value(d => d.value)

最後就只剩下傳資料進去圖表內啦!有沒有覺得圓餅圖真的超簡單的,要設定的東西有夠少XD

還記得上面設定好的 arc 嗎?這邊會把 arc 擺在 path 內,其實大家可以稍微想一下圓餅圖其實就是把一個圓形的線條內部在上色而已,所以 arc 的設定會擺在 path 內好像也變得蠻合理了,再來是傳資料的部分,在上一個段落提到這次的資料其實是要傳進去 pie.value() 內以便於畫出真正的圓餅圖,所以這裡的 d3.data() 內就會把 pie 也順便傳進去,寫法就像這樣:

svg
  .selectAll('path')
  .data(pie(datas))
  .enter()
  .append('g')
  .append('path')
  .attr('d', arc)
  .attr('fill', d => chartColor[d.name].color)

組合起來

最後筆者有把上面流程所講的程式碼都丟到 GitHub 上,有興趣想要參考的讀者歡迎上去參考這些範例碼。

pie chart

總結

今天介紹了圓餅圖這個非常萬用的圖表,其實圓餅圖有非常多的變形可以玩,所以筆者會在明天的文章介紹另一種圓餅圖的變形:環圈圖,這個圖表也是很常使用的統計圖表,有了今天文章的觀念再來看明天的文章就會更好懂,所以建議大家可以在今天的文章多花些時間消化一下,這樣明天的文章就比較容易吸收了。

如果對於文章有任何問題歡迎在下面留言給我,沒問題的話明天要來介紹環圈圖了。


上一篇
Day24-line chart(using D3.js)
下一篇
Day26-donut chart(using D3.js)
系列文
React + D3 的正確姿勢30

尚未有邦友留言

立即登入留言