【D3.js in Action 3 精译_039】4.3 D3 面积图的绘制方法及其边界标签的添加

news2024/11/27 12:50:47

当前内容所在位置:

  • 第四章 直线、曲线与弧线的绘制 ✔️
    • 4.1 坐标轴的创建(上篇)
      • 4.1.1 D3 中的边距约定(中篇)
      • 4.1.2 坐标轴的生成(中篇)
        • 4.1.2.1 比例尺的声明(中篇)
        • 4.1.2.2 坐标轴的添加(下篇)
        • 4.1.2.3 轴标签的添加(下篇)
    • 4.2 D3 折线图的绘制
      • 4.2.1 直线生成工具的使用
      • 4.2.2 对数据点作曲线插值处理
    • 4.3 D3 面积图的绘制 ✔️
      • 4.3.1 面积图生成工具的用法 ✔️
      • 4.3.2 用标签提高图表的可读性 ✔️
    • 4.4 D3 弧形图的绘制

文章目录

    • 4.3 面积图的绘制 Drawing an area
      • 4.3.1 面积图生成工具的用法 Using the area generator
      • 4.3.2 用标签提高图表的可读性 Enhancing readability with labels

《D3.js in Action》全新第三版封面

《D3.js in Action》全新第三版封面

译者按
由于 D3 的折线图和面积图在实现方式上相似度极高,这一篇就趁热打铁,将示例折线图剩下的面积图部分一并学完。看似复杂的面积图在作者精心绘制的示意图的帮助下变得非常简单(至少比我的其他专栏要容易很多),曾在 MSOffice 中盛行的“字不如表、表不如图”的说法用到 D3 数据可视化上依然适用。如果早几年出现这样的扫盲级 D3 参考书,如今国内数据可视化领域 ECharts 一手遮天的局面没准还真能被打破。一起学起来吧!

4.3 面积图的绘制 Drawing an area

本节将实现示例折线图后方的面积图部分,用于展示每个日期最低气温与最高气温的波动范围。D3 绘制面积图的方法与绘制折线图类似,也是通过 SVG 的路径元素来创建。D3 还专门提供了面积图生成工具函数 d3.area() 来处理路径 d 属性的复杂运算。

动手绘制前还需要注意一点:示例中的面积图位于折线图的 后方(behind the line chart)。鉴于屏幕元素的渲染顺序与添加到 SVG 父容器的元素顺序保持一致,因此该面积区域的实现代码应该添加到创建折线图的代码 前面

4.3.1 面积图生成工具的用法 Using the area generator

首先声明一个面积图生成工具函数(area generator function),并赋给常量 areaGenerator。根据以下示例代码,面积生成工具至少需要三个访问器函数(accessor functions)。一是 x(),用于计算数据点的水平坐标,与直线生成工具完全相同;垂直方向上则略有不同,数据点从一组变为了两组,分别对应面积区域的上下边缘,因此需要设置 y0()y1() 两个访问器函数。注意,示例面积图中的上下边缘数据点具有相同的水平坐标:

const areaGenerator = d3.area()
  .x(d => xScale(d.date))
  .y0(d => yScale(d.min_temp_F))
  .y1(d => yScale(d.max_temp_F));

图 4.19 生动直观地展示了面积区域的下边界和上边界情况,以及面积生成工具对相关数据的计算处理过程:

图 4.19 面积生成工具 d3.area() 与三个及更多访问器函数的组合用法示意图。绘制最高最低气温构成的温差区域,需要用到 x()、y0() 和 y1(),分别用于计算各数据点的水平坐标、面积区下边界(即当日最低气温)的垂直坐标、以及面积区上边界(即当日最高气温)的垂直坐标。

【图 4.19 面积生成工具 d3.area() 与三个及更多访问器函数的组合用法示意图。绘制最高最低气温构成的温差区域,需要用到 x()、y0() 和 y1(),分别用于计算各数据点的水平坐标、面积区下边界(即当日最低气温)的垂直坐标、以及面积区上边界(即当日最高气温)的垂直坐标。】

与折线图类似,我们同样可以在面积生成工具函数上链式调用访问器函数 curve() 来对面积图的上下边缘作曲线插值处理,这里还是沿用上一节介绍过的 D3 内置插值函数 d3.curveCatmullRom,如以下代码所示:

const areaGenerator = d3.area()
  .x(d => xScale(d.date))
  .y0(d => yScale(d.min_temp_F))
  .y1(d => yScale(d.max_temp_F))
  .curve(d3.curveCatmullRom);

面积生成器准备就绪后,就可以在内部图表选择集上添加一个 SVG 路径元素。该元素的 d 属性,可以通过刚才备好的面积生成器计算得到,传入参数为数据集 data。剩下的都是一些与审美相关的属性设置:填充色通过 fill 属性实现,属性值就是前面声明过的紫红色常量 aubergine;为了让面积区域与折线部分清晰可辨,可以给面积图加一点透明度,指定其 fill-opacity 属性为 20%,最终渲染效果如图 4.20 所示。注意,颜色常量 aubergine 必须先声明再使用:

innerChart
  .append("path")
    .attr("d", areaGenerator(data))
    .attr("fill", aubergine) // 即 "#75485E"
    .attr("fill-opacity", 0.2);

图 4.20 由折线图表示的日均气温与面积图表示的当日气温波动范围的绘制效果图

【图 4.20 由折线图表示的日均气温与面积图表示的当日气温波动范围的绘制效果图】

可以看出,D3 面积图的绘制过程与折线图的绘制十分类似。二者的主要区别在于,折线图只有一组数据点,用直线段进行绘制;而面积图需要处理上下两个边缘,每个边缘对应一组数据点。这就是直线生成器函数只需要两个访问器函数(即 x()y())、而面积生成器需要至少三个访问器函数(本例即为 x()y0()y1())的根本原因,如图 4.21 所示:

图 4.21 D3 面积图的绘制步骤

【图 4.21 D3 面积图的绘制步骤】

4.3.2 用标签提高图表的可读性 Enhancing readability with labels

至此,我们实现了 2021 年纽约市日均气温的折线图的绘制,并同步展示了当日最低气温与最高气温的变化区域,效果看上去已经很不错了;但我们还需要确保看到这张图表的人们能够轻松准确地理解折线与面积的含义。添加图表标签(label)就是个不错的想法。

前面学过,图表标签不过是放置在可视化作品里的 SVG 文本元素。在本例中,不妨创建三个标签,分别用于表示折线图末尾的平均气温、位置靠下的当日最低气温、以及靠上放置的当日最高气温。

先从折线图标签开始。先将 SVG 文本元素添加到内部图表选择集中,然后调用 text() 方法设置标签文本为 "Average temperature"(即“平均气温”);接着通过 xy 属性设置标签在绘图区内的坐标。

我们希望标签位于折线图末尾,也就是最后一个数据点的后面;其水平坐标可以通过先前声明的常量 lastDate 由水平比例尺函数 xScale() 算得;另外可以再给标签一个 10px 的间距。

而垂直坐标的计算还需要一个当天的平均气温值,可以先通过 data[data.length - 1] 获取到最后一个数据点;然后利用句点标识符拿到对应的平均气温;接着再调用垂直比例尺函数 yScale() 算得该数据点的垂直坐标。最后复用颜色常量 aubergine,通过 fill 属性来指定标签文本的颜色,如以下代码所示:

innerChart
  .append("text")
    .text("Average temperature")
    .attr("x", xScale(lastDate) + 10)
    .attr("y", yScale(data[data.length - 1].avg_temp_F))
    .attr("fill", aubergine);

如果保存项目并在浏览器中查看效果,会发现文本标签的底边与折线图最后一个数据点的中心垂直对齐了。默认情况下,SVG 文本元素的基准线(baseline)位于文本的底边位置,如图 4.22 (左图)所示。这时可以使用 dominant-baseline 属性来手动修改。如以下代码所示,将该属性值设为 middle,基准线就改到了文本的中心位置:

innerChart
  .append("text")
    .text("Average temperature")
    .attr("x", xScale(lastDate) + 10)
    .attr("y", yScale(data[data.length - 1].avg_temp_F))
    .attr("dominant-baseline", "middle")
    .attr("fill", aubergine);

图 4.22 SVG 文本元素的 y 属性可设置其基准线在垂直方向的位置,默认位置在文本底边。可通过 dominant-baseline 进行修改,值为 middle 时基准线与文本中心对齐;值为 hanging 时基准线则位于文本顶部。

【图 4.22 SVG 文本元素的 y 属性可设置其基准线在垂直方向的位置,默认位置在文本底边。可通过 dominant-baseline 进行修改,值为 middle 时基准线与文本中心对齐;值为 hanging 时基准线则位于文本顶部。】

接着再给面积图的下边界添加一个文本标签,代表最低温度的变化趋势。具体做法与刚才一样,先添加一个 SVG 文本元素,并指定文本内容为 "Minimum temperature",即最低气温。

至于标签的坐标方位,可以参考最后一个下凹点(downward protuberance),即下边缘倒数第三个数据点。将该位置的数据值传入垂直坐标尺函数,算得其垂直坐标,然后再下移 20px、右移 13px。这些位移量都是通过在页面上不断尝试不同的位置得到的;借助浏览器的检查工具(inspector tool)是处理这类微调操作的绝佳工具。注意,此时文本标签的 dominant-baseline 属性值改为了 hanging,如图 4.22 所示,表示 y 属性值是相对于文本的顶部而言的。

最后,根据以下代码片段,就能再给图表标签新增一条指示线,将面积图的下凹拐点与标签进行关联,进一步明确标签所代表的含义,如图 4.23 所示。同理,可以使用比例尺分别计算指示线的 x1y1x2y2 属性值,最终确定出线段的起点和终点位置:

innerChart
  .append("text")
    .text("Minimum temperature")
    .attr("x", xScale(data[data.length - 3].date) + 13)
    .attr("y", yScale(data[data.length - 3].min_temp_F) + 20)
    .attr("alignment-baseline", "hanging")
    .attr("fill", aubergine);
innerChart
  .append("line")
    .attr("x1", xScale(data[data.length - 3].date))
    .attr("y1", yScale(data[data.length - 3].min_temp_F) + 3)
    .attr("x2", xScale(data[data.length - 3].date) + 10)
    .attr("y2", yScale(data[data.length - 3].min_temp_F) + 20)
    .attr("stroke", aubergine)
    .attr("stroke-width", 2);

同理也可以给面积区的上边缘添加类似的文本标签,用以表示当日最高气温的变化情况。上边缘标签的定位可以参考其倒数第四个数据点的上凸拐点。然后用相同的手法在标签和上凸拐点间绘制一条指示线,如以下代码片段所示:

innerChart
  .append("text")
    .text("Maximum temperature")
    .attr("x", xScale(data[data.length - 4].date) + 13)
    .attr("y", yScale(data[data.length - 4].max_temp_F) - 20)
    .attr("fill", aubergine);
innerChart
  .append("line")
    .attr("x1", xScale(data[data.length - 4].date))
    .attr("y1", yScale(data[data.length - 4].max_temp_F) - 3)
    .attr("x2", xScale(data[data.length - 4].date) + 10)
    .attr("y2", yScale(data[data.length - 4].max_temp_F) - 20)
    .attr("stroke", aubergine)
    .attr("stroke-width", 2);

这样就完成了折线图部分的绘制:

图 4.23 绘制完毕的 2021 年纽约市全年日均气温及其变化趋势效果图

【图 4.23 绘制完毕的 2021 年纽约市全年日均气温及其变化趋势效果图】



另附:专栏文章连载期间 完全免费,后续 不排除 调整为收费专栏。对 D3.js 感兴趣、或者想要从零开始彻底掌握 D3 的朋友们强烈建议及时关注本专栏,一起学习交流,共同进步!

目前译好的其他章节内容如下(可进入专栏查看详情):

  • 第一部分 D3.js 基础知识
    • 第一章 D3.js 简介(已完结)
      • 1.1 何为 D3.js?
      • 1.2 D3 生态系统——入门须知
      • 1.3 数据可视化最佳实践(上)
      • 1.3 数据可视化最佳实践(下)
      • 1.4 本章小结
    • 第二章 DOM 的操作方法(已完结)
      • 2.1 第一个 D3 可视化图表
      • 2.2 环境准备
      • 2.3 用 D3 选中页面元素
      • 2.4 向选择集添加元素
      • 2.5 用 D3 设置与修改元素属性
      • 2.6 用 D3 设置与修改元素样式
      • 2.7 本章小结
    • 第三章 数据的处理(已完结)
      • 3.1 理解数据
      • 3.2 准备数据
      • 3.3 将数据绑定到 DOM 元素
        • 3.3.1 利用数据给 DOM 属性动态赋值
      • 3.4 让数据适应屏幕
        • 3.4.1 比例尺简介(上篇)
        • 3.4.2 线性比例尺(中篇)
          • 3.4.2.1 基于 Mocha 测试 D3 线性比例尺(DIY 实战)
        • 3.4.3 分段比例尺(下篇)
          • 3.4.3.1 使用 Observable 在线绘制 D3 条形图(DIY 实战)
      • 3.5 加注图表标签(上篇)
        • 3.5.1 人物专访:Krisztina Szűcs(下篇)
      • 3.6 本章小结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2235899.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

美国大选——极具典型的可视化案例!GISer学起来

有人说可视化技术有啥意义,不就做个大屏么? 那真的小看了,就如下图这个美国大选来看,这么复杂混乱的信息,可视化技术给你梳理的明明白白的,简单、直观、形象、便于记忆。 让用户能够从繁杂信息中快速抓到重…

使用PyQt5设计一个简易计算器

目录 设计UI图 代码 结果展示 设计UI图 代码 from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import QFileDialog, QMainWindow, QMessageBox from untitled import Ui_MainWindow import sysclass…

数据结构-数组(稀疏矩阵转置)和广义表

目录 1、数组定义 1)数组存储地址计算示例①行优先②列优先 2)稀疏矩阵的转置三元组顺序表结构定义 ①普通矩阵转置②三元组顺序表转置稀疏矩阵③稀疏矩阵的快速转置 3)十字链表结构定义 2、广义表定义 1)基本操作①GetHead②GetT…

cooladmin使用整理

1、后端关键字自动生成没有代码段提示,原因是拉取的项目代码中没有.vscode文件夹,复制一套至项目src同级即可 2、前端快速创建,在Entity完成后就去快速创建中选数据结构,这时没有对应的内容,数据结构是和controller层a…

Java 网络编程(一)—— UDP数据报套接字编程

概念 在网络编程中主要的对象有两个:客户端和服务器。客户端是提供请求的,归用户使用,发送的请求会被服务器接收,服务器根据请求做出响应,然后再将响应的数据包返回给客户端。 作为程序员,我们主要关心应…

Jmeter命令监控CPU等指标

JMeter 命令行执行脚本得到的报告中,是没有CPU、内存使用率等监控数据的,但是可以使用JMeter插件帮忙。 一、下载jmeter-plugins-manager.jar 下载后将文件放到jmeter安装包lib/ext目录下。打开Jmeter》菜单栏》选项》Plugins Manager 二、安装PerfMon…

ES + SkyWalking + Spring Boot:日志分析与服务监控(三)

目录 一、搭建SkyWalking 1.1 版本选择 1.2 下载安装 1.3 配置启动 1.4 SkyWalking UI介绍 二、Springboot项目使用 2.1 Agent下载 2.2 Agent配置skywalking oap地址 2.3 IDEA配置Agent地址 2.4 生成的ES索引介绍 三、在kibana上查看日志 四、问题和解决 3.1 日志…

如何快速搭建一个spring boot项目

一、准备工作 1.1 安装JDK:确保计算机上已安装Java Development Kit (JDK) 8或更高版本、并配置了环境变量 1.2 安装Maven:下载并安装Maven构建工具,这是Spring Boot官方推荐的构建工具。 1.3 安装代码编辑器:这里推荐使用Inte…

spring-第十三章 AOP

spring 文章目录 spring前言1.AOP介绍2.AOP七大术语3.切点表达式4.使用spring的AOP4.1概述4.2准备工作4.3基于注解方式使用AOP4.3.1准备目标类和目标方法4.3.2编写配置类4.3.3编写通知类4.3.4编写测试类4.3.5通知类型4.3.6切面的先后顺序4.3.7PointCut注解通用切点 4.4基于XML方…

jmeter常用配置元件介绍总结之安装插件

系列文章目录 1.windows、linux安装jmeter及设置中文显示 2.jmeter常用配置元件介绍总结之安装插件 3.jmeter常用配置元件介绍总结之取样器 jmeter常用配置元件介绍总结之安装插件 1.下载插件2.安装插件管理包3.不用插件管理包,直接官网插件下载安装 1.下载插件 jm…

MySQL 多数据库备份与恢复,包括查询,函数,SP

一、备份语句: mysqldump 可以用来导出单个数据库、多个数据库,甚至所有数据库的数据。以下是导出多个数据库到指定文件位置的语法和具体案例。 基本语法 mysqldump -u [username] -p[password] --databases [db1] [db2] ... > [file_path] -u: …

contenteditable实现需要一个像文本域一样的可编辑框

我这里是因为左上和右下有一个固定的模板,所有用textarea有点不方便,查了下还有一个方法可以解决就是在需要编辑的元素上加上 :contenteditable"true" 完整代码如下,因为这个弹窗是两用的,所以用messageType做了一下判…

linux 安装anaconda3

1.下载 使用repo镜像网址下载对应安装包 右击获取下载地址,使用终端下载 wget https://repo.anaconda.com/archive/Anaconda3-2024.02-1-Linux-x86_64.sh2.安装 使用以下命令可直接指定位置 bash Anaconda3-2024.02-1-Linux-x86_64.sh -b -p /home/anaconda3也…

如何选择适合的AWS EC2实例类型

在云计算的世界中,Amazon Web Services(AWS)提供了丰富的服务,其中Elastic Compute Cloud(EC2)是最受欢迎的服务之一。选择合适的EC2实例类型对于确保应用程序的性能和成本效益至关重要。我们九河云通过本文…

(蓝桥杯C/C++)——基础算法(下)

目录 一、时空复杂度 1.时间复杂度 2.空间复杂度 3.分析技巧 4.代码示例 二、递归 1.递归的介绍 2.递归如何实现 3.递归和循环的比较 4.代码示例 三、差分 1.差分的原理和特点 2.差分的实现 3.例题讲解 四、枚举 1.枚举算法介绍 2.解空间的类型 3. 循环枚举解…

7.5 inch电力线载波通信技术

7.5寸电子桌牌 产品型号 PE75R_D_W 尺寸 176.2*137.15*80mm 屏幕尺寸 7.5 inch 显示区域(mm) 163.2(H) * 97.92(V) 分辨率 800*480 显示技术 电子墨水屏双面显示 显示颜色 黑/白/红 外观颜色 银色 工作温度 0-40℃ 视角 180 支持内容格式 文本/图片/二维码…

Linux下的ADC

ADC ADC简介 ADC是 Analog Digital Converter 的缩写,翻译过来为模数转换器,ADC可以将模拟值转换成数字值。模拟值是什么呢?比如我们日常生活中的温度,速度,湿度等等都是模拟值。所以如果我们想测量这些模拟值的值是多少&#x…

星空天文 2.0.1| 完全免费的观星软件,无注册登录,天文爱好者必备。

星空天文是一款完全免费且功能强大的观星软件,适用于安卓平台。无需注册登录即可使用,界面设计精美且操作简单。软件支持AR实景模式,可以将实景与星空结合,增强观星体验。用户可以设定任意日期和时间来观察不同时段的天空&#xf…

书生大模型实战营第四期-入门岛-1. Linux前置基础

入门岛-Linux前置基础 书生大模型实战营-第四期-Linux前置基础: 任务:https://github.com/InternLM/Tutorial/blob/camp4/docs/L0/linux/task.md 文档:https://github.com/InternLM/Tutorial/tree/camp4/docs/L0/linux 任务描述完成所需时…

JavaEE初阶--servlet篇(三)HttpServlet/response/request对应方法使用

文章目录 1.总括说明2.httpservlet父类2.1方法介绍2.2dopost方法的演示2.3doput方法的演示 3.HttpServletRequest类3.1方法说明3.2方法使用演示3.3getparameter方法使用3.4使用form表单的方式3.5jackson获取参数 4.HttpResponse类4.1设置状态码4.2自动进行刷新4.3重定向跳转4.3…