**[D3.js](http://d3js.org/)作為一門輕型的可視化類庫,非常便于將數據與web界面元素綁定,實現可視化。樂帝d3.js入門是大體看了一遍[《d3js數據可視化實戰》](http://download.csdn.net/detail/loganyang123/6781653)這本書,D3操作非常類似于jquery的使用,具體體現在兩點:**
- **選擇器模塊都采用CSS3標準**
- **方法可以鏈式調用**
**有了jquery使用基礎,相信再加上以上書籍的例子,調試很容易上手使用D3.js,樂帝目前認為D3.js與jquery區別在于:D3.js獨有的數據結構概念及對SVG操作方便的實現。而深入理解D3原理,以上皮毛的理解就不夠用了。**
**通過閱讀上述書籍樂帝將D3內容劃了幾大塊來分開理解:**
**DOM操作包括:**
- **選擇器模塊(select、selectAll等方法)及如何實現鏈式調用。**
- **節點模塊(append、remove等方法實現)**
- **樣式模塊(attr、style等方法實現)**
**數據綁定相關方法:**
- **data方法**
- **enter、exit等方法**
**比例尺:**
- **值域與輸出域的實現**
**更新、過渡、動畫方法:**
- **transition方法及連帶duration、ease、delay等方法**
**事件:**
- **即綁定事件**
**而后通讀[API](https://github.com/mbostock/d3/wiki/API-Reference)發現對于理解D3.js實現機理有一些關鍵概念,這里關鍵概念涉及selection、data join、group、transition等。而樂帝讀API最大心得在于,在沒有一個大體概念時,千萬不要去觸碰源碼,還是按部就班讀API吧,讀不懂把文檔翻譯一遍就懂了,樂帝是這么做的。**
**這篇文章樂帝主要想討論[data join](http://download.csdn.net/detail/yingyiledi/8074405),但在討論之前,還是需要補充下基本概念。**
**D3.js獨有關鍵概念是selection,樂帝將其翻譯成元素集。它表示從當前文檔獲取的元素數組。它定義了一種數據結構,或者說是對原有dom文檔數據結構的修改。有了元素集之后,就可以對元素執行常規操作了,諸如屬性、樣式、參數、文檔內容等。**
**selection存在的意義在于,是它將頁面元素與數據實現綁定連接,連接的數據又可以產生enter和exit子元素集,因此能夠反映數據的變化,用于添加或移除元素。**
**D3支持方法鏈,操作方法返回值是元素集,從這一句話,我們知道不管如何具體實現鏈式操作,我們知道返回的是元素集就夠了。**
**樂帝最近思考,整個web世界甚至整個世界,由兩種力量驅動:數據與人。而某些高深思想或許能把人也歸結為數據。D3是這兩種力量的典型,數據驅動展現,人驅動交互。脫離人與數據,D3的代碼,只是一堆分離的函數而已。D3緊緊擁抱數據,這就是其最大特點。**
**selection介紹完了,我們開始介紹data join概念。**
**由上所述,D3是數據驅動,而元素集是溝通數據與元素的集合,而data join的概念又是代表數據與元素結合三種狀態的概念,由此看來,data join在D3中屬于核心概念。**
**[《以data join概念思考》](http://bost.ocks.org/mike/join/)這篇文章給出了對data join比較簡明易懂的陳述。**
**在D3中任何時候,數據與頁面元素都有三種關系:數據與元素綁定時,即一一對應,這樣構成的selection狀態叫update selection;沒有元素與之對應的數據構成的selection叫enter selection;沒有數據與之對應的元素構成的selection叫exit selection,它代表將要被移除的元素集。**
**如下圖:**
****
**從字面上理解,D3對數據的推崇可謂毫無節操,有數據沒元素叫enter,有元素沒數據叫exit,代表要被踢出去的元素。**
**下面來看一段代碼例子:**
~~~
svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", 2.5);
~~~
**首先來看第一句svg.selectAll("circle"),它返回空的元素集,因為SVG容器是空的。**
****
****
**然后上述空元素集與數據結合,構成新的元素集,包含enter、update、exit三種狀態。因為元素集是空的,所以update和exit元素集為空,而enter狀態的元素集,則包括五個占位符元素。**

selection.enter后,返回enter元素集,此時為五個綁定數據的對象。

**最后append("circle")一步,使得enter元素集實現與元素一一對應,沒錯構造成了上述的update元素集狀態。**
**由上述例子不難看出,給頁面對象添加子對象不用for循環,而是采取data join的概念,用意在于,在靜態展現的基礎上,對update及exit做微小改動,就可以使它實現動態展現。這就意味著你可以看實時數據,允許數據集合的交互行為及溫和過渡效果展現。**
**任何時候運行代碼,都會重新計算data join,從而保證數據與元素預期的關系。**
**data join允許我們隊指定狀態進行操作,比如,可是設置常數值在enter上,而不是update上,通過重新選擇元素最小化改變原有dom,大大提升渲染效率。**
**下面樂帝展示一個[對各個狀態data join操作](http://bl.ocks.org/mbostock/5779690#index.html)的例子:**
**起始HTML:**
~~~
<div>update</div>
<div>exit</div>
~~~
**起始D3代碼:**
~~~
var dataset =["enter", "hello"];
var key = function(d) {
return d || this.textContent;
}
var duration = 750;
var div = d3.select("body").selectAll("div")
.data(dataset,key);
~~~
**此時data join 三個狀態:**
****
****
**如上圖,不難分析得到,此時data join三狀態:update元素集為空,enter元素集已經有數據綁定,exit元素集有兩個div元素,在第二張圖中innerHTML屬性中,發現恰恰是初始化HTML的兩個div元素,這里采用了鍵函數(key)方法,鍵函數被調用了四次,前兩次調用的是已有的div數據調用,后兩次則是enter狀態元素集數據調用。**
**接下來對exit元素集操作:**
~~~
// // 1. exit
var exitTransition = d3.transition().duration(750).each(function() {
div.exit()
.style("background", "red")
.transition()
.style("opacity", 0)
.remove();//移除節點
});
~~~

**不難得出結論,是原有兩個div將要被移除,在頁面及內存中清除。**
**接下來對enter的操作,這里update為空,故第二步update操作并沒有實際意義。**
~~~
// 2. update
var updateTransition = exitTransition.transition().each(function() {
div.transition()
.style("background", "orange");
});
// 3. enter
var enterTransition = updateTransition.transition().each(function() {
div.enter().append("div")
.text(function(d) { return d; })
.style("opacity", 0)
.transition()
.style("background", "green")
.style("opacity", 1);
});
~~~
****
****
**第三步對enter元素集的操作,使其與元素綁定,并設置成綠色。**
**樂帝在調試期間還發現了另外的情況:**
**一開始js代碼是這樣的:**
~~~
var dataset =["enter", "update"];
var key = function(d) {
return d || this.textContent;
}
var duration = 750;
var div = d3.select("body").selectAll("div")
.data(dataset,key);
~~~
**即dataset有一個元素與已存在的div文本內容相同,又由于鍵函數是處理的是dataset與div文本內容的集合,經過運行如下:**
****
**與之上比較不難發現,這里update元素集有一個元素,enter元素集有一個enter狀態元素。另看exit元素集:**
****
**exit及enter都少了一個對應狀態的對象,這里樂帝猜測d3應該是將每個鍵值函數返回數據進行了查重操作,將兩個“update”文本數據合并成一個update狀態元素了。**
**執行1.exit代碼,此時只有exit文本的div被移除。執行2.update代碼時,update文本的div被設置為背景為橘黃色。最后執行3.enter代碼時,背景色為綠色的div被加入到文檔。**
- 前言
- 前端編程提高之旅(一)----插件
- 前端編程提高之旅(二)----網站常見特效的jquery實現
- 前端編程提高之旅(三)----瀏覽器兼容之IE6
- 前端編程提高之旅(四)----backbone初體驗
- 前端編程提高之旅(五)----寫給大家看的css書
- 前端編程提高之旅(六)----backbone實現todoMVC
- 前端編程提高之旅(七)----marionette實現todoMVC
- 前端編程提高之旅(八)----D3.js數據可視化data join解析
- 前端編程提高之旅(九)----延遲對象
- 前端編程提高之旅(十)----表單驗證插件與cookie插件
- 前端編程提高之旅(十一)----jquery代碼的組織
- 前端編程提高之旅(十二)----position置入值應用
- 前端編程提高之旅(十三)----jquery選擇器
- 前端編程提高之旅(十四)----jquery DOM操作
- 前端編程提高之旅(十五)----jquery事件
- 前端編程提高之旅(十六)----jquery中的動畫
- 前端編程提高之旅(十七)----jquery中表單、表格和ajax
- 前端編程提高之旅(十八)----移動端web流行交互技術方案研究