D3.js, 数据可视化入门笔记

作者 : 开心源码 本文共2702个字,预计阅读时间需要7分钟 发布时间: 2022-05-12 共203人阅读

D3入门

D3(Data Driven Docuemtns)是一套非常优秀的数据可视化库,它可以帮助开发者在浏览器中直观地展示各种数据。

尽管这个工具本身非常强大,但是其学习门槛并不低。其中一个起因在于教程的不友好,新手学习起来很容易没有头绪。官方给出的 tutorials 一方面升级不及时,导致和API文档对不上号,用v3的教程对照v5的API文档看的一头雾水。二来很多例子也相对复杂,缺少少量循序渐进的讲解。

这里将会分享如何实现少量简单的数据可视化图形。

Fundamentals 入门教学

首先推荐一篇优秀的 d3 基础教程

如何制作一个饼图/环形图(pie/donut)

我们可以把一个数组 [110, 12, 18] ,用环形图的方式展现。

donut.png

源代码在这里查看。

像这样的饼图,可以分成三个部门:环形(Arc)、文字(Label)和连接环形文字之间的连线(Line)。

Arc

在这里每一条数据对应的环形,可以使用 SVG 里的 Path 元从来表示,通过给 Path 传递形容图形形状的参数,便可以在浏览器中渲染出我们需要的图形。为了画出环形,我们需要几个基本信息:

  • 环内径 (innerRadius)
  • 环外经 (outerRadius)
  • 起始弧度 (startAngle)
  • 终止弧度 (endAngle)

这里使用弧度来表示环的起始和终止位置,而不是角度。长度等于半径的弧长对应的弧度定义为1,所以对于一个完整的圆,弧度是 2 * PI。后面我们会用到中间弧度 (midAngle) 来判断环在左半边圆还是右半边圆,这可以帮助我们定位数据标签 (label)。

d3-shape 可以帮我们计算需要的图形参数。调用 d3.pie() 会返回一个 pie 生成器 (generator)。这个生成器可以把传入的数据转化成扇形/环形相应的弧度。而为了得到环形的形状形容(path),我们还要用到 d3.arc 生成器,并传入内外径参数,有了弧度和半径参数之后,才能生成实际的图形。

// 指定了两个相关函数:value accessor 和 sort// value 函数表示如何从单个 data 中取取到值// sort 函数假如没有专门指定的话,会默认降序排列const pie = d3.pie().value((d) => d).sort(null);const slices = pie(data);// slices 的结构如下,注意 slices 的排序和给定的 data 排序一致,index 对应 sort 之后的顺序。[  {    data: number,    value: number,    index: number,    startAngle: number,    endAngle: number,    padAngle: number,  },  ...]// 带有内外径的 arc 生成器const innerArc = d3.arc().innerRadius(innerRadius).outerRadius(outerRadius);// D3 的选择 (selection) 部分const slice = d3.select('.slices').selectAll('path').data(slices);slice.enter()  .append('path')  .attr('d', (d, i) => innerArc(slices[i]))  .attr('transform', `translate(${width / 2}, ${height / 2})`)  .attr('fill', (d, i) => colorArray[i % (colorArray.length)]);slice.exit().remove();

Line

Line 是连接环形图心和文字标签之间的连线,可以用 Polyline 元素渲染。为了绘制连线,我们需要知道起点、转折点和终点。

连线的起点是环的圆心,转折点是外层一个不可见的同弧度环的圆心,终点根据环的位置判断,假如环在左半边圆,那么从转折点往左平移一段距离,在右边则向右平移一段距离。

 const endPoints = []; // 记录下终点,为文字标签定位       const pivotArc = d3.arc().innerRadius(outerRadius).outerRadius(pivotRadius);      const line = d3.select('.lines').selectAll('polyline').data(slices);      line.enter()        .append('polyline')        .attr('points', (d, i) => {          const slice = slices[i];          const innerCentroid = innerArc.centroid(slice);          const x1 = innerCentroid[0] + width / 2;          const y1 = innerCentroid[1] + height / 2;          const pivotPoint = pivotArc.centroid(slice);          const x2 = pivotPoint[0] + width / 2;          const y2 = pivotPoint[1] + height / 2;          const midAngle = getMidAngle(slice);          const x3 = x2 + (midAngle > Math.PI ? -20 : 20);          const y3 = y2;          endPoints[i] = [x3, y3];          return `${x1},${y1} ${x2},${y2} ${x3},${y3}`;        })        .attr('fill', 'none')        .attr('stroke', (d, i) => colorArray[i % (colorArray.length)]);      line.exit().remove();

Label

定位到终点之后,我们可以增加文字标签。

const label = svg.select('.labels').selectAll('text').data(slices);      label.enter()  .append('text')  .text((d) => d.value)  .attr('transform', (d, i) => {    const x = endPoints[i][0] + (getMidAngle(d) > Math.PI ? -10 : 10);     const y = endPoints[i][1] + 5;     return `translate(${x}, ${y})`;   })   .attr('text-anchor', (d) => {     const midAngle = getMidAngle(d);     return midAngle > Math.PI ? 'end' : 'start';   });   label.exit().remove();

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » D3.js, 数据可视化入门笔记

发表回复