前言
在web前端开发中,时常会碰到显示图表的需求。而在这个领域中,国内最有名的库莫过于Echarts
了,其他的还有Ant
的g2
,highchart
和chart.js
等,这些库的特点是开箱即用,基于配置,根据官方提供的demo,进行一定的调整就能够满足开发的任务的,也有提供自定义的方案,满足特殊的需求。
不过我总感觉不能满足于这种高级封装库提供的便利,因为这样比较难提升自己的开发能力,所以希望去折腾些较底层的库,让自己可以多动些脑筋。(也有一种潮流是直接使用React
这类前端框架,做可视化的工作(同样也是数据驱动视图),不过这样子就相当于再造一个轮子了)
而d3
就是一个很好的选择,历史悠久,使用者众多,作者Mike Bostock
也是个很有创造力的开发者,独力写了很多优秀的可视化demo
,除了d3
还创建了可视化分享平台Observerblehq
。
API
设计方面采用了类似JQuery
的链式调用,代码组织的特点是分成了多个独立的模块,分开仓库进行管理,所以也方便使用者按需引入。d3
的类的创建,不使用new
的方式,而通过函数返回一个新的对象,对象相关的变量,存储在闭包内。
我觉得d3
主要是一个可视化数据处理工具函数的库,不提供图形渲染引擎,所以可以让使用者全盘掌控显示的内容。
API概念说明
d3.selection
d3
的DOM操作的风格十分类似Jquery
- 创建DOM元素并返回一个类似
Jquery
集合的Selection
对象
1 | d3.create('svg') |
选择DOM元素,
select
和selectAll
都会返回一个Selection
。1
2
3
4
5selection.select('rect')
selection.selectAll('rect')
// 或者使用d3的静态方法
d3.select('rect')
d3.selectAll('rect')绑定数据。绑定数据的方法有
data
和datum
两种,data
会返回一个新的集合并逐一把每一行数据绑定给selection
中的成员,如原selection
中的成员数量比data
的行数小,则新创建的selection
会使用占位用的empty
补足;datum
则是将整组数据逐一绑定给每一个selection
成员,不会产生新的集合。1
2
3
4let arr: any[]
selection.data(arr)
// 设置selection各成员绑定的数据
selection.datum(arr)绑定数据的行数与
selection
的数量有出入时,d3
会产生enter
和exit
的集合。但是并不会默认给enter
的集合自动创建对应的DOM元素,这时可使用join
去创建。
1 | let arr: any[] |
selection.call
接收一个以selection
为参数的回调函数,目前看来用途主要给selection
添加一些子元素,这样就不会改变外部链式调用的主体。
1 | selection.call((s) => s.append('path')) |
selection.each
方法并不会回传一个子selection
,而是回传三个参数d
(子data),i
(索引),nodesGroup
(selection
内部的DOM集合),回调函数的this
等同于nodesGroup[i]
1
2
3
4selection.each(function (d, i, nodesGroup) {
// 由于并不是子selection,所以需要进行select把DOM变成d3的selection对象
d3.select(this)
})
d3.Shape
d3.lineRadial
与d3.line
作用同样都是生成线段,不同的是lineRadial
的坐标系是极坐标系,而且需要注意的是0 rad是12点方向,角度增长为顺时针,每个点由angle
和radius
方法定义。
d3.polygon
d3.polygonCentroid
,求多边形的中点a。
原理是以[P_(n - 1), P_n, [0, 0]]
为顶点组成三角形,求出各个三角形的中点P_m_n
(顶点坐标和除以3)。
然后各个顶点根据权重W(三角形n的面积 / 所有三角形的面积和)
相加求得。
三角形的面积 = (V_(n - 1) X(叉积) V_n) * 0.5