本章旨在幫助讀者初步認(rèn)識(shí)并且運(yùn)行D3.js,。其中包含一些基本知識(shí),比如什么是D3.js,,如何搭建一個(gè)典型的D3.js數(shù)據(jù)可視化(data visualization)環(huán)境,。還有一個(gè)專門的章節(jié),解釋了一些JavaScript中鮮為人知而D3.js又甚為倚重的特性,。 什么是D3,?D3是指數(shù)據(jù)驅(qū)動(dòng)文檔(Data-Driven Documents),,根據(jù)D3的官方定義:
總的來說,,D3是這樣一個(gè)特殊的JavaScript庫,它利用現(xiàn)有的Web標(biāo)準(zhǔn),,通過更簡單的(數(shù)據(jù)驅(qū)動(dòng))方式來制作炫目的可視化效果,。D3.js由Mike Bostock 更多有關(guān)制作D3的創(chuàng)意,,可以參考MikeBostock于2010年在IEEEInfoVis發(fā)表的論文Declarative Language Design for Interactive Visualization,鏈接: 如果對(duì)于D3是如何制作的感興趣,,建議看看Mike Bostock于2011年在IEEE InfoVis發(fā)表的論文D3: Data-Driven Document,鏈接:http://vis./papers/d3,。 Protovis,,D3.js的前輩,是Mike Bostock和斯坦??梢暬M的Jeff Heer制做的,,相關(guān)鏈接:http:// mbostock./protovis/ 1.2 搭建一個(gè)簡易的D3開發(fā)環(huán)境在開始使用D3之前,我們要做的第一件事是搭建一個(gè)開發(fā)環(huán)境,。這節(jié)里,,我們將告訴你如何在幾分鐘內(nèi)搭建一個(gè)簡單的D3開發(fā)環(huán)境。 1.2.1 準(zhǔn)備階段在我們開始前,,請(qǐng)確保你已經(jīng)安裝好一個(gè)文本編輯器,。 1.2.2 搭建環(huán)境我們先要下載D3.js。 1.我們可以在http:///下載最新版本的D3.js,,也可以在https://github. com/mbostock/d3/tags下載之前的版本,。另外,如果你對(duì)開發(fā)中的最新D3版本感興趣,,可以fork以下的代碼庫https://github.com/mbostock/d3,。 2.下載并且解壓縮后,我們得到了3個(gè)文件:d3.v3.js、d3.v3.min.js和許可證文件,。在開發(fā)過程中,,建議使用d3.v3.js,它可以幫你深入到D3庫中跟蹤調(diào)試JavaScript代碼,。把d3.v3.js和新建的index.html放在同一個(gè)文件夾里,,index.html應(yīng)該包含下面的代碼。 <!-- 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文件的名字會(huì)略微不同,,叫做d3.js,而非d3.v3.js,。 我們已經(jīng)搭建了一個(gè)最簡單的D3數(shù)據(jù)可視化開發(fā)環(huán)境?,F(xiàn)在可以用我們最喜歡的文本編輯器編輯那個(gè)html文件,還可以用瀏覽器打開它來檢查可視化的效果,。 可以在這里下載這個(gè)例子的源碼: 1.2.3 工作原理D3是個(gè)相當(dāng)獨(dú)立的程序庫。它不依賴于特定瀏覽器提供的功能以及其他JavaScript庫,。實(shí)際上,你甚至可以通過簡單的配置,,讓D3脫離瀏覽器而在諸如Node.js這樣的環(huán)境中運(yùn)行起來(后面的章節(jié)會(huì)更詳細(xì)地介紹這點(diǎn)),。 如果你的瀏覽器是IE9,建議使用Aight兼容庫和Sizzle selector engine,。其中前者可以在這里下載:https://github.com/shawnbot/aight,,而后者可以在這里下載:http:///。 html文件的頭部信息中必須包含如下的編碼格式聲明,。 <meta charset="utf-8]( 上述聲明會(huì)告訴瀏覽器和驗(yàn)證器在渲染頁面的時(shí)候使用哪個(gè)字符集,,否則瀏覽器就不會(huì)正確加載D3了,因?yàn)镈3使用了一些utf-8里面的特殊字符,,比如π,。 D3是完全開源的。它使用了它的作者M(jìn)ichael Bostock自己定制的開源許可證,。該許可證跟流行的MIT許可證十分類似,,僅有一點(diǎn)不同,就是其明確聲明了Michael Bostock的名字未經(jīng)允許不可用來標(biāo)記此軟件的派生品,,或者用以擴(kuò)大此軟件的派生品的影響,。 1.2.4 更多內(nèi)容本書提供了大量的代碼示例。所有的源碼均可在GitHub上下載到(https:// github.com),。 如何獲取源碼最簡單的方式就是直接克隆Git上的代碼庫(https://github.com.NickQiZhu/ d3-cookbook 如果你不熟悉Git,,克?。╟lone)很類似于其他的版本控制軟件中的簽出(checking out)。不過克隆所做的并非簡單的簽出,。它把所有分支和歷史拷貝到了你的本地機(jī)器,,也就是把整個(gè)代碼庫都拷貝到了本地機(jī)器中,所以你完全可以使用這個(gè)拷貝過來的代碼庫,,在本地環(huán)境中離線工作,。 如果是首次安裝Git,可以在這里找到Git客戶端下載列表:http:/// downloads 另一個(gè)使用Git和GitHub的方式是安裝GitHub客戶端,它提供了比Git更多樣的功能,。在作者編寫本書時(shí),,GitHub僅僅提供了Windows版(http://thub. com/ 安裝完Git客戶端后,,運(yùn)行下面的命令就可以把本書中所有的代碼都下載到你的機(jī)器里,。 > git clone git://github.com/NickQiZhu/d3-cookbook.git 如果你打算使用GitHub客戶端(目前還沒有中文版),在https://github.com/NickQiZhu/d3-cookbook頁面點(diǎn)擊Fork按鈕(在頁面的右上角),,之后你就可以在GitHub客戶端中看到這個(gè)代碼庫了,。 1.3 搭建一個(gè)基于NPM的開發(fā)環(huán)境如果你所在的項(xiàng)目是一個(gè)略復(fù)雜的數(shù)據(jù)展示項(xiàng)目,并且使用了為數(shù)不少的JavaScript庫,,那我們之前討論的那個(gè)簡單的解決方案可能就顯得有些褚小杯大,,不能勝任了。在這一節(jié)當(dāng)中,,我們將展示一個(gè)使用了NPM(Node Packaged Modules,,實(shí)際上就是JavaScript庫的代碼庫管理系統(tǒng))的更加強(qiáng)大的系統(tǒng)。如果你像我一樣沒有耐心,,想更快地嘗試本書最帶勁兒的部分,,想學(xué)點(diǎn)秘傳招式,完全可以跳過這部分,,如果想搭建一個(gè)產(chǎn)品開發(fā)環(huán)境,,再回來看看這部分也不遲。 1.3.1 準(zhǔn)備階段我們開始前要先確保NPM已經(jīng)安裝好了,。在安裝Node.js時(shí),,NPM作為其中一部分也被安裝了??梢栽?a href="http:///download/" target="_blank">http:///download/ > npm -v 1.2.14 如果前面的命令輸出了NPM客戶端的版本號(hào),,就說明安裝成功了。 1.3.2 搭建環(huán)境安裝完NPM后,,讓我們創(chuàng)建一個(gè)包描述符文件,,以便自動(dòng)化一些手動(dòng)安裝的過程。 1.首先,,在工程文件夾下,,創(chuàng)建名為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文件后,,運(yùn)行下面的命令。 > npm install 1.3.3 工作原理package.json文件中絕大部分字段僅僅用于提供信息,,比如name,、description、homepage,、author和repository,。如果你打算把自己的庫發(fā)布到NPM的代碼庫中,就要用到name和version字段?,F(xiàn)在,,我們?cè)谝獾氖莇ependencies和devDependencies字段。 ◆ dependencies字段描述了你的工程所用到的庫在運(yùn)行時(shí)的依賴,,它們可以使你的工程在瀏覽器中正常運(yùn)行。在這個(gè)簡單的例子中,,對(duì)于d3我們只有一個(gè)依賴,。d3是D3在NPM庫中發(fā)布時(shí)使用的名字。版本號(hào)3.x標(biāo)明該工程可以兼容任意大版本為3的發(fā)行版,,并且NPM應(yīng)該獲取大版本為3的最新的穩(wěn)定發(fā)布版本來滿足依賴,。 D3是個(gè)自滿足的庫,運(yùn)行時(shí)對(duì)外部是零依賴,。然而這并不意味著它不能跟其他JavaScript庫一起運(yùn)行,。作者平時(shí)也使用一些其他的庫以便讓自己的工作容易些,比如JQuery,、Zepto.js,、Underscore.js和Backbone.js。 ◆ devDependencies字段描述了庫在開發(fā)時(shí)(編譯時(shí))的依賴,。就是說,,這個(gè)字段內(nèi)羅列出來的庫文件僅僅在構(gòu)建工程時(shí)會(huì)用到,運(yùn)行JavaScript工程時(shí)用不到它們。 關(guān)于NPM包JSON文件更詳細(xì)的文檔,,可以參考這里https:///doc/json.html,。 執(zhí)行npminstall可以自動(dòng)觸發(fā)NPM去下載你工程中所引用的所有依賴,包括遞歸的下載依賴的依賴,。所有的依賴庫文件會(huì)被下載到node_modules文件夾中,,該文件夾位于工程文件夾中的根目錄里。這些完成以后,,就可以創(chuàng)建一個(gè)HTML文件(跟我們之前創(chuàng)建的那個(gè)一樣),,HTML文件直接從node_modules/d3/d3.js來引用D3的JavaScript庫。 本節(jié)中的代碼可以在此處下載,,里面包含了自動(dòng)構(gòu)建腳本,。 https://github.com/NickQiZhu/d3-cookbook/tree/master/src/chapter1/ npm-dev-env 工程中會(huì)有一些麻煩的地方,比如手動(dòng)下載JavaScript庫以時(shí)刻保持它們的版本更新,。為了避免這些麻煩,,使用NPM是個(gè)行之有效的方式,可以拯救你于水火之中,。當(dāng)然,,一些聰明的讀者可能已經(jīng)發(fā)現(xiàn)了,使用這個(gè)方法可以把我們的“搭建環(huán)境”過程直接提升一個(gè)檔次,。想象一下,,你正在構(gòu)建一個(gè)巨大的可視化工程,其中包含了上千行的JavaScript代碼,,很明顯我們這里所描述的簡單的搭建方式滿足不了這種情形,。因?yàn)椤澳K化的JavaScript開發(fā)”這個(gè)話題足夠?qū)懕緯耍赃@里我們就不再討論這方面的話題了,,我們將把注意力放在數(shù)據(jù)可視化和D3上,。如果你對(duì)這方面感興趣,可以看看這一節(jié)的代碼,,里面演示了如果實(shí)現(xiàn)一個(gè)模塊化的工程,,當(dāng)然也包含了自動(dòng)構(gòu)建腳本。在后面單元測試相關(guān)的章節(jié)中,,我們會(huì)針對(duì)這個(gè)話題多講一些,,演示一下,可以在某些方面增強(qiáng)環(huán)境,,以便運(yùn)行自動(dòng)化單元測試,。 1.3.4 更多內(nèi)容前面提到過,你可以通過瀏覽器直接打開HTML文件來查看可視化的結(jié)果,,不過這種方式有一些局限性,。一但我們需要從其他文件中加載數(shù)據(jù)(后面的章節(jié)中我們就要這么做了,,這也很像你平時(shí)工作中的情形),由于瀏覽器內(nèi)建的安全機(jī)制,,這種方式就不好用了,。為了繞開這個(gè)安全限制,強(qiáng)烈建議搭建一個(gè)本地的HTTP服務(wù)器,,用該服務(wù)器來維護(hù)HTML頁面和數(shù)據(jù)文件,,而非直接從文件系統(tǒng)加載。 搭建本地HTTP服務(wù)器由于使用的操作系統(tǒng)不同,,HTTP服務(wù)器的軟件包不同,,搭建HTTP服務(wù)器的方法也很不同。這里說幾種比較流行的搭建方式,。 Python簡易HTTP服務(wù)器這是我最喜歡的方式,。如果你的機(jī)器上已經(jīng)安裝了Python,通常UNIX/Linux/Mac OS發(fā)行版上都有,,直接運(yùn)行下面的命令即可,。 > python –m SimpleHTTPServer 8888 如果你擁有更新版本的Python,那么你也可以運(yùn)行如下命令,。 > python –m http.server 這個(gè)python小程序可以啟動(dòng)一個(gè)HTTP服務(wù)器,,然后你就可以訪問該程序所在文件夾中的所有文件。這是目前所有操作系統(tǒng)中運(yùn)行HTTP服務(wù)器最簡單的方式,。 如果你的機(jī)器沒有安裝python,,可以在這里下載http://www./getit/。現(xiàn)在所有的操作系統(tǒng),,諸如Windows,、Linux,還有Mac,,都支持它,。 Node.js HTTP服務(wù)器安裝Node.js之后(前面的小節(jié)中所做的搭建開發(fā)環(huán)境練習(xí),包含了相應(yīng)的內(nèi)容),,就可以搭建http-server模塊了。與Python簡易HTTP服務(wù)器類似,,通過該模塊,,你可以從任意的文件夾快速啟動(dòng)一個(gè)輕量級(jí)的HTTP服務(wù)器。 安裝http-server模塊,。 > npm install http-server –g 命令中的-g參數(shù)會(huì)把http-server模塊設(shè)置為全局的,,這樣你就可以在命令行里直接使用http-server命令。完成此步后,,可以通過下面的命令,,在任意文件夾內(nèi)啟動(dòng)一個(gè)服務(wù)器,。 > http-server . 該命令可以啟動(dòng)一個(gè)Node.js驅(qū)動(dòng)的HTTP服務(wù)器,默認(rèn)端口號(hào)是8080,,也可以用 -p 參數(shù)指定一個(gè)端口號(hào),。 如果是在Linux/UNIX/Mac的操作系統(tǒng)中運(yùn)行該命令,需要用sudo模式或者root權(quán)限來運(yùn)行,。 1.4 理解D3風(fēng)格的JavaScript對(duì)于那些習(xí)慣了過程式或者面向?qū)ο笫降腏avaScript風(fēng)格的人來說,,他們會(huì)感覺D3使用函數(shù)式的JavaScript編程風(fēng)格有一些奇怪。本節(jié)會(huì)涵蓋一些JavaScript中函數(shù)式編程最根本的功能性概念,,以便對(duì)D3有個(gè)基本的理解,,將來可以用D3的風(fēng)格來編寫可視化工程的代碼。 1.4.1 準(zhǔn)備階段在瀏覽器中打開下面文件的本地副本,。 https://github.com/NickQiZhu/d3-cookbook/blob/master/src/ chapter1/functional-js.html 1.4.2 開始編程現(xiàn)在讓我們嘗試更深入一點(diǎn),,了解一下JavaScript函數(shù)式方面的內(nèi)容。請(qǐng)看下面的代碼段,, 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(); 這段代碼在頁面上生成了下面圖片中的示例,。 函數(shù)式JavaScript簡單示例 1.4.3 工作原理盡管非常簡單,但是不可否認(rèn),,這段示例中的代碼跟D3風(fēng)格的JavaScript非常相似,。這不是巧合,在JavaScript編程范型中,,這叫做函數(shù)對(duì)象,。跟很多有趣的話題一樣,這個(gè)話題也能寫一本書,。不過在本節(jié)中,,我會(huì)嘗試盡量多講一些這種特殊范型的東西,好讓不理解D3語法的讀者也能創(chuàng)建這種風(fēng)格的庫文件,。正如D3的維基頁面上所講的那樣,,這種函數(shù)式編程風(fēng)格給D3帶來了很大的便利性。
函數(shù)即對(duì)象JavaScript中的函數(shù)是對(duì)象。跟其他的對(duì)象一樣,,函數(shù)只是鍵值對(duì)的一個(gè)集合,。函數(shù)對(duì)象跟普通對(duì)象的區(qū)別就是,函數(shù)可以執(zhí)行,,函數(shù)還帶有兩個(gè)隱藏的屬性,,即函數(shù)上下文和函數(shù)代碼。這兩個(gè)隱藏屬性有時(shí)候會(huì)給你一個(gè)大大的“意外驚喜”,,如果你有著很深的過程式編程背景,,這點(diǎn)可能更明顯,。不過這也是我們最需要注意的關(guān)鍵點(diǎn)了,要了解一下D3使用函數(shù)的奇怪方式,。 JavaScript的大部分特性都顯得有些不夠“面向?qū)ο蟆?,不過在函數(shù)對(duì)象這方面,JavaScript跟其他語言相比較應(yīng)該更勝一籌,。 現(xiàn)在我們心里有了這樣的概念,,那就再看一遍這段代碼。 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這個(gè)函數(shù)對(duì)象的內(nèi)部私有變量,??墒莚ender函數(shù)卻是instance對(duì)象的一個(gè)方法,并且被定義為對(duì)象字面量,。函數(shù)本身也是對(duì)象,,它可以存儲(chǔ)在對(duì)象/函數(shù)、其他變量,、數(shù)組里,,也可以作為函數(shù)參數(shù)。運(yùn)行SimpleWidget的結(jié)果就是I行所寫的,,返回一個(gè)instance對(duì)象,。 function SimpleWidget(spec) { ... return instance; // <-- I } render函數(shù)中用到了一些我們還沒講過的D3中的函數(shù),不過我們現(xiàn)在先不管它們,,后面的章節(jié)中我們會(huì)詳細(xì)講解的,。它們也只是渲染了一些可視化的東西,跟我們目前的話題沒有太多的關(guān)系,。 下載示例代碼 可以從http://www.下載你購買的所有Packt圖書的示例代碼,。如果是在其他地方購買的話,可以在http://www./support注冊(cè)一下,,代碼會(huì)通過郵件發(fā)送給你,。 靜態(tài)變量作用域好奇的讀者可能會(huì)問,這個(gè)示例中的變量作用域到底是怎樣的???看上去好奇怪,render函數(shù)不僅訪問了instance,、headline和description,,還訪問了從SimpleWidget傳進(jìn)來的spec變量,。這個(gè)怪異的變量作用域其實(shí)是由一個(gè)簡單的靜態(tài)作用域規(guī)則來決定的,??梢园堰@個(gè)規(guī)則想象成這樣:當(dāng)查找一個(gè)變量引用時(shí),該變量先被當(dāng)成是一個(gè)本地變量,。如果沒有找到變量聲明(比如C行中的headline),,就繼續(xù)在父對(duì)象里找(本例中,SimpleWidget函數(shù)就是靜態(tài)的父對(duì)象,,headline變量的聲明在B行),。如果還是沒有找到,就不斷地重復(fù)這個(gè)過程,,遞歸地去父對(duì)象里查找,,一直到全局變量的定義那層。如果最后還是沒有找到,,就針對(duì)該變量生成一個(gè)引用錯(cuò)誤,。這樣的作用域行為與大多數(shù)流行語言(諸如Java、C#)中的變量處理方式大不相同,,可能需要一段時(shí)間適應(yīng),,要是你覺得不習(xí)慣的話,也不用擔(dān)心,,練得多了,,就習(xí)慣了。 對(duì)于有Java和C#背景的人,,需要再提醒一下,,JavaScript沒有實(shí)現(xiàn)塊作用域(block scoping)。我們這里描述的靜態(tài)作用域規(guī)則,,僅僅適用于函數(shù)/對(duì)象級(jí)別,,不適用于塊級(jí)別。 for(var i = 0; i < 10; i++){ for(var i = 0; i < 2; i++){ console.log(i); } } 對(duì)于上面這段代碼,,你可能覺得它會(huì)打印20個(gè)數(shù)字,。其實(shí)在JavaScript里,這段代碼會(huì)陷入到無限循環(huán),。因?yàn)镴avaScript沒有實(shí)現(xiàn)塊級(jí)別的作用域,,所以里面那層循環(huán)的i跟外面那層循環(huán)的i是同一個(gè)變量。于是里面的循環(huán)改變了i的值,,導(dǎo)致外面的循環(huán)永遠(yuǎn)不會(huì)結(jié)束,。 跟流行的原型編程中的偽類模式相比,這樣的模式通常被稱作函數(shù)模式,。函數(shù)模式的優(yōu)點(diǎn)是提供了更好的信息隱藏和封裝,。因?yàn)橹荒芡ㄟ^靜態(tài)作用域規(guī)則里限定的那些嵌套定義的函數(shù)來訪問私有變量(我們示例中的headline和description),所以SimpleWidget函數(shù)返回的對(duì)象就更加靈活,,也更加健壯,。
可變參數(shù)函數(shù)在G行有些奇怪的東西,。 instance.headline = function (h) { if (!arguments.length) h; // <-- G headline = h; return instance; // <-- H }; 你可能會(huì)問,G行的這個(gè)arguments從哪里來的,?這個(gè)例子中從來沒有定義過它,。其實(shí)這個(gè)arguments是內(nèi)建的隱藏參數(shù),并可在函數(shù)執(zhí)行時(shí)直接使用,。arguments是一個(gè)數(shù)組,,它包含了所在函數(shù)的全部參數(shù)。 實(shí)際上,,arguments本身并不是JavaScript的數(shù)組對(duì)象,。雖然它有l(wèi)ength 屬性,并可以用索引下標(biāo)訪問每個(gè)元素,,但是它沒有JavaScript中數(shù)組對(duì)象的那么多方法(比如slice,、concat)。如果你想在arguments上使用JavaScript數(shù)組對(duì)象的方法,,需要這樣: var newArgs = Array.prototype.slice.apply (arguments); 把這個(gè)隱藏的參數(shù)和JavaScript可以在函數(shù)聲明時(shí)省略參數(shù)的功能結(jié)合起來,,就可以寫出instance.headline這種不需要指定參數(shù)個(gè)數(shù)的函數(shù)。在本例中,,我們可以傳一個(gè)參數(shù)h,,也可以不傳。因?yàn)槿绻麤]有傳進(jìn)來參數(shù),,arguments.length就返回0,,headline函數(shù)就返回h,如果h有值,,就變成了一個(gè)賦值操作,。為了說清楚,我們看看下面這段代碼,。 var widget = SimpleWidget({color: "#6495ed"}) .headline("Simple Widget"); // 給headline賦值 console.log(widget.headline()); // 輸出"Simple Widget" 這里你可以看到headline在參數(shù)不同的情況下,,可以分別作為setter和getter(賦值操作和取值操作)。 函數(shù)級(jí)聯(lián)調(diào)用這個(gè)例子另一個(gè)有趣的地方是函數(shù)的級(jí)聯(lián)調(diào)用,。這也是D3庫提供的一個(gè)主要的函數(shù)調(diào)用方式,,因?yàn)镈3庫中的大多數(shù)函數(shù)都設(shè)計(jì)成了這種鏈?zhǔn)降慕Y(jié)構(gòu),以便能提供簡潔的、上下文連貫的編程接口,。如果你理解可變參數(shù)函數(shù)的概念,,就很好理解這個(gè)了??勺儏?shù)函數(shù)(比如headline函數(shù))能同時(shí)作為setter和getter,當(dāng)其作為setter時(shí),,返回instance對(duì)象,,這就使得你可以在返回的instance上立即執(zhí)行另一個(gè)函數(shù),此即鏈?zhǔn)秸{(diào)用,。 看下面這段代碼,。 var widget = SimpleWidget({color: "#6495ed"}) .headline("Simple Widget") .description("This is ...") .render(); 這個(gè)例子中,SimpleWidget函數(shù)返回了instance對(duì)象(如I行所示),。那么,,headline函數(shù)在這里是一個(gè)setter,同時(shí)也返回一個(gè)instance對(duì)象(如H行所示),。description函數(shù)執(zhí)行后也返回instance對(duì)象,。最后調(diào)用了render函數(shù)。 現(xiàn)在我們已經(jīng)大概了解了JavaScript的函數(shù)式風(fēng)格,,有了一個(gè)可工作的D3開發(fā)環(huán)境,,也準(zhǔn)備好了使用D3提供的豐富功能來一試身手。在開始前,,我還想講幾個(gè)比較重點(diǎn)的事情,,即如何尋找、分享代碼以及有困難時(shí)如何獲取幫助,。 1.4.4 更多內(nèi)容先讓我們看幾個(gè)有用的東西,。 尋找、分享代碼在D3眾多值得稱贊的亮點(diǎn)中,,有一個(gè)是比其他可視化工具提供了更加豐富的示例和教程,,你可以從中汲取靈感。當(dāng)我創(chuàng)建自己的開源可視化圖表項(xiàng)目,,還有寫作這本書的時(shí)候,,我在那些資源中獲得了大量的靈感。我會(huì)在那些最棒的例子里,,挑出一些列個(gè)清單出來,。這個(gè)清單雖然不是百科全書,但卻是個(gè)不錯(cuò)的入門參考,。 ◆ D3 gallery(https://github.com/mbostock/d3/wiki/Gallery),,這里有不少有趣的例子,可以幫你在線查找D3的使用方法,有各種各樣的圖表,、特定的技術(shù),,還有一些跟其他工具一起實(shí)現(xiàn)的示例。 ◆ BioVisualize(http://biovisualize./d3visualization),,算是一個(gè)分門別類的D3 gallery,,可以幫你快速地在線查找你想要的例子。 ◆ D3教程(https://github.com/mbostock/d3/wiki/Tutorials),,有很多朋友不斷更新提供的教程,、討論和文檔,給你細(xì)致地演示了D3的使用方法,。 ◆ D3插件(https://github.com/d3/d3-plugins),,可能有些你需要的功能是D3沒有的。在你自己實(shí)踐之前,,先查查D3的插件庫,,它提供了各種常用的、不常用的功能,。 ◆ D3 API(https://github.com/mbostock/d3/wiki/API-Reference)是很不錯(cuò)的文檔,。這里你能找到D3所提供的全部功能、屬性的詳細(xì)說明,。 ◆ Mike Bostok's Blocks(http://bl./mbostock)是個(gè)D3示例站點(diǎn),,作者是Mike Bostock,這個(gè)站點(diǎn)里有很多有趣的例子,。 ◆ JS Bin(http:///ugacud/1/edit)是個(gè)在線的D3測試,、實(shí)驗(yàn)環(huán)境。你可以很容易地通過該工具跟其他人分享一些簡單的代碼,。 ◆ JS Fiddle(http:///qAHC2/)跟JS Bin差不多,,也是一個(gè)在線JavaScript代碼分享平臺(tái)。 如何獲取幫助即便有了這些例子,、教程,,還有書,你在實(shí)踐的過程里仍然會(huì)遇到問題,。不過D3有數(shù)目龐大并且活躍度不錯(cuò)的社區(qū),。一般情況,簡單地“google”一下,,就能找到滿意的答案,。要是沒有也不用擔(dān)心,D3還有強(qiáng)大的社區(qū)支持,。 ◆StackOverFlow上的D3.js(http:///questions/ tagged/d3.js):StackOverflow是最著名的免費(fèi)技術(shù)主題問答社區(qū)站點(diǎn),,D3在StackOverflow上有專門的頁面,,可以幫你找到專家,快速地解決你的問題,。 ◆ D3 Google討論組(https://groups.google.com/forum/?fromgroups#! forum/d3-js):這是個(gè)官方的用戶組,,不單單有D3,還有一些其他相關(guān)的庫,。 |
|