D3.js入門指南

jopen 8年前發布 | 145K 次閱讀 圖表/報表制作 D3.Js

本章涵蓋以下內容:

◆ 搭建簡易的D3開發環境

◆ 搭建基于NPM(Node Packaged Modules是Node.js的套件管理工具)的開發環境

◆ 理解D3風格的JavaScript

1.1 簡介

本章旨在幫助讀者初步認識并且運行D3.js。其中包含一些基本知識,比如什么是D3.js,如何搭建一個典型的D3.js數據可視化(data visualization)環境。還有一個專門的章節,解釋了一些JavaScript中鮮為人知而D3.js又甚為倚重的特性。

什么是D3?D3是指數據驅動文檔(Data-Driven Documents),根據D3的官方定義:

D3.js是一個JavaScript庫,它可以通過數據來操作文檔。D3可以通過使用HTML、SVG和CSS把數據鮮活形象地展現出來。D3嚴格遵循Web標準,因而可以讓你的程序輕松兼容現代主流瀏覽器并避免對特定框架的依賴。同時,它提供了強大的可視化組件,可以讓使用者以數據驅動的方式去操作DOM。

D3維基(2013年8月)

總的來說,D3是這樣一個特殊的JavaScript庫,它利用現有的Web標準,通過更簡單的(數據驅動)方式來制作炫目的可視化效果。D3.js由Mike Bostock
http://bost.ocks. org/mike/
制作。之前他制作過一個叫Protovis的數據可視化JavaScript庫,如今它已經被D3.js取代。如果想了解更多諸如D3.js制作過程、影響Protovis和D3.js的相關理論這類的信息,可以看看下面的鏈接。而本書將著眼于如何使用D3.js來增強可視化。D3使用JavaScript實現數據可視化的方式比較特別,因此剛開始時可能會讓人覺得有些難懂。我希望通過本書中的大量實例,其中有基礎的,也有高級的話題,能夠幫助大家更好更高效地使用D3。一旦理解了原理,使用D3就可以讓數據可視化的效率和豐富程度產生指數化的增長。

更多有關制作D3的創意,可以參考MikeBostock于2010年在IEEEInfoVis發表的論文Declarative Language Design for Interactive Visualization,鏈接:
[http://vis.stanford.edu/papers/protovis-design] (http://vis.stanford.edu/papers/protovis-design)。

如果對于D3是如何制作的感興趣,建議看看Mike Bostock于2011年在IEEE InfoVis發表的論文D3: Data-Driven Document,鏈接:http://vis.stanford.edu/papers/d3

Protovis,D3.js的前輩,是Mike Bostock和斯坦福可視化組的Jeff Heer制做的,相關鏈接:http:// mbostock.github.io/protovis/

1.2 搭建一個簡易的D3開發環境

在開始使用D3之前,我們要做的第一件事是搭建一個開發環境。這節里,我們將告訴你如何在幾分鐘內搭建一個簡單的D3開發環境。

1.2.1 準備階段

在我們開始前,請確保你已經安裝好一個文本編輯器。

1.2.2 搭建環境

我們先要下載D3.js。

1.我們可以在http://d3js.org/下載最新版本的D3.js,也可以在https://github. com/mbostock/d3/tags下載之前的版本。另外,如果你對開發中的最新D3版本感興趣,可以fork以下的代碼庫https://github.com/mbostock/d3

2.下載并且解壓縮后,我們得到了3個文件:d3.v3.js、d3.v3.min.js和許可證文件。在開發過程中,建議使用d3.v3.js,它可以幫你深入到D3庫中跟蹤調試JavaScript代碼。把d3.v3.js和新建的index.html放在同一個文件夾里,index.html應該包含下面的代碼。

<!-- index.html -->

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8](

    <title>Simple D3 Dev Env</title>

    <script type="text/javascript" src="d3.v3.js](</script>

</head>

<body>



</body>

</html>

如果是直接下載源代碼或者tagged 版本,JavaScript文件的名字會略微不同,叫做d3.js,而非d3.v3.js。

我們已經搭建了一個最簡單的D3數據可視化開發環境。現在可以用我們最喜歡的文本編輯器編輯那個html文件,還可以用瀏覽器打開它來檢查可視化的效果。

可以在這里下載這個例子的源碼:
https://github.com/NickQiZhu/d3-cookbook/tree/master/ src/chapter1/simple-dev-env

1.2.3 工作原理

D3是個相當獨立的程序庫。它不依賴于特定瀏覽器提供的功能以及其他JavaScript庫。實際上,你甚至可以通過簡單的配置,讓D3脫離瀏覽器而在諸如Node.js這樣的環境中運行起來(后面的章節會更詳細地介紹這點)。

如果你的瀏覽器是IE9,建議使用Aight兼容庫和Sizzle selector engine。其中前者可以在這里下載:https://github.com/shawnbot/aight,而后者可以在這里下載:http://sizzlejs.com/

html文件的頭部信息中必須包含如下的編碼格式聲明。

<meta charset="utf-8](

上述聲明會告訴瀏覽器和驗證器在渲染頁面的時候使用哪個字符集,否則瀏覽器就不會正確加載D3了,因為D3使用了一些utf-8里面的特殊字符,比如π。

D3是完全開源的。它使用了它的作者Michael Bostock自己定制的開源許可證。該許可證跟流行的MIT許可證十分類似,僅有一點不同,就是其明確聲明了Michael Bostock的名字未經允許不可用來標記此軟件的派生品,或者用以擴大此軟件的派生品的影響。

1.2.4 更多內容

本書提供了大量的代碼示例。所有的源碼均可在GitHub上下載到(https:// github.com)。

如何獲取源碼

最簡單的方式就是直接克隆Git上的代碼庫(https://github.com.NickQiZhu/ d3-cookbook
)。如果你不打算構建開發環境,跳過這步即可。

如果你不熟悉Git,克隆(clone)很類似于其他的版本控制軟件中的簽出(checking out)。不過克隆所做的并非簡單的簽出。它把所有分支和歷史拷貝到了你的本地機器,也就是把整個代碼庫都拷貝到了本地機器中,所以你完全可以使用這個拷貝過來的代碼庫,在本地環境中離線工作。

如果是首次安裝Git,可以在這里找到Git客戶端下載列表:http://git-scm.com/ downloads
,在這里還有針對不同操作系統的安裝向導:http://git-scm.com/book/ en/Getting-StartedInstalling-Git

另一個使用Git和GitHub的方式是安裝GitHub客戶端,它提供了比Git更多樣的功能。在作者編寫本書時,GitHub僅僅提供了Windows版(http://windows.github. com/
)和Mac OS版(http://mac.github.com/)。

安裝完Git客戶端后,運行下面的命令就可以把本書中所有的代碼都下載到你的機器里。

> git clone git://github.com/NickQiZhu/d3-cookbook.git

如果你打算使用GitHub客戶端(目前還沒有中文版),在https://github.com/NickQiZhu/d3-cookbook頁面點擊Fork按鈕(在頁面的右上角),之后你就可以在GitHub客戶端中看到這個代碼庫了。

1.3 搭建一個基于NPM的開發環境

如果你所在的項目是一個略復雜的數據展示項目,并且使用了為數不少的JavaScript庫,那我們之前討論的那個簡單的解決方案可能就顯得有些褚小杯大,不能勝任了。在這一節當中,我們將展示一個使用了NPM(Node Packaged Modules,實際上就是JavaScript庫的代碼庫管理系統)的更加強大的系統。如果你像我一樣沒有耐心,想更快地嘗試本書最帶勁兒的部分,想學點秘傳招式,完全可以跳過這部分,如果想搭建一個產品開發環境,再回來看看這部分也不遲。

1.3.1 準備階段

我們開始前要先確保NPM已經安裝好了。在安裝Node.js時,NPM作為其中一部分也被安裝了。可以在http://nodejs.org/download/
下載Node.js。選擇適合你操作系統的Node.js,安裝完畢后,在終端窗口運行如下npm命令。

> npm -v 
1.2.14

如果前面的命令輸出了NPM客戶端的版本號,就說明安裝成功了。

1.3.2 搭建環境

安裝完NPM后,讓我們創建一個包描述符文件,以便自動化一些手動安裝的過程。

1.首先,在工程文件夾下,創建名為package.json的文件,包含下面的代碼。

{

   "name": "d3-project-template",

   "version": "0.1.0",

   "description": "Ready to go d3 data visualization project template",

   "keywords": [

     "data visualization",

     "d3"

   ],

   "homepage": "<project home page>",

   "author": {

     "name": "<your name>",

     "url": "<your url>"

   },

   "repository": {

     "type": "git",

     "url": "<source repo url>"

   },

   "dependencies": {

     "d3":"3.x"

     },

   "devDependencies": {

       "uglify-js": "2.x"

   }

}

2.定義package.json文件后,運行下面的命令。

> npm install

1.3.3 工作原理

package.json文件中絕大部分字段僅僅用于提供信息,比如name、description、homepage、author和repository。如果你打算把自己的庫發布到NPM的代碼庫中,就要用到name和version字段。現在,我們在意的是dependencies和devDependencies字段。

◆ dependencies字段描述了你的工程所用到的庫在運行時的依賴,它們可以使你的工程在瀏覽器中正常運行。在這個簡單的例子中,對于d3我們只有一個依賴。d3是D3在NPM庫中發布時使用的名字。版本號3.x標明該工程可以兼容任意大版本為3的發行版,并且NPM應該獲取大版本為3的最新的穩定發布版本來滿足依賴。

D3是個自滿足的庫,運行時對外部是零依賴。然而這并不意味著它不能跟其他JavaScript庫一起運行。作者平時也使用一些其他的庫以便讓自己的工作容易些,比如JQuery、Zepto.js、Underscore.js和Backbone.js。

◆ devDependencies字段描述了庫在開發時(編譯時)的依賴。就是說,這個字段內羅列出來的庫文件僅僅在構建工程時會用到,運行JavaScript工程時用不到它們。

關于NPM包JSON文件更詳細的文檔,可以參考這里https://npmjs.org/doc/json.html

執行npminstall可以自動觸發NPM去下載你工程中所引用的所有依賴,包括遞歸的下載依賴的依賴。所有的依賴庫文件會被下載到node_modules文件夾中,該文件夾位于工程文件夾中的根目錄里。這些完成以后,就可以創建一個HTML文件(跟我們之前創建的那個一樣),HTML文件直接從node_modules/d3/d3.js來引用D3的JavaScript庫。

本節中的代碼可以在此處下載,里面包含了自動構建腳本。

https://github.com/NickQiZhu/d3-cookbook/tree/master/src/chapter1/ npm-dev-env

工程中會有一些麻煩的地方,比如手動下載JavaScript庫以時刻保持它們的版本更新。為了避免這些麻煩,使用NPM是個行之有效的方式,可以拯救你于水火之中。當然,一些聰明的讀者可能已經發現了,使用這個方法可以把我們的“搭建環境”過程直接提升一個檔次。想象一下,你正在構建一個巨大的可視化工程,其中包含了上千行的JavaScript代碼,很明顯我們這里所描述的簡單的搭建方式滿足不了這種情形。因為“模塊化的JavaScript開發”這個話題足夠寫本書了,所以這里我們就不再討論這方面的話題了,我們將把注意力放在數據可視化和D3上。如果你對這方面感興趣,可以看看這一節的代碼,里面演示了如果實現一個模塊化的工程,當然也包含了自動構建腳本。在后面單元測試相關的章節中,我們會針對這個話題多講一些,演示一下,可以在某些方面增強環境,以便運行自動化單元測試。

1.3.4 更多內容

前面提到過,你可以通過瀏覽器直接打開HTML文件來查看可視化的結果,不過這種方式有一些局限性。一但我們需要從其他文件中加載數據(后面的章節中我們就要這么做了,這也很像你平時工作中的情形),由于瀏覽器內建的安全機制,這種方式就不好用了。為了繞開這個安全限制,強烈建議搭建一個本地的HTTP服務器,用該服務器來維護HTML頁面和數據文件,而非直接從文件系統加載。

搭建本地HTTP服務器

由于使用的操作系統不同,HTTP服務器的軟件包不同,搭建HTTP服務器的方法也很不同。這里說幾種比較流行的搭建方式。

Python簡易HTTP服務器

這是我最喜歡的方式。如果你的機器上已經安裝了Python,通常UNIX/Linux/Mac OS發行版上都有,直接運行下面的命令即可。

> python –m SimpleHTTPServer 8888

如果你擁有更新版本的Python,那么你也可以運行如下命令。

> python –m http.server

這個python小程序可以啟動一個HTTP服務器,然后你就可以訪問該程序所在文件夾中的所有文件。這是目前所有操作系統中運行HTTP服務器最簡單的方式。

如果你的機器沒有安裝python,可以在這里下載http://www.python.org/getit/。現在所有的操作系統,諸如Windows、Linux,還有Mac,都支持它。

Node.js HTTP服務器

安裝Node.js之后(前面的小節中所做的搭建開發環境練習,包含了相應的內容),就可以搭建http-server模塊了。與Python簡易HTTP服務器類似,通過該模塊,你可以從任意的文件夾快速啟動一個輕量級的HTTP服務器。

安裝http-server模塊。

> npm install http-server –g

命令中的-g參數會把http-server模塊設置為全局的,這樣你就可以在命令行里直接使用http-server命令。完成此步后,可以通過下面的命令,在任意文件夾內啟動一個服務器。

> http-server .

該命令可以啟動一個Node.js驅動的HTTP服務器,默認端口號是8080,也可以用 -p 參數指定一個端口號。

如果是在Linux/UNIX/Mac的操作系統中運行該命令,需要用sudo模式或者root權限來運行。

1.4 理解D3風格的JavaScript

對于那些習慣了過程式或者面向對象式的JavaScript風格的人來說,他們會感覺D3使用函數式的JavaScript編程風格有一些奇怪。本節會涵蓋一些JavaScript中函數式編程最根本的功能性概念,以便對D3有個基本的理解,將來可以用D3的風格來編寫可視化工程的代碼。

1.4.1 準備階段

在瀏覽器中打開下面文件的本地副本。

https://github.com/NickQiZhu/d3-cookbook/blob/master/src/ chapter1/functional-js.html

1.4.2 開始編程

現在讓我們嘗試更深入一點,了解一下JavaScript函數式方面的內容。請看下面的代碼段,

function SimpleWidget(spec) {

  var instance = {}; // <-- A



  var headline, description; // <-- B



  instance.render = function () {

    var div = d3.select('body').append("div");



    div.append("h3").text(headline); // <-- C



    div.attr("class", "box")

    .attr("style", "color:" + spec.color) // <-- D

      .append("p")

      .text(description); // <-- E



    return instance; // <-- F

  };



  instance.headline = function (h) {

    if (!arguments.length) h; // <-- G

      headline = h;

    return instance; // <-- H

  };



  instance.description = function (d) {

    if (!arguments.length) d;

      description = d;

    return instance;

  };



  return instance; // <-- I

}



  var widget = SimpleWidget({color: "#6495ed"})

    .headline("Simple Widget")

    .description("This is a simple widget demonstrating functional javascript.");

  widget.render();

這段代碼在頁面上生成了下面圖片中的示例。

函數式JavaScript簡單示例

1.4.3 工作原理

盡管非常簡單,但是不可否認,這段示例中的代碼跟D3風格的JavaScript非常相似。這不是巧合,在JavaScript編程范型中,這叫做函數對象。跟很多有趣的話題一樣,這個話題也能寫一本書。不過在本節中,我會嘗試盡量多講一些這種特殊范型的東西,好讓不理解D3語法的讀者也能創建這種風格的庫文件。正如D3的維基頁面上所講的那樣,這種函數式編程風格給D3帶來了很大的便利性。

D3的函數風格,使得多種組件插件之間的代碼重用成為現實。

{--:}D3維基(2013年8月)

函數即對象

JavaScript中的函數是對象。跟其他的對象一樣,函數只是鍵值對的一個集合。函數對象跟普通對象的區別就是,函數可以執行,函數還帶有兩個隱藏的屬性,即函數上下文和函數代碼。這兩個隱藏屬性有時候會給你一個大大的“意外驚喜”,如果你有著很深的過程式編程背景,這點可能更明顯。不過這也是我們最需要注意的關鍵點了,要了解一下D3使用函數的奇怪方式。

JavaScript的大部分特性都顯得有些不夠“面向對象”,不過在函數對象這方面,JavaScript跟其他語言相比較應該更勝一籌。

現在我們心里有了這樣的概念,那就再看一遍這段代碼。

var instance = {}; // <-- A



var headline, description; // <-- B



instance.render = function () {

  var div = d3.select('body').append("div");



  div.append("h3").text(headline); // <-- C



  div.attr("class", "box")

    .attr("style", "color:" + spec.color) // <-- D

    .append("p")

    .text(description); // <-- E



  return instance; // <-- F

};

在A、B和C行,我們可以看到instance、headline和description都是SimpleWidget這個函數對象的內部私有變量。可是render函數卻是instance對象的一個方法,并且被定義為對象字面量。函數本身也是對象,它可以存儲在對象/函數、其他變量、數組里,也可以作為函數參數。運行SimpleWidget的結果就是I行所寫的,返回一個instance對象。

function SimpleWidget(spec) {

...

  return instance; // <-- I

}

render函數中用到了一些我們還沒講過的D3中的函數,不過我們現在先不管它們,后面的章節中我們會詳細講解的。它們也只是渲染了一些可視化的東西,跟我們目前的話題沒有太多的關系。

下載示例代碼

可以從http://www.packtpub.com下載你購買的所有Packt圖書的示例代碼。如果是在其他地方購買的話,可以在http://www.packtpub.com/support注冊一下,代碼會通過郵件發送給你。

靜態變量作用域

好奇的讀者可能會問,這個示例中的變量作用域到底是怎樣的啊?看上去好奇怪,render函數不僅訪問了instance、headline和description,還訪問了從SimpleWidget傳進來的spec變量。這個怪異的變量作用域其實是由一個簡單的靜態作用域規則來決定的。可以把這個規則想象成這樣:當查找一個變量引用時,該變量先被當成是一個本地變量。如果沒有找到變量聲明(比如C行中的headline),就繼續在父對象里找(本例中,SimpleWidget函數就是靜態的父對象,headline變量的聲明在B行)。如果還是沒有找到,就不斷地重復這個過程,遞歸地去父對象里查找,一直到全局變量的定義那層。如果最后還是沒有找到,就針對該變量生成一個引用錯誤。這樣的作用域行為與大多數流行語言(諸如Java、C#)中的變量處理方式大不相同,可能需要一段時間適應,要是你覺得不習慣的話,也不用擔心,練得多了,就習慣了。

對于有Java和C#背景的人,需要再提醒一下,JavaScript沒有實現塊作用域(block scoping)。我們這里描述的靜態作用域規則,僅僅適用于函數/對象級別,不適用于塊級別。

for(var i = 0; i < 10; i++){

  for(var i = 0; i < 2; i++){

    console.log(i);

  }

}

對于上面這段代碼,你可能覺得它會打印20個數字。其實在JavaScript里,這段代碼會陷入到無限循環。因為JavaScript沒有實現塊級別的作用域,所以里面那層循環的i跟外面那層循環的i是同一個變量。于是里面的循環改變了i的值,導致外面的循環永遠不會結束。

跟流行的原型編程中的偽類模式相比,這樣的模式通常被稱作函數模式。函數模式的優點是提供了更好的信息隱藏和封裝。因為只能通過靜態作用域規則里限定的那些嵌套定義的函數來訪問私有變量(我們示例中的headline和description),所以SimpleWidget函數返回的對象就更加靈活,也更加健壯。

如果我們用函數式風格創建對象,并且該對象所有的方法都沒有用this,那這個對象就是持久(durable)的 {![譯者注:如果一個對象不包含外部可見的成員數據,并且其方法不會使用this,那么這個對象就是持久的.]}。持久對象就是許多功能行為的集合了。

{--:}(Crockfort D. 2008年)

可變參數函數

在G行有些奇怪的東西。

instance.headline = function (h) {

  if (!arguments.length) h; // <-- G

  headline = h;

  return instance; // <-- H

};

你可能會問,G行的這個arguments從哪里來的?這個例子中從來沒有定義過它。其實這個arguments是內建的隱藏參數,并可在函數執行時直接使用。arguments是一個數組,它包含了所在函數的全部參數。

實際上,arguments本身并不是JavaScript的數組對象。雖然它有length 屬性,并可以用索引下標訪問每個元素,但是它沒有JavaScript中數組對象的那么多方法(比如slice、concat)。如果你想在arguments上使用JavaScript數組對象的方法,需要這樣:

var newArgs = Array.prototype.slice.apply (arguments);

把這個隱藏的參數和JavaScript可以在函數聲明時省略參數的功能結合起來,就可以寫出instance.headline這種不需要指定參數個數的函數。在本例中,我們可以傳一個參數h,也可以不傳。因為如果沒有傳進來參數,arguments.length就返回0,headline函數就返回h,如果h有值,就變成了一個賦值操作。為了說清楚,我們看看下面這段代碼。

var widget = SimpleWidget({color: "#6495ed"})

    .headline("Simple Widget"); // 給headline賦值

console.log(widget.headline()); // 輸出"Simple Widget"

這里你可以看到headline在參數不同的情況下,可以分別作為setter和getter(賦值操作和取值操作)。

函數級聯調用

這個例子另一個有趣的地方是函數的級聯調用。這也是D3庫提供的一個主要的函數調用方式,因為D3庫中的大多數函數都設計成了這種鏈式的結構,以便能提供簡潔的、上下文連貫的編程接口。如果你理解可變參數函數的概念,就很好理解這個了。可變參數函數(比如headline函數)能同時作為setter和getter,當其作為setter時,返回instance對象,這就使得你可以在返回的instance上立即執行另一個函數,此即鏈式調用。

看下面這段代碼。

var widget = SimpleWidget({color: "#6495ed"})

  .headline("Simple Widget")

  .description("This is ...")

  .render();

這個例子中,SimpleWidget函數返回了instance對象(如I行所示)。那么,headline函數在這里是一個setter,同時也返回一個instance對象(如H行所示)。description函數執行后也返回instance對象。最后調用了render函數。

現在我們已經大概了解了JavaScript的函數式風格,有了一個可工作的D3開發環境,也準備好了使用D3提供的豐富功能來一試身手。在開始前,我還想講幾個比較重點的事情,即如何尋找、分享代碼以及有困難時如何獲取幫助。

1.4.4 更多內容

先讓我們看幾個有用的東西。

尋找、分享代碼

在D3眾多值得稱贊的亮點中,有一個是比其他可視化工具提供了更加豐富的示例和教程,你可以從中汲取靈感。當我創建自己的開源可視化圖表項目,還有寫作這本書的時候,我在那些資源中獲得了大量的靈感。我會在那些最棒的例子里,挑出一些列個清單出來。這個清單雖然不是百科全書,但卻是個不錯的入門參考。

◆ D3 gallery(https://github.com/mbostock/d3/wiki/Gallery),這里有不少有趣的例子,可以幫你在線查找D3的使用方法,有各種各樣的圖表、特定的技術,還有一些跟其他工具一起實現的示例。

◆ BioVisualize(http://biovisualize.github.io/d3visualization),算是一個分門別類的D3 gallery,可以幫你快速地在線查找你想要的例子。

◆ D3教程(https://github.com/mbostock/d3/wiki/Tutorials),有很多朋友不斷更新提供的教程、討論和文檔,給你細致地演示了D3的使用方法。

◆ D3插件(https://github.com/d3/d3-plugins),可能有些你需要的功能是D3沒有的。在你自己實踐之前,先查查D3的插件庫,它提供了各種常用的、不常用的功能。

◆ D3 API(https://github.com/mbostock/d3/wiki/API-Reference)是很不錯的文檔。這里你能找到D3所提供的全部功能、屬性的詳細說明。

◆ Mike Bostok's Blocks(http://bl.ocks.org/mbostock)是個D3示例站點,作者是Mike Bostock,這個站點里有很多有趣的例子。

◆ JS Bin(http://jsbin.com/ugacud/1/edit)是個在線的D3測試、實驗環境。你可以很容易地通過該工具跟其他人分享一些簡單的代碼。

◆ JS Fiddle(http://jsfiddle.net/qAHC2/)跟JS Bin差不多,也是一個在線JavaScript代碼分享平臺。

如何獲取幫助

即便有了這些例子、教程,還有書,你在實踐的過程里仍然會遇到問題。不過D3有數目龐大并且活躍度不錯的社區。一般情況,簡單地“google”一下,就能找到滿意的答案。要是沒有也不用擔心,D3還有強大的社區支持。

◆StackOverFlow上的D3.js(http://stackoverflow.com/questions/ tagged/d3.js):StackOverflow是最著名的免費技術主題問答社區站點,D3在StackOverflow上有專門的頁面,可以幫你找到專家,快速地解決你的問題。

◆ D3 Google討論組(https://groups.google.com/forum/?fromgroups#! forum/d3-js):這是個官方的用戶組,不單單有D3,還有一些其他相關的庫。

本文摘自:《D3.js數據可視化實戰手冊》

QQ截圖20150206132646.png
QQ截圖20150206132646.png

來自: http://www.jianshu.com/p/c3800c61d2fb

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!