【D3.js in Action 3 精译_029】3.5 给 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 本章小结
文章目录
- 3.5 加注图表标签 Adding labels to a chart
《D3.js in Action》全新第三版封面
译者按
终于来到了本章代码量最为密集的最后一个小节了。作者真的是事无巨细,真正把大家当成零基础的数据可视化爱好者,竟然细致到 JS 的注释是怎么加的也要说明一下……不过这也算是本书的一大魅力吧。也多亏了这份执着和对细节把控的精益求精,新版才出现了这么多直观精美的配图。由于篇幅太长,本节最后的人物专访就放到下篇,本文为上篇,主要介绍条形图的最终实现。一起跟随作者实战起来吧!
3.5 加注图表标签 Adding labels to a chart
示例条形图就快做完了,但目前还不知道哪个矩形条对应哪个技术,也不知道矩形条的长度代表哪些票数。这些问题只要给图表加两组标签(label)就能解决:第一组列出技术名称,放在左侧;第二组则显示各矩形条对应的 count
票数值,分别放到各矩形条的最右端。
在基于 SVG 的可视化项目中,标签的制作可以通过 SVG 文本元素(text
)实现:先将各矩形条分别与两个文本元素相结合,然后将其一同嵌入 SVG 的某个分组元素(group)内。根据第 1 章 1.2.2 节介绍的 SVG 分组元素的知识,这里可以用分组元素将多个子元素视为一个整体进行平移,以便于后续将绑定数据传递给它的后代元素。
接下来需要稍微重构一下代码。首先注释掉与矩形条元素相关的所有代码行,留待后用。在 JavaScript 中,单行注释以双斜杠(//
)开头,而多行注释则以 /*
开始、以 */
结束。
再回到处理数据绑定的那部分代码。此时应该让数据绑定到 SVG 的分组元素(g
)上,而不是之前的矩形条上。然后将该选择集赋给一个常量 barAndLabel
:
const barAndLabel = svg.selectAll("g").data(data).join("g");
为了让矩形条与标签元素同步移动,可以利用 transform
属性让各分组元素做垂直平移(vertical translation)。transform
变换属性(attribute)上的 translate
平移属性(property)接受两个参数:水平平移量,设为 0
;以及垂直平移量,这里设为各矩形条的垂直坐标,由之前定义好的分段比例尺函数 yScale
计算得到:
const barAndLabel = svg.selectAll("g").data(data).join("g").attr("transform", d => `translate(0, ${yScale(d.technology)})`);
虽然 SVG 的分组元素没有可视化的图形表示,也不以占据某个有界空间的形式存在,但我们仍然可以将其想象成能够封装所有子元素的内容盒。借助 transform
属性,这些分组元素实现了垂直方向的均匀排布,如图 3.30 所示。各矩形条及其标签元素将相对于它们所在的父级分组元素进行定位:
【图 3.30 封装了矩形条与标签等后代元素的分组元素在 SVG 容器内的定位情况】
一切就绪后,就可以重新添加矩形条了。如下所示,调用选择集 barAndLabel
,并将矩形元素添加进去:
const barAndLabel = svg.selectAll("g").data(data).join("g").attr("transform", d => `translate(0, ${yScale(d.technology)})`);barAndLabel.append("rect");
由于该选择集包含多个分组元素,D3 会分别给每个分组添加一个矩形元素。保存项目并使用检查工具进行查看,确认它们都已经添加到了 DOM 结构中,如图 3.31 所示:
【图 3.31 添加到每个分组元素里的矩形元素示意图】
现在可以取消刚才的注释,把它们用到新加的 rect
元素上。D3 数据绑定的一大好处,是绑定的数据会传递给分组内的所有后代元素。因此矩形条依然可以像之前那样拿到数据,唯一的区别是,矩形的 y
属性要设为 0
,因为分组元素已经带着它完成了垂直平移:
barAndLabel.append("rect").attr("width", d => xScale(d.count)).attr("height", yScale.bandwidth()).attr("x", 100).attr("y", 0) // 矩形不用再做垂直平移,其定位相对于其父级分组元素的位置.attr("fill", d => d.technology === "D3.js" ? "yellowgreen":"skyblue");
这时就能看到各个矩形条了,效果和之前完全相同(详见图 3.28)。
译注
为方便查看新的条形图效果,我这里直接附上图 3.28:
接下来能可以正式添加标签了!再次调用选择集 barAndLabel
,将 SVG 文本元素分别添加进去。由于各标签需要展示每个对应的技术名称,因此需要再链式调用一次 text()
方法。该方法只接受一个参数:文本元素要显示的文本内容。本例则需要根据每个绑定的数据项动态设置对应的文本内容:
barAndLabel.append("text").text(d => d.technology);
内容设置好后,再用 x
和 y
属性给每个标签定位。先来看水平方向,各标签末端要同矩形条的起始位置对齐。矩形条从 100px
开始,于是可以把文本元素放在大约 96px
的位置,与矩形条保持 4px
的间距。然后令其 text-anchor
属性(attribute)的值为 end
,实现标签右对齐。这样 x
属性值就代表了各标签的末端位置,如图 3.32 所示:
【图 3.32 各技术标签的定位计算示意图】
再来看垂直方向。由于各标签的定位相对于所在的父级分组元素,只需稍向下平移即可与矩形条居中对齐。注意,SVG 文本元素的垂直定位是相对于它的基线(baseline)而言的。经反复试错与微调,最终给定的 y
值为 12
像素。位置的微调可以在浏览器的检查工具(inspector)里快速实现:
barAndLabel.append("text").text(d => d.technology).attr("x", 96).attr("y", 12).attr("text-anchor", "end");
最后,在根据各自的喜好,调用 style()
方法设置文本标签的 font-family
与 font-size
属性,分别确定字体及字号。本例使用的字体为 11 号无衬线字体,如图 3.33 所示:
barAndLabel.append("text").text(d => d.technology).attr("x", 96).attr("y", 12).attr("text-anchor", "end").style("font-family", "sans-serif").style("font-size", "11px");
【图 3.33 加注了技术标签的条形图效果】
接着,再在矩形条的另一端添加一组标签,显示该技术在问卷调查中的得票数,做法与添加技术名称标签类似。先调用 barAndLabel
选择集常量,然后在每个分组元素内添加一个文本元素,再通过链式调用的 text()
方法给每项技术指定相应的 count
值:
barAndLabel.append("text").text(d => d.count)
由于计数标签位于矩形条的末端,而矩形条的水平坐标可以通过 xScale
函数计算得到。再加上矩形条两边的间距(左边为预留的 100px
,后边同样保持 4px
间隔),这样技术标签的 x
属性就能确定了。垂直方向,也令其下移 12px
,如图 3.34 所示:
barAndLabel.append("text").text(d => d.count).attr("x", d => 100 + xScale(d.count) + 4).attr("y", 12)
【图 3.34 计数标签的定位计算示意图】
接着,再给技术标签设置 font-family
和 font-size
属性。注意,计数标签的字号为 9px
,比技术名称的字号 11px
小一些,目的是为了让两组标签保持视觉上的层次感。较大的标签更吸引眼球,也便于让观众理解得票数是次于技术名称的样式设计。
barAndLabel.append("text").text(d => d.count).attr("x", d => 100 + xScale(d.count) + 4).attr("y", 12).style("font-family", "sans-serif").style("font-size", "9px");
最后一步,再在条形图左侧绘制一条垂直线,作为垂直方向的轴线。在以下代码片段中,我们将这条线段添加到 SVG 容器内。该线段的起点坐标 (x1, y1)
为 (100, 0)
,即 SVG 容器的顶部;终点坐标 (x2, y2)
则位于 (100, 700)
,即容器底部。再指定好线条的描边色,让轴线显示出来:
svg.append("line").attr("x1", 100).attr("y1", 0).attr("x2", 100).attr("y2", 700).attr("stroke", "black");
如果再把 SVG 容器的边框去掉,最终条形图的效果就应该如图 3.35 所示。该项目也托管到了 GitHub ,可以访问 http://mng.bz/mjor 进行访问。值得一提的是,本章给标签预留间距的做法并不常用。业内更通用的实现方案是遵守 D3 外边距约定(D3 margin convention),具体内容将在下一章进行介绍,后续章节也将按这种写法来进行讲解。
【图 3.35 最终实现的在线版 D3 条形图效果,详见:http://mng.bz/mjor】
恭喜您完成了本章的学习——知识点着实很密集!如果还没有掌握讲过的所有概念,也不必过于担心。后续章节还将继续提到这些概念,相信很快就能融会贯通 。
译注
实测时发现,左边标签的字号取
11px
时部分标签显示不全,调整为10px
正常。相应的得票数标签也最好该小些,设为8px
比较合适(相关源码已同步上传到 CSDN 下载资源):
【补图 1 本地实测并重新调整字号后的 D3 条形图效果】
相关文章:

【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第一部分 D3.js 基础知识 第一章 D3.js 简介(已完结) 1.1 何为 D3.js?1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践(上)1.3 数据可…...

用python做一个简单的画板
一,画板的介绍 画板(Paint Board)是一个提供用户绘图、涂鸦和创作的平台。现代数字画板通常是由软件程序实现的,具有多种功能。以下是画板的一些主要特征和功能: 1. 基本绘图工具 画笔和铅笔:用户可以选…...

根据传入的文件流链接实现前端下载
后端传入一个下载的url,实现点击按钮,下载文件。 方式一: 通过window.open(“URL”, _blank) 方式 PS:会打开一个新的页面 import React from react;const DownloadButton () > {// window.open("URL", "_…...

大数据新视界 --大数据大厂之大数据环境下的零信任安全架构:构建可靠防护体系
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

基于springboot的高校招生系统(含源码+sql+视频导入教程+文档+PPT)
👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的高校招生系统1拥有两种角色:管理员和用户 管理员:学生管理、专业管理、报名管理、录取通知管理、招生公告管理等 用户:登录注册、报…...

【C++设计模式】行为型模式:观察者模式
文章目录 行为型模式:观察者模式 行为型模式:观察者模式 观察者模式定义了一种一对多的依赖关系:它让一个主题(被观察者)对象关联多个观察者对象,并且当主题对象的状态发生变化时,它会主动通知…...

本篇5K,立志最细,FreeRtos中的信号量Semaphore教程详解!!!
前言:本篇教程,参考韦东山,开发文档,连接放在最后 目录 Semaphore基本概念 二值信号量(Binary Semaphore) 计数信号量(Couting Semaphore) 互斥信号量(Mutex&…...

【Postman】接口测试工具使用
干就完啦 Postman发送get请求案例1: Postman发送post请求案例2 Postman发送其他请求Postman测试实战 学习目标:能够使用Postman发送get/post/put/delete请求并获取响应结果 Postman发送get请求 首先postman是一款接口调试工具,支持win&…...

springboot 整合 rabbitMQ(1)
目录 一、MQ概述 二、MQ的优势和劣势 三、常见的MQ产品 RabbitMQ使用步骤 第一步:确保rabbitmq启动并且可以访问15672 第二步:导入依赖 第三步:配置 auto自动确认 manual手工确认(推荐使用!可以防止消息丢失&a…...

Appium Device Farm安装教程
环境要求:Appium version ≥ 2.4.X 安装appium npm install -g appium2.11.3 如果安装提示如下问题 npm error code EEXIST npm error syscall rename npm error path /Users/wan/.npm/_cacache/tmp/d5787519 npm error dest /Users/wan/.npm/_cacache/content-…...

异常、基类
异常 人生和世界总是充满着意外,争议、冲突和战争似乎是人类必然经历的过程。程序执行也有不满的时候。 不同编程语言的异常 Ada/Modula-3是早期引入异常处理的语言。 C语言没有标准意义的异常,使用goto或setjmp模拟错误或异常发生时的处理流程。 C/Java…...

VScode 自定义代码配色方案
vscode是一款高度自定义配置的编辑器, 我们来看看如何使用它自定义配色吧 首先自定义代码配色是什么呢? 看看我的代码界面 简而言之, 就是给你的代码的不同语义(类名, 函数名, 关键字, 变量)等设置不同的颜色, 使得代码的可读性变强. 其实很多主题已经给出了定制好的配色方案…...

MuMu模拟器12 KitsumeMask安装教程
这里是引用"> 在MuMu模拟器上安装KitsumeMask的时候遇到安装失败的情况。 一、下载APK安装包 如果你没有apk安装包可以通过下面的百度网盘进行下载 通过网盘分享的文件:KitsumeMask 链接: https://pan.baidu.com/s/1yeq3I6BsUD7J6uI-bnk-Vw?pwd=7n3v 提取码: 7n3v 二…...

Perforce静态分析工具2024.2新增功能:Helix QAC全新CI/CD集成支持、Klocwork分析引擎改进和安全增强
Perforce Helix QAC和Klocwork的最新版本对静态分析工具进行了重大改进,通过尽早修复错误、降低开发成本和加快发布速度,使开发团队实现左移。 本文中,我们将概述2024.2版本的新特性和新功能。 CI/CD和左移以实现持续合规性 现代软件开发实…...

太阳能电池特性及其应用
中南民族大学-通信工程2024-大学物理下实验 目录 代码实现结果显示 🛠工具使用 MarsCode(插件,集成在PyCharm); python编程(豆包AI智能体) 💻编程改进 此处是用「Matplotlib」来作图…...

日语学习零基础生活日语口语柯桥外语学校|股票用日语怎么说?
在日语中,“股票”可以说: • 株(かぶ) 这是最常用的表达方式,直接表示“股票”。 例如: 株を買う - 买股票 株を売る - 卖股票 • 株式(かぶしき) 这个词也是“股票”的意…...

第2关:寻找一个序列中的第K小的元素(即第k小元问题)
[TOC]寻找一个序列中的第K小的元素(即第k小元问题) 对于给定的含有n(n<100)元素的无序序列,求这个序列中第k(1≤k≤n)小的元素。 任务描述 本关任务:编写一个能计算数组中的第k小的元素的小程序。 相关…...

docker 搭建 vue3 + vite
vue3发布了,今天就分享一下我使用docker 搭建 vue3 vite 开发环境。至于为什么使用docker搭建,因为多版本可以快速切换,和本地环境避免冲突。好了话不多说我们开始吧。 1. 准备资料 Docker Desktop wsl2 ubuntu 下载地址 : https://www.docker.…...

【网易云音乐】--源代码分享
最近写了一个网易云音乐的音乐实现部分,是通过JavaScript和jQuery实现的,具体效果大家可以参照下面的视频 源代码分享 - git地址: 网易云音乐源代码 下面将着重讲解一下音乐实现部分 视频有点模糊,不好意思,在b站上添加视频的时候…...

股市大涨下的会展业创新者
近期,股市涨势强劲有力,各大指数普遍上扬,市场活力空前。与此同时,伴随全球经济逐步复苏及会展行业不断发展,上市展览公司机遇与挑战并存。国内外市场需求持续增长拓展了广阔发展空间,但同时行业竞争愈发激…...

工具篇-完整的 Git 项目管理工具教程(在命令框中使用 Git、在 IDEA 中使用 Git)
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 Git 概述 2.0 Git 的安装和配置 3.0 获取本地仓库 3.1 基础操作指令 3.2 分支 4.0 Git 远程仓库 4.1 创建远程仓库 4.2 配置 SSH 公钥 4.3 操作远程仓库 5.0 使用…...

关于Amazon Linux 2023的版本及包管理器
在亚马逊上创建EC2实例时,会看到有一个Amazon Linux镜像。 那这个镜像与其他Linux有什么关系和区别呢? 网站是介绍:Amazon Linux 2023 是基于 Linux 的现代化通用操作系统,提供 5 年的长期支持。它针对 AWS 进行了优化࿰…...

Java面向对象编程--高级
目录 一、static关键字 1.1 静态变量 1.2 静态内存解析 1.3 static的应用与练习 二、单例设计模式 2.1 单例模式 2.2 如何实现单例模式 三、代码块 3.1 详解 3.2 练习,测试 四、final关键字 五、抽象类与抽象方法 5.1 abstract 5.2 练习 六、接口 6.…...

Vert.x,Web - 静态资源/模板
静态资源 Vert.x-Web带有开箱即用的处理器(StaticHandler),用于处理静态Web资源(.html, .css, .js, …), 因此可以非常轻松地编写静态Web服务器。 默认静态文件目录为类路径下的webroot目录,对于maven的项目,按规范放在src/main/…...

OpenAI今天Open了一下:开源多智能体框架Swarm
来源 | 机器之心 毫无疑问,多智能体肯定是 OpenAI 未来重要的研究方向之一,前些天 OpenAI 著名研究科学家 Noam Brown还在 X 上为 OpenAI 正在组建的一个新的多智能体研究团队招募机器学习工程师。 就在几个小时前,这个或许还没有组建完成的新…...

车辆重识别(2021NIPS无分类器扩散指南)论文阅读2024/10/08
[1] CLASSIFIER-FREE DIFFUSION GUIDANCE(无分类器扩散指导) (NIPS 2021) 作者:Jonathan Ho & Tim Salimans 单位:Google Research, Brain team(谷歌团队) 摘要: 分类器指导是最近引入的一…...

JavaSE——认识异常
1.概念 在生活中,人有时会生病,在程序中也是一样,程序猿是一帮办事严谨、追求完美的高科技人才。在日常开发中,绞尽脑汁将代码写的尽善尽美,在程序运行过程中,难免会出现一些奇奇怪怪的问题。有时通过代码很…...

嵌入式数据结构中顺序栈用法
第一:嵌入式C语言中栈特点 栈是限制在一端进行插入操作和删除操作的线性表(俗称堆栈),允许进行操作的一端称为“栈顶”,另一固定端称为“栈底”,当栈中没有元素时称为“空栈”。特点 :后进先出(LIFO)。...

PE结构之绑定导入表
打印绑定导入表 //打印 绑定导入表 BOOL PrintBoundImport(__in char* m_fileName) {char* Filebuffer NULL;if (!GetFileBuffer(m_fileName, &Filebuffer)) return FALSE;PIMAGE_DOS_HEADER LPdosHeader NULL;PIMAGE_NT_HEADERS LPntHeader NULL;LPdosHeader (PIMAGE…...

【python学习】1-2 配置python系统环境变量
1.点击“我的电脑”右键,点击属性,点击“高级系统设置”,再点击环境变量。 2.选择“系统变量”中的Path后,点击编辑。 3.点击新建,添加如图两个路径,即是python安装的路径位置后,点击确定。...