D3 vs ECharts
最近做了些數據可視化方面的項目,偶然間發現 D3
這個強大的基於 JavaScript
的可視化工具庫,並驚歎其 GitHub 上的熱度,竟然 遠超 一度被(我自己)公認爲 可視化神器 的 ECharts
——
(統計時間:2020-04-04)
GitHub 指標 | D3 | ECharts |
---|---|---|
Star(點贊) | 90.7k | 40.3k |
Watch(關注) | 4k | 2k |
Used by(被引) | 83k | 64.6k |
Fork(叉取) | 21.9k | 13.6k |
releases(發佈) | 100 | 262 |
contributors(貢獻者) | 96 | 121 |
於是,藉助前期對 JavaScript
的迷之自信與對 O'Reilly
的盲目崇拜,在網上輕輕鬆鬆找到了這本僅 70 頁篇幅的資源——《Getting Started with D3》,開始了漫漫填坑之旅。。。
本書特色
這本小冊子寫於 2012 年,書中的 D3.js
版本爲 2.8.0
,所以和目前的最新版 5.15.1
在語法上還是有很多不同。書中示例均出自 MTA——紐約大都會交管局,目標讀者是數據相關從業人員,包括高校研究員、統計師或設計師等喜歡擼碼並樂於玩數據(不然也不會有精力去填坑)。本書主要特色大致如下:
- 跳過前期儲備知識講解(
HTML
、CSS
、JavaScript
、SVG
、canvas
),直奔D3
主題 - 結合紐約交通具體案例,講解
D3
基本概念 - 隨書源碼提供了數據清洗的完整腳本(
Python
版,待填坑) - 篇幅簡短,上手很快
- 挖坑無數
相關準備
1. 示例代碼
當時想着只是入門,重點在瞭解基本概念,版本影響應該不大,結果第一次練手就卡在了 d3.json()
的新舊寫法上,無奈之下只有先按老版本過一遍代碼,後期再嘗試更新。隨書源碼位置:
GitLab
:https://resources.oreilly.com/examples/0636920025429.git
Gitee
:https://gitee.com/PeacefulWinter2020/Getting-Started-with-D3.git
這裏的 Gitee
版是爲了方便大家快速同步到本地,特意從 GitLab
上遷移到 Gitee
上的。
git clone https://resources.oreilly.com/examples/0636920025429.git
git clone https://gitee.com/PeacefulWinter2020/Getting-Started-with-D3.git
2. 測試服務器
由於書中不少示例的數據源是 JSON
文件格式,需要在服務器環境下運行。書中給出的方案是 Python
版 SimpleHTTPServer
。其實只要是個服務器就行,如 Tomcat
。這裏用到的是 VSCode
插件 Live Server 5.6.1
,編輯器內直接右鍵【Open with Live Server】即可運行。
下面,我將從頭到尾,按書中示例的順序,逐一梳理這本小冊子給大家精心準備的 D3 小確喪。。。
Chapter 1. Introduction
第一章沒有具體示例,只是交待了一些準備工作。
全書示例代碼模板:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="d3.js"></script>
<script>
function draw(data) {
"use strict";
// badass visualization code goes here
}
</script>
</head>
<body>
<script>
d3.json("data/some_data.json", draw);
</script>
</body>
</html>
注意:這裏的 D3 庫文件是舊版的([ v2.8.0.zip 下載 ] [ v5.15.1.zip 下載 ])
值得注意的是,書中提到一個在用 JSON
存數據時值得借鑑的一個基本原則:
數據不要放在 JSON 的鍵上。
——Micha 黃金法則
錯誤寫法:
{
"bob": 20,
"alice": 23,
"drew": 30
}
正確寫法:
[
{
"name": "bob",
"age": 20
},
{
"name": "alice",
"age": 23
},
{
"name": "drew",
"age": 30
}
]
這裏還提到一個方法,用於快速切換到正確的 JSON
寫法:d3.entries()
,但沒有給出具體示例,這裏補全:
let oldData = {
"bob": 20,
"alice": 23,
"drew": 30
};
let newData = d3.entries(oldData).map(e => ({name: e.key, age: e.value}));
console.log(newData);
// Results:
// [{name: "bob", age: 20},
// {name: "alice", age: 23},
// {name: "drew", age: 30}]
Chapter 2. The Enter Selection
這一章引入了一個重要概念:enter selection(輸入選擇),算是第一個坑吧,看得我一頭霧水:這真的是入門級嗎?後來查了一下其他資料才知道,D3 有個 enter、update、exit 的概念,因爲是“入門級”,這裏直接省略了後面兩個,只能在說明欄的鏈接中查看相關的介紹。入門太難了。。。
示例1:創建地鐵線路狀態公告欄
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="js/d3.js"></script>
<script>
function draw(data) {
"use strict";
// badass visualization code goes here
d3.select('body')
.append('ul')
.selectAll('li')
.data(data)
.enter()
.append('li')
// populate content
.text((d, i) => `index=${i}, name=${d.name}, status=${d.status}`)
// set style
.style('color', d => d.status == 'GOOD SERVICE' ? 'green' : 'blue')
.style('font-weight', ({ status: st }) => st != 'GOOD SERVICE' ? 'normal' : 'bold')
}
d3.json("data/service_status.json", draw);
</script>
</body>
</html>
(未完待續)