0

0

D3.js 实现动态进度条实例

小云云

小云云

发布时间:2018-02-27 09:07:50

|

3153人浏览过

|

来源于php中文网

原创

d3 的全称是(data-driven documents),顾名思义可以知道是一个被数据驱动的文档。听名字有点抽象,说简单一点,其实就是一个 javascript 的函数库,使用它主要是用来做数据可视化的。如果你不知道什么是 javascript ,请先学习一下 javascript,推荐阮一峰老师的教程。

JavaScript 文件的后缀名通常为 .js,故 D3 也常使用 D3.js 称呼。D3 提供了各种简单易用的函数,大大简化了 JavaScript 操作数据的难度。由于它本质上是 JavaScript ,所以用 JavaScript 也是可以实现所有功能的,但它能大大减小你的工作量,尤其是在数据可视化方面,D3 已经将生成可视化的复杂步骤精简到了几个简单的函数,你只需要输入几个简单的数据,就能够转换为各种绚丽的图形。有过 JavaScript 基础的朋友一定很容易理解它。

我们经常使用svg或canvas来实现动态图形的绘制,但绘制过程相对较繁琐。对于直观漂亮的进度条,社区也有提供成熟的方案例如highcharts/ECharts等等,但基于配置的开发方式终究无法实现100%的自定义绘制。本文将带你使用D3.js从零一步一步实现动态进度条,并分享代码逻辑原理。

基础要求

  • 了解svg如何绘制基础图形

  • 了解D3.js v4版本

  • 了解如何使用D3.js (v4)绘制svg的基础图形

绘制圆形进度条

对于一个圆形进度条,我们先对其进行任务拆分:

  • 绘制嵌套圆弧

  • 圆心处的实时数据展示

  • 展现动画

  • 美化

1.绘制嵌套圆弧

对于圆形,svg提供现成的 circle 标签供使用,但是其劣势在于,对于圆形进度条使用 circle 可以满足,但对图形进一步扩展时比如绘制半圆, circle 的处理就棘手了。D3.js提供 arc 相关API对圆形的绘制方法进行了封装:

var arc = d3.arc()
   .innerRadius(180)
   .outerRadius(240)
   //.startAngle(0)
   //.endAngle(Math.PI)
arc(); // "M0,-100A100,100,0,0,1,100,0L0,0Z"

上述代码实现了对两个嵌套圆的绘制逻辑, d3.arc() 返回一个圆弧构造函数,并通过链式调用设置内圆与外圆的半径大小,起始角度与结束角度。执行 arc() 构造函数即可获得用于绑定在 上的路径数据。完整代码如下:



上述代码实现了2个步骤:

1.生成将0度作为起点的圆弧构造器 arcGenerator

2.设置 transform 图形偏移量,令图形在画布中央

目前画布上还没有任何元素,接下来我们实际图形的绘制。

var backGround = picture.append("path")
  .datum({endAngle: 2 * Math.PI})
  .style("fill", "#FDF5E6")
  .attr("d", arcGenerator);

我们对画布 picture 添加 元素,依据 endAngle() 特性,使用 datum() 方法将 {endAngle:Math.PI} 也就是终点角度 2π 绑定到 元素上,并将圆弧构造器赋值给 path 路径 d 。这样就生成了指定背景颜色的圆弧,实际图形如下:

第一个圆弧画好了,那么依据svg的层级关系 z-index ,所谓的进度条其实就是覆盖在第一层圆弧之上的第二层圆弧。同理可得:

var upperGround = picture.append('path')
  .datum({endAngle:Math.PI / 2})
  .style('fill','#FFC125')
  .attr('d',arcGenerator)

代码运行后可得:

 

2.圆心处的实时数据展示

第一部分我们已经实现了基于两个 path 的嵌套圆。第二部分我们来实现圆心处的实时数据展示。 在进度条进行加载时,我们在圆心处添加数据来表达当前的加载进度,使用 标签做展示即可:

var dataText = g.append('text')
  .text(12)
  .attr('text-anchor','middle')
  .attr('dominant-baseline','middle')
  .attr('font-size','38px')

暂时将数据设置为12,并设置水平居中和垂直居中,效果如下图:

 

3.展现动画

通过1,2两部分内容我们已经知道了:

  • 绘制进度条的实质是改变上层弧的角度

  • 当弧度是 2π 时为整圆,当弧度是 π 时为半圆

  • 圆形中的数据即为当前弧度相对 2π 的百分比

综上我们只要改变弧度值和数值同时设定改变过程所需时长即可实现所谓"动画"。在ECharts提供的官方实例中,通过 setInterval 来实现每隔固定一段时间进行数据更新,其实在D3.js中同样提供了类似方法来实现类似 setInterval 的功能:

基于vue2.0实现的滑动进度条
基于vue2.0实现的滑动进度条

基于vue2.0实现的滑动进度条

下载
d3.interval(function(){
 foreground.transition().duration(750).attrTween('d',function(d){
  var compute = d3.interpolate(d.endAngle,Math.random() * Math.PI * 2);
  return function(t){
   d.endAngle = compute(t);
   return arcGenerator(d);
  }
  
 })
},1000)

对这段代码进行拆解:

  • d3.interval() 方法提供了 setInterval() 的功能

  • selection.transition.duration() 设置了当前DOM属性过渡变化为指定DOM属性的过程所需时间,毫秒为单位

  • transation.attrTween 为插值功能API,那么何谓插值?

概括来说,在给定的离散数据中补插函数,可以使这条连续函数通过全部数据点。举个例子,给定一个p,想实现其背景颜色的从左边红(red)到右边绿(green)的线性渐变,每一区域的色值该如何计算呢?只需:

var compute = d3.interpolate(d3.rgb(255,0,0),d3.rgb(0,255,0));

compute 即为插值函数,参数范围为[0,1],只要你输入该范围内的数字,那么 compute 函数将返回对应的颜色值。这样的插值有什么用呢?可看下图:

 

假设上图的p长度width为100,那么将[0,100]依比例关系转化为[0,10]的范围数据并输入 compute 函数中,即可得到某一区域对应的颜色。当然,对于线性面积的处理我们不应该使用离散数据作为输入和输出,所以D3.js提供更方便的线性渐变API d3.linear 等,这里就不展开描述了。

言归正传,代码 d3.interpolate(d.endAngle,Math.random() * Math.PI * 2); 实现了如下插值范围:

["当前角度值","随机角度值"] //表达区间而非数组

而后返回一个参数为 t 的函数,那么该函数的作用是什么呢?

t 参数与 d 类似,是D3.js内部实现的插值,其范围为[0,1]。 t 参数根据设置的 duration() 时长自动计算在[0,1]内合适的插值数量,并返回插值结果,实现线性平稳的过渡动画效果。

完成滚动条的动画加载效果,我们接下来写圆心实时数据的变化逻辑,只要实现简单的赋值即可,完整代码如下:

d3.interval(function(){
  foreground.transition().duration(750).attrTween('d',function(d){
   var compute = d3.interpolate(d.endAngle,Math.random() * Math.PI * 2);
   return function(t){
    d.endAngle = compute(t);
    var data = d.endAngle / Math.PI / 2 * 100;
    //设置数值
    d3.select('text').text(data.toFixed(0) + '%');
    //将新参数传入,生成新的圆弧构造器
    return arcGenerator(d);
   }
  })
 },2000)

最终效果如下:

 

4.美化

1,2,3部分我们实现了最基本的进度条样式和功能,但样式看起来还是很单调的,我们接下来我们对进度条进行线性渐变处理。我们使用D3.js提供的线性插值API:

var colorLinear = d3.scaleLinear().domain([0,100]).range(["#EEE685","#EE3B3B"]);

colorLinear 同样是一个插值函数,我们输入[0,100]区间中的数值,就会返回对应["#EEE685","#EE3B3B"]区间内的颜色值。比如当进度条显示进度为"80%"时:

var color = colorLinear(80);
//color即为"80%"对应的色值

实现了颜色取值后,我们只需在进度条变化时,将原有颜色改变即可:

d3.interval(function(){
  foreground.transition().duration(750).attrTween('d',function(d){
   var compute = d3.interpolate(d.endAngle,Math.random() * Math.PI * 2);
   return function(t){
    d.endAngle = compute(t);
    var data = d.endAngle / Math.PI / 2 * 100;
    //设置数值
    d3.select('text').text(data.toFixed(0) + '%');
    //将新参数传入,生成新的圆弧构造器
    return arcGenerator(d);
   }
  })
  .styleTween('fill',function(d){
   return function(t){
    var data = d.endAngle / Math.PI / 2 * 100;
    //返回数值对应的色值
    return colorLinear(data);
   }
  })
 },2000)

styleTween 与 attrTween 类似,是实现改变样式的插值函数。采用链式调用的形式同时对进度条数值和颜色的设置即可。最终实现的效果如下:

 

综上我们实现了在不同数值下颜色变化的圆形进度条,可常用于告警,提醒等业务场景。

绘制矩形进度条

矩形进度条相比圆形进度条简单了很多,同样基于插值原理,平滑改变矩形的长度即可。直接上代码:


 


 

实现的效果如下:

 

总结

基于D3.js绘制进度条的关键点在于插值,从而正确地使图形平滑过渡。如果一定要使用svg或纯css实现矩形和圆形的进度条当然也是可行的,但对于路径和动画的处理,以及css的书写要求都复杂了不少。我们观察到使用D3.js绘制上述两种进度条的逻辑代码几乎完全使用js实现,同时代码量可以控制在20行左右并可封装复用,已经非常精炼了,在自定义图表开发上非常有优势。

对于进度条的衍生版仪表盘图表,相比基础进度条增加了刻度描述和指针计算,但万变不离其宗,只要掌握插值原理和使用,处理类似图表都将得心应手。

相关推荐:

用css3和jquery实现的渐变的动态进度条

基于jquery的多彩百分比 动态进度条 投票效果显示效果实现代码_jquery

微信小程序实现圆形进度条实例分享

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

557

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

394

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

754

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

478

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

454

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

1031

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

658

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

554

2023.09.20

AO3中文版入口地址大全
AO3中文版入口地址大全

本专题整合了AO3中文版入口地址大全,阅读专题下面的的文章了解更多详细内容。

1

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.9万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.3万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号