【D3.js 入门系列二】理解 Update && Enter && Exit、制作交互式动态图表

上一章:《【D3.js 入门系列一】从零开始绘制一个柱形图》

声明:本教程针对D3.js v3版本进行讲解。

【Lesson1】理解 Update、Enter、Exit

Update、Enter、Exit 是 D3 中三个非常重要的概念,它处理的是当选择集和数据的数量关系不确定的情况。

1. 什么是 Update、Enter、Exit

前面章里,反复出现了形如以下的代码。

svg.selectAll("rect")   //选择svg内所有的矩形
    .data(dataset)      //绑定数组
    .enter()            //指定选择集的enter部分
    .append("rect")     //添加足够数量的矩形元素
复制代码

前面提到,这段代码使用的情况是当以下情况出现的时候:

有数据,而没有足够图形元素的时候,使用此方法可以添加足够的元素。

当时并没有深究这段代码是什么意思,本章将对此进行讲解。但是,由于此问题相对复杂,本章只进行最初步的介绍。

假设,在 body 中有三个 p 元素,有一数组 [3, 6, 9],则可以将数组中的每一项分别与一个 p 元素绑定在一起。但是,有一个问题:当数组的长度与元素数量不一致(数组长度 > 元素数量 or 数组长度 < 元素数量)时呢?这时候就需要理解 Update、Enter、Exit 的概念。

如果数组为 [3, 6, 9, 12, 15],将此数组绑定到三个 p 元素的选择集上。可以想象,会有两个数据没有元素与之对应,这时候 D3 会建立两个空的元素与数据对应,这一部分就称为 Enter。而有元素与数据对应的部分称为 Update。如果数组为 [3],则会有两个元素没有数据绑定,那么没有数据绑定的部分被称为 Exit。示意图如下所示。

看到这,我想大家能体会到为什么本节最开始处的代码能够给 SVG 内添加足够数量的元素了吧。它的意思其实是:

此时 SVG 里没有 rect 元素,即元素数量为 0。有一数组 dataset,将数组元素数量为 0 的选择集绑定后,选择其 Enter 部分(请仔细看上图),然后添加(append)元素,也就是添加足够的元素,使得每一个数据都有元素与之对应。

2. Update 和 Enter 的使用

当对应的元素不足时 ( 绑定数据数量 > 对应元素 ),需要添加元素(append)。

现在 body 中有三个 p 元素,要绑定一个长度大于 3 的数组到 p 的选择集上,然后分别处理 update 和 enter 两部分。

var dataset = [ 3 , 6 , 9 , 12 , 15 ];
 
//选择body中的p元素
var p = d3.select("body").selectAll("p");
 
//获取update部分
var update = p.data(dataset);
 
//获取enter部分
var enter = update.enter();
 
//update部分的处理:更新属性值
update.text(function(d){
    return "update " + d;
});
 
//enter部分的处理:添加元素后赋予属性值
enter.append("p")
    .text(function(d){
        return "enter " + d;
    });
复制代码

结果如下图,update 部分和 enter 部分被绑定的数据很清晰地表示了出来。

请大家记住:

  • update 部分的处理办法一般是:更新属性值
  • enter 部分的处理办法一般是:添加元素后,赋予属性值
3. Update 和 Exit 的使用

当对应的元素过多时 ( 绑定数据数量 < 对应元素 ),需要删掉多余的元素。

现在 body 中有三个 p 元素,要绑定一个长度小于 3 的数组到 p 的选择集上,然后分别处理 update 和 exit 两部分。

var dataset = [ 3 ];
 
//选择body中的p元素
var p = d3.select("body").selectAll("p");
 
//获取update部分
var update = p.data(dataset);
 
//获取exit部分
var exit = update.exit();
 
//update部分的处理:更新属性值
update.text(function(d){
    return "update " + d;
});
 
//exit部分的处理:修改p元素的属性
exit.text(function(d){
        return "exit";
    });
 
//exit部分的处理通常是删除元素
// exit.remove();
复制代码

结果如下,请大家区分好 update 部分和 exit 部分。这里为了表明哪一部分是 exit,并没有删除掉多余的元素,但实际上 exit 部分的绝大部分操作是删除。

请大家记住:

  • exit 部分的处理办法一般是:删除元素(remove)

【Lesson2】让图表动起来

D3 支持制作动态的图表。有时候,图表的变化需要缓慢的发生,以便于让用户看清楚变化的过程,也能给用户不小的友好感。

1. 什么是动态效果

前面一章制作的图表是一蹴而就地出现,然后绘制完成后不再发生变化的,这是静态的图表。

动态的图表,是指图表在某一时间段会发生某种变化,可能是形状、颜色、位置等,而且用户是可以看到变化的过程的。

例如,有一个圆,圆心为 (100, 100)。现在我们希望圆的 x 坐标从 100 移到 300,并且移动过程在 2 秒的时间内发生。

这种时候就需要用到动态效果,在 D3 里我们称之为过渡(transition)

2. 实现动态的方法

D3 提供了 4 个方法用于实现图形的过渡:从状态 A 变为状态 B

transition()

启动过渡效果。

其前后是图形变化前后的状态(形状、位置、颜色等等),例如:

.attr("fill","red")         //初始颜色为红色
.transition()               //启动过渡
.attr("fill","steelblue")   //终止颜色为铁蓝色
复制代码

D3 会自动对两种颜色(红色和铁蓝色)之间的颜色值(RGB值)进行插值计算,得到过渡用的颜色值。我们无需知道中间是怎么计算的,只需要享受结果即可。

duration()

指定过渡的持续时间,单位为毫秒。

如 duration(2000) ,指持续 2000 毫秒,即 2 秒。

ease()

指定过渡的方式,常用的有:

  • linear:普通的线性变化
  • circle:慢慢地到达变换的最终状态
  • elastic:带有弹跳的到达最终状态
  • bounce:在最终状态处弹跳几次

调用时,格式形如: ease(“bounce”)。

delay()

指定延迟的时间,表示一定时间后才开始转变,单位同样为毫秒。此函数可以对整体指定延迟,也可以对个别指定延迟。

例如,对整体指定时:

.transition()
.duration(1000)
.delay(500)
复制代码

如此,图形整体在延迟 500 毫秒后发生变化,变化的时长为 1000 毫秒。因此,过渡的总时长为1500毫秒。

又如,对一个一个的图形(图形上绑定了数据)进行指定时:

.transition()
.duration(1000)
.delay(funtion(d,i){
    return 200*i;
})
复制代码

如此,假设有 10 个元素,那么第 1 个元素延迟 0 毫秒(因为 i = 0),第 2 个元素延迟 200 毫秒,第 3 个延迟 400 毫秒,依次类推….整个过渡的长度为 200 * 9 + 1000 = 2800 毫秒。

3. 实现简单的动态效果

下面将在 SVG 画布里添加三个圆,圆出现之后,立即启动过渡效果。

第一个圆,要求移动 x 坐标。

var circle1 = svg.append("circle")
        .attr("cx", 100)
        .attr("cy", 100)
        .attr("r", 45)
        .style("fill","green");
 
//在1秒(1000毫秒)内将圆心坐标由100变为300
circle1.transition()
    .duration(1000)
    .attr("cx", 300);
复制代码

第二个圆,要求既移动 x 坐标,又改变颜色。

var circle2 = svg.append("circle")... //与第一个圆一样,省略部分代码
 
//在1.5秒(1500毫秒)内将圆心坐标由100变为300,
//将颜色从绿色变为红色
circle2.transition()
    .duration(1500)
    .attr("cx", 300)
    .style("fill","red");
复制代码

第三个圆,要求既移动 x 坐标,又改变颜色,还改变半径。

var circle3 = svg.append("circle")... //与第一个圆一样,省略部分代码
 
//在2秒(2000毫秒)内将圆心坐标由100变为300
//将颜色从绿色变为红色
//将半径从45变成25
//过渡方式采用bounce(在终点处弹跳几次)
circle3.transition()
    .duration(2000)
    .ease("bounce")
    .attr("cx", 300)
    .style("fill","red")
    .attr("r", 25);
复制代码
4. 给柱形图加上动态效果

在上一章完整柱形图的基础上稍作修改,即可做成一个带动态效果的、有意思的柱形图。

在添加文字元素和矩形元素的时候,启动过渡效果,让各柱形和文字缓慢升至目标高度,并且在目标处跳动几次。

对于文字元素,代码如下:

.attr("y",function(d){
    var min = yScale.domain()[0];
    return yScale(min);
})
.transition()
.delay(function(d,i){
    return i * 200;
})
.duration(2000)
.ease("bounce")
.attr("y",function(d){
    return yScale(d);
});
复制代码

文字元素的过渡前后,发生变化的是 y 坐标。其起始状态是在 y 轴等于 0 的位置(但要注意,不能在起始状态直接返回 0,要应用比例尺计算画布中的位置)。终止状态是目标值。

对于矩形元素,思想与文字元素一样,只是在计算起始状态时要稍微复杂一些,请读者自行研读页面底部的示例代码地址中的代码。


【Lesson3】交互式操作

与图表的交互,指在图形元素上设置一个或多个监听器,当事件发生时,做出相应的反应。

1. 什么是交互

交互,指的是用户输入了某种指令,程序接受到指令之后必须做出某种响应。对可视化图表来说,交互能使图表更加生动,能表现更多内容。例如,拖动图表中某些图形、鼠标滑到图形上出现提示框、用触屏放大或缩小图形等等。

用户用于交互的工具一般有三种:鼠标、键盘、触屏。

2. 如何添加交互

对某一元素添加交互操作十分简单,代码如下:

var circle = svg.append("circle");
 
circle.on("click", function(){
    //在这里添加交互内容
});
复制代码

这段代码在 SVG 中添加了一个圆,然后添加了一个监听器,是通过 on() 添加的。在 D3 中,每一个选择集都有 on() 函数,用于添加事件监听器。

on() 的第一个参数是监听的事件,第二个参数是监听到事件后响应的内容,第二个参数是一个函数。

鼠标常用的事件有:

  • click:鼠标单击某元素时,相当于 mousedown 和 mouseup 组合在一起。
  • mouseover:光标放在某元素上。
  • mouseout:光标从某元素上移出来时。
  • mousemove:鼠标被移动的时候。
  • mousedown:鼠标按钮被按下。
  • mouseup:鼠标按钮被松开。
  • dblclick:鼠标双击。

键盘常用的事件有三个:

  • keydown:当用户按下任意键时触发,按住不放会重复触发此事件。该事件不会区分字母的大小写,例如“A”和“a”被视为一致。
  • keypress:当用户按下字符键(大小写字母、数字、加号、等号、回车等)时触发,按住不放会重复触发此事件。该事件区分字母的大小写。
  • keyup:当用户释放键时触发,不区分字母的大小写。

触屏常用的事件有三个:

  • touchstart:当触摸点被放在触摸屏上时。
  • touchmove:当触摸点在触摸屏上移动时。
  • touchend:当触摸点从触摸屏上拿开时。

当某个事件被监听到时,D3 会把当前的事件存到 d3.event 对象,里面保存了当前事件的各种参数,请大家好好参详。如果需要监听到事件后立刻输出该事件,可以添加一行代码:

circle.on("click", function(){
    console.log(d3.event);
});
复制代码
3. 带有交互的柱形图

将【D3.js 入门系列一】的部分代码修改成如下代码。

var rects = svg.selectAll(".MyRect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("class","MyRect")   //把类里的 fill 属性清空
        .attr("transform","translate(" + padding.left + "," + padding.top + ")")
        .attr("x", function(d,i){
            return xScale(i) + rectPadding/2;
        } )
        .attr("y",function(d){
            return yScale(d);
        })
        .attr("width", xScale.rangeBand() - rectPadding )
        .attr("height", function(d){
            return height - padding.top - padding.bottom - yScale(d);
        })
        .attr("fill","steelblue")       //填充颜色不要写在CSS里
        .on("mouseover",function(d,i){
            d3.select(this)
                .attr("fill","yellow");
        })
        .on("mouseout",function(d,i){
            d3.select(this)
                .transition()
                .duration(500)
                .attr("fill","steelblue");
        });
复制代码

这段代码添加了鼠标移入(mouseover),鼠标移出(mouseout)两个事件的监听器。监听器函数中都使用了 d3.select(this),表示选择当前的元素,this 是当前的元素,要改变响应事件的元素时这么写就好。

mouseover 监听器函数的内容为:将当前元素变为黄色

mouseout 监听器函数的内容为:缓慢地将元素变为原来的颜色(蓝色)

代码示例地址:github.com/legend-li/D…

未完待续~

参考资料:www.ourd3js.com/
D3.js(v3)中文api:github.com/d3/d3/wiki/…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
08-10
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值