# 單元 77 [加碼達標系列 2000%]:D3.js 資料視覺化的利器(入門) --- ## D3.js 資料視覺化的利器 ### 加碼達標系列 --- ### D3.js 資料視覺化 * 將數據透過 形狀、量體、顏色 ..等做視覺呈現 * 讓人直觀感受相對比例、統計特性跟重要性 * 要素:資料整理、視覺元素、座標與尺規 ![](https://i.imgur.com/cXfb7ud.jpg) ---- ### 資料視覺化的程式面 * 能夠處理元素跟數據對應 * 能夠轉換數據成屬性 * 能快速處理圖形 * 傳統作法(如Jquery) - 迴圈與元素對應 ![](https://i.imgur.com/KcxgBvh.png) ---- ### D3.js 介紹 * 操作十分彈性,語法與Jquery相似 * 著重資料跟元素的鏈結處理 / 可批次指定屬性 * 擁有廣泛情況的工具函數(圖表、地圖、力場..等) ![](https://i.imgur.com/MbUcHPu.png) --- ### 第一部分: 改變元素 * 選取元素: 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() ![](https://i.imgur.com/cC6B5n9.png) ```javascript= var data = ['a','b','c','d','e'] var elements = d3.selectAll("h3") .data(data) ``` ---- ![](https://i.imgur.com/ccu9RCm.png) ```javascript= //針對有資料無元素的集合 elements.enter() //有資料無元素 elements.exit() //有元素無資料 elements.enter().append("h3") //加入實際元素 elements.exit().remove() //移除多餘元素 ``` ---- #### 第一部分: 批次改變元素 * style / attr / text 批次function(data,index) ![](https://i.imgur.com/rfywXdm.png) ```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://i.imgur.com/8YBqXmj.png) https://github.com/d3/d3-scale ---- #### 第一部分: Scale的顏色 * scaleLinear().domain([1,10]).range(['#000','#fff','#f24']) * scaleOrdinal 序列對應 * d3裡面有提供很多[顏色集](https://bl.ocks.org/pstuffa/3393ff2711a53975040077b7453781a9 ) ![](https://i.imgur.com/jhrIJsJ.png) ---- * scaleOrdinal 序列對應 * 依照輸入給後面陣列裡面顏色 * [1,2,3]=>[color1,color2,color3] ```javascript= var scaleColor = d3.scaleOrdinal().range(d3.schemeAccent) scaleColor(0) //#7fc97f ``` --- ### 第二部分: SVG圖形:更為彈性的圖形 * svg自由度極高,好操作圖形 * 操作svg時,以屬性attr為主 ![](https://i.imgur.com/stUszZU.png) ---- #### 第二部分: D3與SVG * 快速處理形狀 * https://github.com/d3/d3-shape ![](https://i.imgur.com/AVEzheY.png) ---- #### 第二部分: 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") ``` ![](https://i.imgur.com/KKwWcdA.png) ---- #### 第二部分: 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 ![](https://i.imgur.com/lZ2NUTY.png) ---- ```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 ![](https://i.imgur.com/PysUBdK.png) ---- #### 第三部分: 讀入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://i.imgur.com/ZsHNiJp.png) 資料來源: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/