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元素
1 2 
  | d3.select('p') d3.selectAll('p') 
  | 
 
还可以选择其他常用的选择器,包括派生选择器,与document.querySelector和document.querySelectorAll方法十分类似
1 2 3 4 
  | 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]]) 取得或设置元素的样式 
1 2 3 4 5 6 
  | 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 
1 2 3 4 5 6 7 8 9 10 11 
  | <body>   <p>Dog</p>   <p>Cat</p>   <p>Monkey</p>   <script type="text/javascript">     var p = d3.select('body').selectAll('p');          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方法比较适用于日常数据需求,使用更多
1 2 3 4 5 6 7 8 9 10 11 12 
  | <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.data(dataset);     console.log(p);   </script> </body> 
  | 
 
运行代码查看控制台,数值1、2、3分别绑定到了第1、2、3个p标签



绑定数据后,就可以利用绑定的数据做一些事情了,D3为大部分操作DOM的方法添加了函数参数,该函数有两个参数,一个代表绑定的数据,通常为d,另一个为序数值,通常为i
1 2 3 4 5 6 7 8 9 10 11 12 13 14 
  | <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.data(dataset)       .text(function(d, i) {         return d + ' ' + i       });   </script> </body> 
  | 
 
运行结果如下图:

enter()与exit()的用法
在前面讲数据绑定中,数组的长度与标签数量是相等的,如果数据的长度不可控,会导致有些标签没有数据,有些数据没有标签匹配,这个时候就要用到enter与exit方法了
selection.enter() 为缺失的元素返回占位符 
1 2 3 4 5 6 7 8 9 10 
  | <body>   <p>Dog</p>   <script type="text/javascript">     var dataset = [1, 2, 3];     var p = d3.select('body').selectAll('p');          enter = p.data(dataset).enter();     console.log(enter);   </script> </body> 
  | 
 
查看控制台,发现出现了2个并不真实存在的EnterNode,绑定了剩余的数据,这就是enter部分,如果后面继续添加新的标签,标签会被自动绑定剩余数据

selection.exit() 返回没有被绑定数据的元素 
1 2 3 4 5 6 7 8 9 10 11 12 
  | <body>   <p>Dog</p>   <p>Cat</p>   <p>Monkey</p>   <script type="text/javascript">     var dataset = [1];     var p = d3.select('body').selectAll('p');          exit = p.data(dataset).exit();     console.log(exit);   </script> </body> 
  | 
 
查看控制台,有2个标签并没有绑定数据,这就是exit部分,可以把多余的exit部分移除掉

交互与动画
selection.on(typenames[,listener[,capture]]) 
D3的事件绑定非常简单,与jQuery的on方法一样,指定事件类型后,调用回调函数
1 2 3 4 5 6 7 8 9 
  | <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方法,就能形成炫酷的过渡动画
1 2 3 4 5 6 7 8 9 10 11 
  | <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> 
  |