d3.js 进阶
2016-04-14
本篇文章谈谈 d3 的动画、svg 图形生成器以及 d3 提供的 layout
一、动画
1. 鼠标 hover ,显示当前坐标
- 使用 .on() 为图表添加交互
- 当前 this 指向的 d3 对象:
d3.select(this)
- 事件对象:
d3.event
- 常用事件 'mouseover', 'mouseout'
2. 为图表添加动画
散点图-动画.png代码如下:
circles.transition()
// 为每个结点按序增加延迟时间,达成依次出现的效果
.delay(function(d, i){
return i * 10;
})
// 动画总时长
.duration(100)
// 更新样式
.attr(circleAttrs);
更新样式:
- 坐标 从原点移至 x, y
- 半径 从小变大
3. 新增结点,动态更新比例尺
散点图-animate2.png- 返回当前鼠标坐标:
var coods = d3.mouse(this);
- 反向获取比例尺的值:
xScale.invert()
- 更新 data 数组
data.push(obj)
; - 更新比例尺的
domain 区间
- 更新坐标轴 重新
.call(xAxis)
二、Layout
什么是 layout?
layout 的作用是将数据转成适合绘图的结构,d3 提供了多种 layout, 如:Pie, Tree, Force, Partition, Cluster, Bundle 等等。更多介绍...
下面以绘制树形图为例:
{% highlight javascript %}
var tree = d3.layout.tree().size([degree, radius]);
// 得到结点数据
var nodeData = tree.nodes(data);
// 得到连线数据
var linkData = tree.links(nodeData);
{% endhighlight %}
1. 数据转换
tree-console出来的数据格式.pngparent
和 children
指针,联系着各个对象。
2. 生成曲线
{% highlight javascript %}
var diagonal = d3.svg.diagonal.radial()
// 点变换器
.projection(function(d){
return [d.y, d.x/180* Math.PI];
});
{% endhighlight %}
设置结点之间连线的形式,d3.svg.diagonal.radial()
调用径向对角线生成器。
对角线生成器:输入两个顶点坐标,生成一条贝塞尔曲线。
3. 移动
由于绘制后的树形图是以左上角为原点,向上展开的。故定位时需要做旋转。
tree-位移过程.pngtranslate()
, rotate()
- 初始化时,位于左上角;
- 整体 y 轴向下移动;
- 结点右移,注意到此时叶子结点是重合的(即 “曹丕”、“曹植”);
- 整体顺时针旋转;
- 结点逆时针旋转,回到水平线。
补充:
其中 .size([degree, radius]
设定范围,通过设置树形开口的角度以及延伸半径长度。
a. 角度
角度不同.pngb. 半径
半径不同.pngc. 为啥要叫 “半径”?设置角度为 360 度后,便一目了然了
tree-360-250.png三、图形生成器
图形生成器是 d3 提供的一个非常好用的功能,通过输入数据,生成绘制 SVG 图形所需要的格式。
如以折线举例:
折线图.png图中 7 个点数据如下:
折线图数据映射.png使用 d3 提供的 line 生成器,d3.svg.line()
, 便可把数据整合成绘制 path 所要的格式了,即添加 M, L, Z 等。
<path
d="M0,500 L125,500 L250,500 L375,500 L500,500 L625,500 L750,500 L750,0 L625,125 L500,187.5 L375,237.5 L250,262.5 L125,312.5 L0,375Z" >
</path>
常用图形生成器有:
// 折线
d3.svg.line()
.x()
.y()
// 区域
d3.svg.area()
.x0()
.x1()
.y0()
.y1()
// 坐标轴
d3.svg.axis()
.scale()
.orient()
.ticks()
// 弧形
d3.svg.arc()
.innerRadius()
.outerRadius()
四、其他
发现的一些技巧
- 使用 tickSize(-config.height) 来绘制分割细线;
-
shape-rendering: crispEdges;
使得数轴和刻度线精确到像素级 - 一种简化写法
- '(' + [margin.left, margin.top] + ')' 强制类型转换时,自动会转成 '( margin.left, margin.top )' 形式;
- 最佳实践: 设置属性应当与设置动画分离开来