d3.js数据可视化从入门到放不下(二)—— 实现一个基础图表

tech2024-05-13  76

接上回的enter-update-exit模式,其实看书上的概念的话也不难理解,就是把整个图表的的生命周期分为进入-更新-退出三个阶段,再换句话说,可以把这三个阶段理解为三个函数,在不同生命周期执行相应函数即可。

个人觉得在学习一个新的框架或工具的时候,最重要的还是理解其使用思路和模式,这点极为重要,只要这点搞懂了,其它的也不是什么大问题了,剩下的无非就是语法的问题,语法这个东西嘛,多练习就行了。

本次主要分享基于d3.js来实现一个基本的图表demo,旨在深入理解其enter-update-exit模式。并以此为基础demo,在后期学习d3.js的过程中用新学到的特点不断完善丰富。

一、mock方案

首先,本例中将数据存放在数组中,然后定义一个render函数,并通过定时器不断调用它,并在定时器中修改数组的值,使图表更新。

二、编码

【进入】周期

```js 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```元素(用于显示数字)。 - 总结:在【进入】周期中,主要搭建最终可视化效果的框架和结构。 - 此时页面效果:![在这里插入图片描述](https://img-blog.csdnimg.cn/2020090317455928.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hlbXlXZWI=,size_16,color_FFFFFF,t_70#pic_center)

【更新】周期

// 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秒钟调用一次

三、最终效果

ps:自己脑补一下它动起来的样子。。。

四、结语

基础demo,后续文章会陆续加入坐标系、样式、进出场动画等。

最新回复(0)