Introduction to D3.js - Cover

想在網站上做資料視覺化,你會怎麼做?用 Excel 填填拉拉產生圖表再存成圖檔上傳嗎?用套件產生千篇一律的圖表再嵌入到網站裡?雖然我們之前已經寫過不少 D3.js 實戰,今天我們回歸到最基本,從入門開始介紹如何在網頁上用 D3.js 製作視覺圖表。

Data Driven Document 讓我們先用瑣碎問答法來看一看 D3.js:

  • D3.js 是什麼?
    • 是一套 Javascript 函式庫,包含一整組操縱畫圖很好用的輔助工具,還有很方便的資料操作模型
  • 為什麼要用 D3.js ,而不用其他像是 chart.js 、 highchart.js 、 amchart.js ?
    • 各有優缺點, D3.js 的優點是彈性超大但實作繁瑣,其它圖表則是容易建立但形式侷限。
  • 需要先學其它東西嗎?
    • 一定得會:Javascript、HTML
    • 強烈建議:CSS、SVG
    • 編按:不會的別擔心,我們未來也會有相關分享喔!

那麼開始吧!

這樣講你可能不相信,其實 D3.js 的基礎不是在視覺化,而是資料與物件的結合。「資料」 - 例如各國嬰兒死亡率 - 逐一結合至「物件」 - 比方說一個長條、一個圓形。下圖為死亡率資料結合至圓形物件上的表現:

data binding

在上圖中,左邊共有四筆資料,各包含國名、國旗與死亡率;我們先利用 D3.js 將這些資料結合到中間的圓形物件;接著再次透過 D3.js 使用資料來替物件設定參數,比方說死亡率對應到半徑,國旗則用來為圓形著色,可以得到右邊的泡泡圖。

上面這一段話大概就是 D3.js 運作的基本原理囉!

實戰時間

使用 D3.js,請先在 HTML 中引入 D3.js 的程式碼:

  <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>

接著就可以開始囉!假設我們想要將剛剛的死亡率資料畫成長條圖,資料如下:

 var death_rate = [['越南',24.26],['阿魯巴',17.48],['關島',10.01],['澳門',5.84]];

D3.js 的第一步就是選取物件。使用 d3.select 函式:

  var root = d3.select("body");

他會傳回一個代表 <body> 的物件。如果有用過 jQuery 的話,這個效果類似 $(“body"),你也可以連環執行,取得部份文件中的標籤物件:

  var span = d3.select("body").select("h3").select("span");

取得的物件, D3.js 也替你包裝得很方便使用。比方說我們可以用 text 函式改變標籤的內文、或者用 style 函式設定標籤的樣式:

  span.text("hello world").style("font-size", "24px");

上面的例子取得的只有一個物件,但是在做資料連結時,根據資料數量的不同,可能會需要很多個物件。這時候我們可以改用 d3.selectAll 函式,並在呼叫 selectAll 之前利用select 確認這些物件所屬的位置:

  var div = d3.select("body").selectAll("div");

接著就是這次的重頭戲 - 資料連結囉!使用 data 函式便可以做到:

  d3.select("body").selectAll("div").data(death_rate);

你可能會想,資料的數量又不一定,難道我得先在 HTML 裡寫好一堆 <div> 標籤來讓資料連結嗎? 事實上 D3.js 提供了兩個函式 - enter 跟 exit -幫我們過濾出「沒有物件可配對的資料」與「沒有資料可配對的物件」這兩個集合, 方便我們緊接著利用另外兩個輔助函式「append」與「remove」來處理數量不符的情況:

  var div_data_bind = d3.select("body").selectAll("div").data(death_rate);
  div_set = div_data_bind.enter().append("div"); /*為「沒有物件可配對的資料」建立標籤 */
  div_data_bind.exit().remove(); /* 刪除「沒有資料可配對的物件」*/

如程式碼所見, append 幫我們建立標籤物件給資料配對,而 remove 則移除掉多餘的標籤。

物件 / 資料連結完成以後,我們就可以開始設定物件的參數。這裡有 D3.js 的另一個要點:「設定參數時可以代入函式,參數的值會用函式執行的結果來設定」。而傳入函式的參數則會是各筆資料 d 與資料的順序 i 。比方說,我們利用國名跟資料順序來填標籤的內容:

  div_set.text(function(d,i) {
    return i + " / " + d[0];
  });

則你會在網頁上看到這樣的結果:

  0 / 越南
  1 / 阿魯巴
  2 / 關島
  3 / 澳門

講了這麼多,完整的程式碼也就如下七行:

  var death_rate = [['越南',24.26],['阿魯巴',17.48],['關島',10.01],['澳門',5.84]];
  var div_data_bind = d3.select("body").selectAll("div").data(death_rate);
  div_set = div_data_bind.enter().append("div");
  div_data_bind.exit().remove();
  div_set.text(function(d,i) {
    return i + " / " + d[0];
  });

看到這裡,大致上你已經瞭解 D3.js 的基礎了。

我要圖表啦!

都學到一半了,怎麼還沒看到圖表?其實現在我們已經具備製作圖表的能力了。把剛剛的 <div> 標籤想成是長條,我們只要設定寬度、高度與背景顏色就可以做到囉:

  div_set.style("height", "20px");
  div_set.style("background", "red");
  div_set.style("margin", "5px");
  div_set.style("width", function(d,i) {
    return (d[1] * 10)+"px";
  });

在上面的程式碼片段中,我們將長條高度設為 20px ,背景設為紅色,預留 5px 的間距,並將寬度設定為死亡率的 10 倍,其值會介於 50 ~ 240px 之間。執行結果如下(放大呈現):

simple bar chart example

我的第一個視覺圖表

這就是我們的第一個視覺化作品啦!有沒有很感動呢?

可是接下來呢?

這篇教學文為大家介紹的是 D3.js 的核心部份 - Data Binding ,但其實 Data Binding 有很多工具可以幫你做,例如 AngularJS 。即便捨棄 Data Binding 不看,D3.js 仍有另一個強大的地方 - 豐富的繪圖輔助函式庫,協助我們繪制圓餅、地理區塊、計算地圖投影、顏色與座標內差轉換、各種圖表配置的計算工具等等,就算不使用 D3.js 的 Data Binding ,那些也是非常有用的工具。

另外,D3.js 若搭配 SVG ,透過繪製任意形狀可以有更多變化可以玩,所以 SVG 也是很值得一學的技術喔!其實不光只是 SVG,只要會產生物件模型的東西例如 MathML 、 X3DOM 等等的,通通可以利用 D3js 玩得很愉快。

不過,由於這篇篇幅已經很長了,我決定將這些內容留待下次再跟大家分享。如果想知道 D3js 的工具函式庫部份可以玩出什麼樣的創意,別忘了隨時關注我們的更新喔!


Written by infographics.tw

3 Comments

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *