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() 构造函数即可获得用于绑定在 <path> 上的路径数据。完整代码如下:
<!--html--> <svg></svg> <script> var arcGenerator = d3.arc().innerRadius(80).outerRadius(100).startAngle(0); var picture = d3.select('svg').append('g').attr('transform','translate(480,250)'); </script>
上述代码实现了2个步骤:
1.生成将0度作为起点的圆弧构造器 arcGenerator
2.设置 transform 图形偏移量,令图形在画布中央
目前画布上还没有任何元素,接下来我们实际图形的绘制。
var backGround = picture.append("path") .datum({endAngle: 2 * Math.PI}) .style("fill", "#FDF5E6") .attr("d", arcGenerator);
我们对画布 picture 添加 <path> 元素,依据 endAngle() 特性,使用 datum() 方法将 {endAngle:Math.PI} 也就是终点角度 2π 绑定到 <path> 元素上,并将圆弧构造器赋值给 path 路径 d 。这样就生成了指定背景颜色的圆弧,实际图形如下:
第一个圆弧画好了,那么依据svg的层级关系 z-index ,所谓的进度条其实就是覆盖在第一层圆弧之上的第二层圆弧。同理可得:
var upperGround = picture.append('path') .datum({endAngle:Math.PI / 2}) .style('fill','#FFC125') .attr('d',arcGenerator)
代码运行后可得:
2.圆心处的实时数据展示
第一部分我们已经实现了基于两个 path 的嵌套圆。第二部分我们来实现圆心处的实时数据展示。 在进度条进行加载时,我们在圆心处添加数据来表达当前的加载进度,使用 <text> 标签做展示即可:
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π 的百分比