原文連接git
本人所有譯文地址github
當你想要使用D3繪製散點圖時,你須要在圖中建立多個circle
來表達你的數據信息。這時你會發現D3根本沒有給你一個建立多個DOM元素的原生方法。數組
雖然它爲咱們提供了.append
這個方法來建立單個元素。app
svg.append('circle')
.attr("cx", d.x)
.attr("cy", d.y)
.attr("r", 2.5)
複製代碼
但這樣每次只能建立一個circle
元素,然而咱們須要一堆圓來傳達數據內容。在你想要使用for
循環或者暴力解決這個問題前,請理解下面例子中的鏈式方法的意義。svg
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);
複製代碼
上面的代碼作了咱們想作的:爲每一個數據元素建立了對應的circle
元素,賦值x
、y
屬性定位到對應位置。在上面的代碼中selectAll('circle')
作了什麼?爲何咱們須要選擇不存在的元素來建立新的元素?spa
這是約定俗成的寫法,與其告訴D3如何來作事,不如直接說你想要什麼。咱們想要circle
元素來對應數據信息,每一個圓對應一份數據元素。爲此咱們告訴D3咱們須要一個與數據對應的cirlce
元素選擇集,而不是要求D3建立circle
元素。這個思想就是咱們本次所要說明的數據綁定。翻譯
當數據綁定到已存在元素上時,會建立update
選擇集。其他未被綁定到元素上的數據會建立enter
選擇集,表示缺失的元素。一樣,已存在且未被綁定到數據的元素會返回exit
選擇集,一般表示須要被刪除的元素。code
下面咱們經過解釋代碼來一步步說明enter-append
模式數據綁定的意義:cdn
svg.selectAll('circle')
返回一個全新的空選擇集,由於SVG容器中是空的,這個選擇集的父元素節點就是SVG容器自己。enter
、update
、exit
。由於這些選擇集如今是空的,因此返回的update
、exit
也是空的。可是由於已經綁定數組了,因此此時enter
選擇集包含對應每一個數據元素的佔位符。selection.data
方法時會返回update
選擇集,enter
和exit
選擇集不會返回。執行selection.enter
則會返回對應的enter
選擇集。enter
選擇集上執行selection.append
方法會在SVG容器中添加缺失的元素。如今在SVG容器中,每一個數據項都有一個對應的circle
元素存在了。數據綁定的本質是先聲明選擇集和數據之間的關係,而後經過enter
、update
和exit
三個狀態來具體實現這個關係。blog
爲何這麼麻煩?就不能提供一個直接建立多元素的原生方法嗎?數據綁定的好處在於它能夠泛化。當以上代碼只是處理了enter
選擇集,這對靜態可視化來講已經足夠了。你也能夠擴展代碼讓它支持動態圖表,只須要稍微修改下update
和exit
選擇集的操做。這意味着你能夠可視化實時數據,容許交互探索,並能夠平穩過分數據的變化。
下面是一個小例子:
var circle = svg.selectAll("circle")
.data(data);
circle.exit().remove();
circle.enter().append("circle")
.attr("r", 2.5)
.merge(circle)
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
複製代碼
每當運行此代碼時,它將從新計算數據綁定並維護元素和數據之間所需的對應關係。若是此時新數據集數量少於老數據集時,剩餘的元素將出如今exit
選擇集當中而且會被刪除。若是新數據集中元素數量多於老數據集時,enter
選擇集會爲這些數據生成佔位符,並建立對應的circle
元素。若是新數據集和老數據集數量相同,則現有元素會更新到新數據集對應的位置,沒有元素增減。
以數據綁定的思想來編寫意味着你的代碼更具備聲明性:你能夠處理這三種狀態無需任何條件語句或循環。相反,你能夠描述元素應該如何與數據相對應。若是返回的enter
、update
、exit
選擇集爲空,對應的代碼是不會執行的。
若是有須要,數據綁定還容許你操做元素爲特定狀態。好比你能夠設定給enter
選擇集的元素設定屬性(例如圓半徑,定義'r
'屬性)。
circle.enter().append("circle")
.attr("r", 0)
.transition()
.attr("r", 2.5);
複製代碼
本文翻譯自D3做者Mike Bostock2012年的博文,翻譯本文的目的是但願能夠從做者自己的角度來理解爲何要用綁定數據和元素的方式來完成建立多SVG元素的操做。