# 單元 77 [加碼達標系列 2000%]:D3.js 資料視覺化的利器(入門)
---
## D3.js 資料視覺化的利器
### 加碼達標系列
---
### D3.js 資料視覺化
* 將數據透過 形狀、量體、顏色 ..等做視覺呈現
* 讓人直觀感受相對比例、統計特性跟重要性
* 要素:資料整理、視覺元素、座標與尺規

----
### 資料視覺化的程式面
* 能夠處理元素跟數據對應
* 能夠轉換數據成屬性
* 能快速處理圖形
* 傳統作法(如Jquery) - 迴圈與元素對應

----
### D3.js 介紹
* 操作十分彈性,語法與Jquery相似
* 著重資料跟元素的鏈結處理 / 可批次指定屬性
* 擁有廣泛情況的工具函數(圖表、地圖、力場..等)

---
### 第一部分: 改變元素
* 選取元素: select / selectAll
* 改變屬性: style / attr / text / html
```javascript=
d3.select("ul").selectAll("li.item")
.style("background-color","red")
.text("hello d3!")
```
----
#### 第一部分: 元素與資料的連結
1. 元素選擇:selectAll(元素)
2. 資料連結:data(資料)
3. 變動集合:enter() / exit()

```javascript=
var data = ['a','b','c','d','e']
var elements = d3.selectAll("h3")
.data(data)
```
----

```javascript=
//針對有資料無元素的集合
elements.enter() //有資料無元素
elements.exit() //有元素無資料
elements.enter().append("h3") //加入實際元素
elements.exit().remove() //移除多餘元素
```
----
#### 第一部分: 批次改變元素
* style / attr / text 批次function(data,index)

```javascript=
var data = ['a','b','c','d','e']
var elements = d3.selectAll("h3")
.data(data)
.text((d,i)=>(i+". "+d)) // 1.a 2.b...
.style("color",(d,i)=>("rgb("+i*50+",255,255)"))
```
----
#### 第一部分: 數據縮放與轉換
* scaleLinear / scaleLog 線性/指數縮放
* domain 輸入數值範圍
* range 輸出範圍

https://github.com/d3/d3-scale
----
#### 第一部分: Scale的顏色
* scaleLinear().domain([1,10]).range(['#000','#fff','#f24'])
* scaleOrdinal 序列對應
* d3裡面有提供很多[顏色集](https://bl.ocks.org/pstuffa/3393ff2711a53975040077b7453781a9
)

----
* scaleOrdinal 序列對應
* 依照輸入給後面陣列裡面顏色
* [1,2,3]=>[color1,color2,color3]
```javascript=
var scaleColor = d3.scaleOrdinal().range(d3.schemeAccent)
scaleColor(0) //#7fc97f
```
---
### 第二部分: SVG圖形:更為彈性的圖形
* svg自由度極高,好操作圖形
* 操作svg時,以屬性attr為主

----
#### 第二部分: D3與SVG
* 快速處理形狀
* https://github.com/d3/d3-shape

----
#### 第二部分: line輔助函數使用範例
* d3.shape: 視為轉換函數
* 於line函數上定義好轉換規則嵌入
```javascript=
let data = [1,20,10,3,50]
var line = d3.line()
.x((d,i)=>i*100)
.y((d,i)=>d)
svg.append("path")
.datum(data)
.attr("d", line)
.style("stroke", "black")
```

----
#### 第二部分: arc輔助函數使用範例
```javascript=
var arc = d3.arc()
.innerRadius(50)
.outerRadius(120)
svg.append("path")
.datum({startAngle: 0,endAngle: Math.PI*1})
.attr("d", arc)
.style("fill", "orange")
```
---
### 第三部分: 時間變化與轉換
* 平滑變化到另一個狀態[(範例)](http://bl.ocks.org/mbostock/1256572)
* 變動 transition
* 長度 duration / 延遲 delay
* 速度函數 ease
* 可以接受函數轉換
```javascript=
d3.select("svg").selectAll("rect")
.attr("fill","red")
.transition()
.duration(500)
.delay((d,i)=>i*100)
.attr("fill","yellow")
```
----
#### 第三部分: 多層次群組
* 多層次綁定第二次的data

----
```javascript=
var data = [[1,2,3],[2,3,4],[3,4,5]]
//第一層
var elements =
d3.selectAll("g.group").data(data)
.enter().append("g").attr("class","group")
//第二層
elements.selectAll("rect").data(d=>d)
.enter().append("rect")
```
----
#### 第三部分: d3 Layout
* 有一些可直接拿來用的圖表
* Pie Chart / Stacked Layout / Forced Layout

----
#### 第三部分: 讀入csv
* d3.csvParse(資料,轉換函數)
* 可以同時讀入+map轉換
```javascript=
var data = d3.csvParse(`Year,NTD/USD,JPY/USD,USD/GBP,HKD/USD
2010,31.642,87.78,1.5461,7.7692
2011,29.464,79.81,1.6036,7.784
2012,29.614,79.79,1.5853,7.7564
2013,29.77,97.60,1.5645,7.756`,function(d,i){
})
//讀檔案時(ajax): d3.csv("data.csv", function(error, data) {}
```
---
### 實作範例練習: 匯率視覺化
https://codepen.io/frank890417/pen/mjMxWp?editors=0011

資料來源:https://cpx.cbc.gov.tw/Data/DataMain/?pxfilename=BP01Y01.px
---
參考資料
http://blog.infographics.tw/2015/05/d3js-tutorial-force-layout/
http://blog.infographics.tw/2016/02/data-restructure-with-d3js/
https://github.com/d3/d3/blob/master/API.md
http://blog.infographics.tw/2016/05/d3js-seven-pro-tips/
http://d3indepth.com/