iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 23
2
Modern Web

「小孩才做選擇,我全都要。」小白也能輕鬆瞭解的 Vue.js 與 D3.js 。系列 第 23

[ D3.js ] 資料選取 d3-selection 與資料綁定 Joining Data

  • 分享至 

  • xImage
  •  

學習完 Vue 之後,想要透過單元測試守護你的專案,但又不知道從何起手?
別擔心,快來訂閱作者最新系列文 《小白也能輕鬆瞭解的 Vue3 單元測試!》
讓你的 Vue 專案更上一層樓!


資料選取

在繪製圖表前,首先要掌握 D3.js 如何 選取元素,接著才能將要修改的資料輸出到選取的元素裡。而 D3.js 選取元素的部分與 jQuery 是同一套作法,也就是以往撰寫 CSS 相關程式時,開發者怎麼比對元素,就是以那一套為基準即可!

例如選取 id 為 test 的元素則是使用 #test 作為選取器。

這裡假定開發者已稍微瞭解基礎的 CSS 選擇器(selector ),如果對於 CSS 選擇器還不熟悉的話,可以透過這個 有趣的盤子遊戲 來快速學習 CSS 選擇器!

而 D3.js 目前提供了兩種方法以供開發者捕捉元素:

  • d3.select :捕捉符合選取器的第一個元素
  • d3.selectAll :捕捉符合選取器的所有元素

使用 D3.js 選取器捕捉到的元素(選擇集),後續則可以繼續透過 D3.js 的方法來進行 DOM 的操作修改,例如將選取到的 p 元素中所有的文字都改成紅色:

JavaScript 部分:

d3.selectAll('p').style('color','red')

若想要測試語法,除了使用前面章節提到的開發環境建置之外,你可以直接在 D3.js 官方網站 開啟開發者工具(DevTools)直接測試!

資料綁定

現在我們已經可以透過 D3.js 選取到資料集了,然而選取集上的元素裡面並沒有帶任何的資料,我們得透過 D3.js 提供的資料綁定方法將資料綁定於選取的資料集中,目前 D3.js 提供了兩種方法供開發者使用,接著就來介紹一下他們用法與差異:

  • selection.datum
  • selection.data

datum

datum 的用法有兩種,一種是未帶參數直接使用其函式,如d3.selection.datum() 將會返回選取集所綁定的數據資料

第二種就是將數據資料當作參數帶入函式當中,如d3.selection.datum('數據資料') 將會把數據資料綁定到選取集中每一個元素身上,而數據資料綁定的類型除了undefinednull值之外都可以賦予該元素

let d3datum = d3.selectAll('p').datum('綁定資料')

以 D3.js 官網觀察,透過 console.log(d3datum) 可以很清楚的看到該選取集元素物件屬性中含有一個 __data__ 的欄位,而這個欄位就是 D3.js 賦予這個元素的資料位置。(如下圖)

https://ithelp.ithome.com.tw/upload/images/20190925/20119062yg0GqFbt7u.jpg

綁定資料後可以接著以 D3.js 的提供方法來使用這筆資料,例如將透過 text 函式將內容更換為所綁定的資料:

let d3datum = d3.selectAll('p')
                .datum('綁定資料')
                .text(function(d){
                    return d
                })

所有被綁定到的資料透過 text 內函式的第一個傳送參數d)替換進去,而 text 用法則是將返回(return)的數值替換為該文字節點的內容。

註:部分 D3.js 提供的方法第一個傳送參數皆為元素所綁定的資料data),第二個則為資料集的索引值index)。

最後就會看到 D3.js 官方網站變成了這樣:

https://ithelp.ithome.com.tw/upload/images/20190925/20119062XFSQrvYrxe.jpg

要注意的是,datum 在綁定資料的過程時,有一個特性是若透過被綁定資料的元素來新增一個新的元素時,其子元素也會繼承父元素的數據資料__data__)。

data

data 使用方法與 datum 相同,而不一樣的是其綁定資料的邏輯是會按照陣列索引值指定的方法來依序的綁定資料到元素上。

例如網站上目前有三個<div>元素:

<section>
    <div></div>
    <div></div>
    <div></div>
</section>

若是有一筆數據資料為['a','b','c'],透過 data、datum 方法綁定後:

let sampleData = ['a','b','c']

D3.selectAll('div').data(sampleData)

接著再觀察 __data__ 將會得到:

\ 透過 data 綁定得到的__data__ 透過 datum 綁定得到的__data__
第一個 <div> a ['a','b','c']
第二個 <div> b ['a','b','c']
第三個 <div> c ['a','b','c']

由此可見,data 所綁定的數據資料的邏輯會依照其綁定的元素集下去做分配,因此若是綁定的元素數量與數據資料的數量不同時,將會被 D3.js 歸納為以下三種邏輯:

  • update : 輸入該筆數據資料時若還有元素可供資料輸入,該筆輸入的資料會被歸納 update 資料。
  • enter : 輸入該筆數據資料時若沒有元素可供資料輸入,該筆輸入的資料會被歸納 enter 資料。
  • exit : 若是資料已經輸入完了,還有剩餘被綁定的元素,則剩下的元素將會被歸納為 exit 資料。

例如被綁定的元素有三個,而數據資料有四筆時:

元素 數據資料 整筆被綁定的元素會被歸納為
第一筆被綁定的元素 a update 資料
第二筆被綁定的元素 b update 資料
第三筆被綁定的元素 c update 資料
d enter 資料

例如被綁定的元素有四個,而數據資料只有兩筆時:

元素 數據資料 整筆被綁定的元素會被歸納為
第一筆被綁定的元素 a update 資料
第二筆被綁定的元素 b update 資料
第三筆被綁定的元素 exit 資料
第四筆被綁定的元素 exit 資料

透過 d3.selection.data() 返回的數值中,可以看到一個屬於 update 資料的陣列物件以及 enter 函式與 exit 函式分別可以找到對應類型的資料,而這個類別資料的重要性在於,繪製圖型時我們需要透過這些類型的資料來判斷那些是我們要更動的資料或哪些元素是我們不需要的。若開發者能夠分清楚這三種數據資料的差別,對往後的資料處理上將會更加的容易!

而我們今天已經能夠透過 D3.js 選取到資料集以及將資料綁定給元素了,並且我們還能夠判斷出哪些資料是屬於要更新 update 、進入 enter 以及離開 exit,接下來明天我們將會活用這三個類別資料來進行資料處理,就讓我們明天見啦!

橘橘舉頭望明月
https://ithelp.ithome.com.tw/upload/images/20190925/20119062iIohG6Xuvh.jpg

9/26 更新

不排斥英文文章閱讀的話,D3.js 作者本人 Mike Bostock 也有一篇文章詳細介紹了 D3.js 中 選擇集的運作,並且還有提供視覺動畫解釋之間的關係。


上一篇
[ D3.js ] SVG 圖形繪製補充
下一篇
[ D3.js ] 資料圖形繪製與重繪 enter(), exit() & update()
系列文
「小孩才做選擇,我全都要。」小白也能輕鬆瞭解的 Vue.js 與 D3.js 。37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

1
Kuro Hsu
iT邦新手 1 級 ‧ 2019-09-26 13:44:01

leave ? 應該是 exit 吧?

ShawnL iT邦新手 1 級 ‧ 2019-09-26 14:18:13 檢舉

感謝大大 Kuro Hsu 已修正內容。

0
tsai10n
iT邦新手 5 級 ‧ 2019-09-26 23:38:37

既然前面講Vue了,有沒有考慮不用d3-selection,而是直接用vue template?

ShawnL iT邦新手 1 級 ‧ 2019-09-27 02:11:06 檢舉

tsai10n 你好:
我在最新的文章中有寫一章 D3.js in Vue.js,主要是透過 Vue.js 生命週期監聽 更改資料來驅動 Vue.js 的執行。

template 的部分由於個人礙於時間上的考量,原本文章預計是在後面解說 Vue-cli 時,直接以 .vue 檔的架構來寫成元件的模樣,若時間允許會再回來補上 JavaScript 的 template 版本,非常感謝你的建議。

我要留言

立即登入留言