為何現在研究 d3.js?
最近在工作上開始接觸 d3.js 要客製一個圖表,呈現大量分群資料,投射至二維空間上的對應位置。
從之前了解到,d3.js 是很適合,且能滿足我們需求的工具。
透過範例學習?
因為提供的方法很多,如何組合使用達到自己想要的效果,參考現有的範例,對我來說會比較有效率。
使用 HTML Elements 展現 d3.js 的 selection.data()
, selection.enter()
, selection.exit()
與 selection.join()
的使用
HTML <section>
根據一組 number
array,插入 <p>
,顯示資料對應文字內容,並增加 threshold 條件,以不同背景色區分小於 threshold 或不小於。
首先,我們會透過 d3.select()
或 d3.selectAll()
選取 element
再透過 .data()
方法對此次選取的 element 綁定 對應順序 的資料
以這個簡單的範例說明一下:
const data = ['a', 'b', 'c'];
d3.selectAll('p')
.data(data)
.text((d, i) => {
return `text: ${d}, at: ${i}`;
});
可以看到,原始 <p>
有五個,但是 data
內容只有三筆
因此在給定 text 內容時,只有前三個有發生改變
在我們的情境範例裡,分別定義 function 處理 update、append 與 remove 的動作
update()
選取 <section id="demo01">
中的所有 <p>
綁定資料 data
(預設為 [1, 2, 13, 5, 34, 3, 1.2, 8]
)
並透過 .text()
設定顯示文字內容
.style()
設定 CSS 樣式
對應的 handler:
renderContent(d, i)
renderTextColor(d, i)
renderBgColor(d, i)
分別接收兩個參數
第一個表示 d
該順位 element 對應的資料,
第二個 i
會傳入順位的 index
function update() {
return d3.select('#demo01')
.selectAll('p')
.data(data)
.text(renderContent)
.style('color', renderTextColor)
.style('background-color', renderBgColor);
}
addEntered()
主要在處理 enter()
回應尚無對應 element 的資料,.append()
新增對應的 element
並再透過 .text()
, .style()
做相同的邏輯處理
function addEntered(selection) {
if (selection) {
return selection.enter()
.append('p')
.style('color', renderTextColor)
.style('background-color', renderBgColor)
.text(renderContent);
}
}
透過 .exit()
則可取得目前沒有對應資料的 element
再使用 .remove()
進行刪除
function removeExited(selection) {
if (selection) {
return selection.exit().remove();
}
}
.join()
而在 d3.js 還有提供一個便利的方法 .join()
可以簡化我們自己分次處理的步驟
以上的邏輯可以簡化成
d3.select('#demo02')
.selectAll('p')
.style('color', renderTextColor)
.data(data)
.join(
enter => enter.append('p'),
update => update,
exit => exit.remove()
)
.style('color', renderTextColor)
.style('background-color', renderBgColor)
.text(renderContent)
可以看到 .join()
參數可以分別對應 enter, update, exit 處理
而 update 與 exit 的部分可省略
update 的處理預設會是 identity function
function (d) {
return d;
}
exit 的動作預設就是進行 selection.remove()
然後,可以再簡化成 .join()
參數僅帶入一個字串,如: .join("p")
即表示 append("p")
最終,上面這一段就可以簡化成:
d3.select('#demo02')
.selectAll('p')
.style('color', renderTextColor)
.data(data)
.join('p')
.style('color', renderTextColor)
.style('background-color', renderBgColor)
.text(renderContent)
使用範例動態變更 data
就可以看出效果
謝謝!
有點有趣吧!
selection.data()
- d3.js API reference
selection.enter()
- d3.js API reference
selection.exit()
- d3.js API reference
selection.join()
- d3.js API reference