D3.js是一個通過資料來操作文件JavaScript庫。結合SVG,D3特別適合用於圖表的繪製,但D3本身並不是一個圖表庫,它把資料繫結到DOM中,利用SVG輸出圖表。本文所講內容適用於v4.0+版本
從v4.0開始,D3把各個模組分離開來,各個模組相互獨立,也就是說如果你只需要用到D3強大的陣列操作部分,只需引用d3-array部分(例如npm install d3-array),不需要引用所有的D3庫。這樣做能夠使前端模組化開發更加靈活,減小引用資源體積,節省效能
用D3操作DOM元素
- d3.select(selector) 返回匹配選擇器的第一個元素
- d3.selectAll(selector) 返回匹配選擇器所有元素
比如d3.selectAll(‘p’)可以選擇所有的p元素,d3.select(‘p’)只選擇第一個p元素
d3.select('p')
d3.selectAll('p')
複製程式碼
還可以選擇其他常用的選擇器,包括派生選擇器,與document.querySelector和document.querySelectorAll方法十分類似
d3.select('.chart')
d3.selectAll('.chart')
d3.select('#chart')
d3.select('.chart rect')
複製程式碼
- selection.append(type) 建立新元素並返回該元素
- selection.remove() 從DOM中移除當前元素
- selection.attr(name[,value]) 取得或設定屬性的值
- selection.style(name[,value[,priority]]) 取得或設定元素的樣式
d3.select('body')
.append('svg')
.attr('width', 500)
.attr('height', 500)
.style('background', 'red')
.remove()
複製程式碼
上面的程式碼首先在body中建立了一個svg標籤,然後給它設定高度和寬度,設定背景色,最後被刪除,D3的程式碼風格基本採用鏈式寫法,因為大部分D3的方法都返回D3物件的例項,這和jQuery非常相似
在DOM元素中繫結資料
資料繫結是D3的最大特色,也是最讓入門者困惑的地方,D3中文全稱“資料驅動文件”,主要的方法有兩個
- selection.datum([value]) 為每個元素繫結值value
<body>
<p>Dog</p>
<p>Cat</p>
<p>Monkey</p>
<script type="text/javascript">
var p = d3.select('body').selectAll('p');
// 為p元素集繫結數值1
p.datum(1);
console.log(p);
</script>
</body>
複製程式碼
執行程式碼檢視控制檯,數值1已經被賦予了p標籤的**data**屬性了
- selection.data([data[,key]]) 為每個元素分別繫結對應data中資料值
data方法與datum方法的區別在於,data的引數是陣列,分別分配給對應的DOM元素,每個DOM元素得到一個value值,而datum把相同引數均賦值給DOM元素,每個元素得到的資料值相同,data方法比較適用於日常資料需求,使用更多
<body>
<p>Dog</p>
<p>Cat</p>
<p>Monkey</p>
<script type="text/javascript">
var dataset = [1, 2, 3];
var p = d3.select('body').selectAll('p');
// 為p元素集繫結陣列dataset
p.data(dataset);
console.log(p);
</script>
</body>
複製程式碼
執行程式碼檢視控制檯,數值1、2、3分別繫結到了第1、2、3個p標籤
繫結資料後,就可以利用繫結的資料做一些事情了,D3為大部分操作DOM的方法新增了函式引數,該函式有兩個引數,一個代表繫結的資料,通常為d,另一個為序數值,通常為i
<body>
<p>Dog</p>
<p>Cat</p>
<p>Monkey</p>
<script type="text/javascript">
var dataset = [1, 2, 3];
var p = d3.select('body').selectAll('p');
// 更改p元素內的內容,d是資料值,i是序數值
p.data(dataset)
.text(function(d, i) {
return d + ' ' + i
});
</script>
</body>
複製程式碼
執行結果如下圖:
enter()與exit()的用法
在前面講資料繫結中,陣列的長度與標籤數量是相等的,如果資料的長度不可控,會導致有些標籤沒有資料,有些資料沒有標籤匹配,這個時候就要用到enter與exit方法了
- selection.enter() 為缺失的元素返回佔位符
<body>
<p>Dog</p>
<script type="text/javascript">
var dataset = [1, 2, 3];
var p = d3.select('body').selectAll('p');
// 目前只有1個元素,3個資料值
enter = p.data(dataset).enter();
console.log(enter);
</script>
</body>
複製程式碼
檢視控制檯,發現出現了2個並不真實存在的EnterNode,繫結了剩餘的資料,這就是enter部分,如果後面繼續新增新的標籤,標籤會被自動繫結剩餘資料
- selection.exit() 返回沒有被繫結資料的元素
<body>
<p>Dog</p>
<p>Cat</p>
<p>Monkey</p>
<script type="text/javascript">
var dataset = [1];
var p = d3.select('body').selectAll('p');
// 目前有3個元素,只有1個資料值
exit = p.data(dataset).exit();
console.log(exit);
</script>
</body>
複製程式碼
檢視控制檯,有2個標籤並沒有繫結資料,這就是exit部分,可以把多餘的exit部分移除掉
互動與動畫
- selection.on(typenames[,listener[,capture]])
D3的事件繫結非常簡單,與jQuery的on方法一樣,指定事件型別後,呼叫回撥函式
<body>
<p>Dog</p>
<script type="text/javascript">
var p = d3.select('body').select('p');
p.on('click', function() {
d3.select(this).text('Cat');
})
</script>
</body>
複製程式碼
- selection.transition([name])
在元素之間加入transition方法,就能形成炫酷的過渡動畫
<body>
<div></div>
<script type="text/javascript">
var div = d3.select('body').select('div');
div.style('width', '200px')
.style('height', '200px')
.style('background', 'red')
.transition()
.style('width', '400px');
</script>
</body>
複製程式碼