開始學習D3.js,網上沒有找到很滿意的中文教程,可是發現了一個很好的英文教程,講解的很是詳細。從一個初始簡單的HTML網頁開始,逐步加入D3.js的應用,幾乎是逐句講解。學習的時候,就順便翻譯成中文,來和你們分享 。固然,更推薦看英文原文教程了,點擊這裏。javascript
簡單例子html
在這個例子中,你將會使用D3.js來把數據綁定到簡單網頁的DOM元素(DOM element)上。java
如今開始了!下面是一個簡單的HTML網頁:數組
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <script type="text/javascript" src="d3.v3.min.js"></script> 5 </head> 6 <body> 7 </body> 8 </html>
打開Chrome的開發者工具進入JavaScript控制檯,觀察元素查閱器(inspector)。app
在JavaScript控制檯上輸入下面這段代碼:dom
1 var theData = [1,2,3] //一個數組 2 3 var p = d3.select("body").selectAll("p") 4 .data(theData) 5 .enter() 6 .append("p") 7 .text("hello");
結果以下:工具
恭喜你!你如今已經成功使用D3.js把一些數據綁定到了DOM元素上了!學習
D3.js 的 SelectAll 方法spa
在上面那段Javascript代碼中,有一個方法是:.selectAll("p").翻譯
D3.js中的selectAll方法使用的是CSS3中的選擇器來獲取DOM元素。不一樣於select方法(該方法獲取的是第一個目標元素),而selectAll方法選擇的是全部匹配的元素。
可是!!初識的HTML網頁中並不包含<p>,也就是說,該方法返回的是一個空的選擇結果(selection)。
在此以後呢,咱們又使用了.data(theData)和.enter()把數據綁定到這個空的選擇結果中,這是怎麼回事呢?
D3.js的data操做符(operator)
在上面那段Javascript代碼中,接下來的是.data(theData)。
這個data操做符是把一個數據數組(多是數值數組、對象數組或者別的什麼數組)與當前的選擇結果聯繫(join)起來。
在本例中,並無提供key值,所以theData數組中的每個元素都被分配到當前選擇結果中的一個元素上。數組中第一個元素,也就是數字1,被分配到第一個<p>元素,第二個元素2被分配到相應的第二個<p>,以此類推。
可是!!正如上面說過的,初識網頁中根本沒有一個<p>,那麼到底怎麼回事?
D3.js的Virtual Selections
與D3.js中的其餘方法不一樣的是,data操做符返回的是三個Virtual selection。
這三個virtual selection是enter,update以及exit。
enter選集:對全部缺失的元素以佔位符placeholder替代。
update選集:包含現有的元素,並綁定到數據
剩下的元素最終都會出如今exit選集中,並被移除。
因爲從下面代碼獲得的選集是空的:
1 d3.select("body").selectAll("p")
所以,虛擬enter選集中包含的是<p>元素的佔位符。
咱們將會的後面章節繼續討論虛擬選集enter,update,exit,而如今,咱們就把焦點放在enter虛擬選集上。
若是想要了解更多虛擬選集(virtual selection)知識,這裏推薦一篇經典文章:Mike Bostock 寫的"Thinking with Joins"。
D3.js的enter方法
D3.js的enter方法從data操做符返回一個虛擬選集。這個方法只能做用於data操做符,由於只有data操做符返回的是三個虛擬選集。
1 var p = d3.select("body").selectAll("p") 2 .data(theData) 3 .enter()
正如前面所說,對於數組中的數據元素,若是缺乏與之對應的DOM元素,那麼就會有一個佔位符來頂替,而enter方法返回的就是這些佔位符集合的引用(reference)。
獲得這個引用以後,就能對該集合操做了。
在這裏須要特別注意的是,這個引用後只能連接(chaining)append,insert以及select操做符,經過他們來操做該引用所指向的集合。
在這些操做符連接到.enter()選集,咱們就能夠像處理其餘選集那樣,來對其內容進行更改。
D3.js的Append操做符
咱們再次來看看這段代碼:
1 var p = d3.select("body").selectAll("p") 2 .data(theData) 3 .enter() 4 .append("p")
咱們把.append("p")做用於.enter()選集之上。
對上一步中所產生的每一個佔位符(placeholder),都有一個P元素插入進去。
因爲在咱們的數據數組中,有三個數據元素(1,2,3),可是在網頁中,沒有一個P元素,因此.append("p")就建立並加入了3個段落元素。
在本例中,當咱們對.enter()的選集使用了append操做符以後,返回的是一個具備3個HTML段落元素的選集。
D3.js的text操做符
若是咱們把以前那段Javascript代碼作一改變,去掉text操做符:
1 var theData = [1,2,3] 2 3 var p = d3.select("body").selectAll("p") 4 .data(theData) 5 .enter() 6 .append("p");
咱們獲得的結果是:
咱們注意到,與以前的那張圖片相對比,這裏的段落都是不包含任何文字的。
text操做符對全部被選擇的元素的textContent屬性進行賦值。
在本例中,.text("hello"),值是「hello」。由於咱們的選集中有3個<p>元素,所以每一個元素都被插入了「hello」。
數據到哪兒去了?
在本文的例子中,一開始就是一個Javascript的數據數組:
1 var theData = [1,2,3]
但是到最後,咱們獲得了三個內容是「hello」的段落。
那麼對於數字1,2,3,發生了什麼?
D3.js的data操做符回顧
讓咱們經過一個簡單的例子,在javascript控制檯中再次觀察下data操做符:
1 console.log(d3.select("body"));
當咱們點擊回車,而後點擊向下的箭頭來查看「body」的屬性,你看到的應該以下:
在0:<body>這一行下面,你能夠看到HTML中body元素的屬性。
如今,咱們在Javascript控制檯運行一下下面這句代碼,咱們加入了.data()操做符。
1 console.log(d3.select("body").data([1]));
咱們的數據出如今名爲_data_的屬性中:
當咱們把數據分配到一個元素上時,這個數據被存儲到_data_屬性中。
到此,數據能夠經過_data_屬性被再選。這也就是咱們所說的數據綁定到Dom元素(Binding Data to Dom Elements)。
初始例子回顧
回顧咱們在頁面最上方提到的那個例子,如今咱們使用console.log()來查看數據綁定到什麼地方了:
1 var theData = [1,2,3] 2 3 var p = d3.select("body").selectAll("p") 4 .data(theData) 5 .enter() 6 .append("p") 7 .text("love") 8 9 console.log(p);
結果是:
從上圖能夠看出3個段落元素被添加。
你還會看到最後一個(第三個)段落元素的_data_屬性值爲3,這個值就是來自咱們的數據集theData!