接上回的enter-update-exit模式,其实看书上的概念的话也不难理解,就是把整个图表的的生命周期分为进入-更新-退出三个阶段,再换句话说,可以把这三个阶段理解为三个函数,在不同生命周期执行相应函数即可。
个人觉得在学习一个新的框架或工具的时候,最重要的还是理解其使用思路和模式,这点极为重要,只要这点搞懂了,其它的也不是什么大问题了,剩下的无非就是语法的问题,语法这个东西嘛,多练习就行了。
本次主要分享基于d3.js来实现一个基本的图表demo,旨在深入理解其enter-update-exit模式。并以此为基础demo,在后期学习d3.js的过程中用新学到的特点不断完善丰富。
一、mock方案
首先,本例中将数据存放在数组中,然后定义一个render函数,并通过定时器不断调用它,并在定时器中修改数组的值,使图表更新。
二、编码
-
【进入】周期
let data = [10, 15, 30, 50, 80, 65, 55, 30, 20, 10, 8];
function render(data) {
// Enter
d3.select("body")
.selectAll("div.h-bar") // <- A
.data(data) // <- B
.enter() // <- C
.append("div") // <- D
.attr("class", "h-bar") // <- E
.append("span"); // <- F
}
render(data);
-
代码解读:
此时为【进入】的周期,在第A行中选中了所有拥有.h-bar类的div元素。但是页面上实际是没有这些元素的,这个时候就需要如第B行那样调用data方法,刚才第A行的含义是实际上是声明页面上应该有这些拥有.h-bar类的div元素,也就是说这个操作是选中了图形元素的集合。
然后再调用data方法,并将图表数据(即外部我们声明好的数组)作为参数传递给data方法。此时外部的数组便绑定到了这些即将要创建的图形元素上了。
此时,数据集合和图形集合都创建好了,在第C行调用enter方法选出所有还没有被可视化的数据元素,然后再第F行中为其追加一个div元素,并在第E行中为其设置样式为h-bar,然后再在其中追加一个span元素(用于显示数字)。 -
总结:在【进入】周期中,主要搭建最终可视化效果的框架和结构。
-
此时页面效果:
-
【更新】周期
// Update
d3.select("body") // <- A
.selectAll("div.h-bar") // <- B
.data(data) // <- C
.style("width", (d) => d * 3 + "px") // <- D
.select("span") // <- E
.text((d) => d); // <- F
-
代码解读: 如第
A、B、C行所示,和【进入】周期时一样,首先定义图形元素集合和数据集合。主要区别在于第D行,从语义化的角度理解,此时为【更新】周期,所以并不需要调用enter方法,我们要做的是修改它的样式。在第C行中,通过调用data方法,返回了图形元素集合和数据集合的交集。
然后再第D行中使用style方法修改其宽度,需要注意的是为了让图标看起来更直观,我们将宽度设置为其本身数值的3倍。最后,在第E行中再选中其内部的span元素,并在第F行中将span的内容设置为这个数值。
需要单独说明的是:- 形参
d实际上就是指代的与当前图形元素关联的数据的值; - 代码中的样式为外部独立的
css写好的,此处不再赘述。
- 形参
-
此时页面效果:
-
【退出】周期
// Exit
d3.select("body") // <- A
.select("div.h-bar") // <- B
.data(data) // <- C
.exit(). // <- D
remove(); // <- E
-
代码解读:
第A、B、C行和前面一样,在退出模式我们需要第D行调用exit方法返回这些需要进行删除操作的元素,然后再在第E行调用remove方法来把这个元素从页面中移除掉。 这样做的目的是将上一次的渲染的元素从DOM文档中删除,以保证每次调用render函数的时候所有的图形和数据都是绝对匹配的,避免不可预知的异常问题。 -
优化
为了让这个例子更加直观一点,我们让这个简易图表动起来。
setInterval(() => {
data.shift();
data.push(Math.round(Math.random() * 100));
render(data);
}, 2000);
- 一句话代码解读:很简单,删除
mock数据的第一个值,然后再在最后随机加一个数字,再用定时器每2秒钟调用一次
三、最终效果
四、结语
基础demo,后续文章会陆续加入坐标系、样式、进出场动画等。