【D3.js in Action 3 精译_043】5.1 饼图和环形图的创建(三):圆弧的绘制

当前内容所在位置:

  • 第五章 饼图布局与堆叠布局 ✔️
    • 5.1 饼图和环形图的创建 ✔️
      • 5.1.1 准备阶段(一)
      • 5.1.2 饼图布局生成器(二)
      • 5.1.3 圆弧的绘制(三) ✔️
      • 5.1.4 数据标签的添加(四)

文章目录

    • 5.1.3 圆弧的绘制 Drawing the arcs
      • 5.1.3.1 D3 色阶的用法 Using a color scale

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

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

【译者按】有了第四章绘制 D3 圆弧的基础后,再来实现本章的环形图就轻松多了,只是在一些细节处理上加入了新的知识点,比如 D3 色阶的配置。一起来看看吧。

5.1.3 圆弧的绘制 Drawing the arcs

有了带注解的数据集,下一步就可以绘制饼图的弧线了。接下来您会发现本节演示内容与上一章中弧线的绘制手法大同小异,因此本节将不再展开相关细节进行演示。如需了解相关细节,详见本书第 4 章内容。

在代码清单 5.4 中,我们先调用 d3.arc() 方法来初始化一个圆弧生成器,然后使用各种访问器函数(accessor functions)来设置环形图的内外半径、环形片段之间的间隙(即填充角)以及圆弧轨迹的圆角半径。如果内圆半径为 0,绘制的就是一个饼图;如若大于 0,则得到一个环形图(donut chart)。

本例与第 4 章采用的绘制策略相比,唯一的区别在于本例中可以在声明圆弧生成器时通过 startAngle()endAngle() 这两个访问器函数配置环形片段的初始角与终止角。而这些值都提前在数据集中算好了,直接使用 d.startAngled.endAngle 就能访问到。

最后,要让圆弧出现在屏幕上,还需要利用 D3 的数据绑定机制,为每个环形片段生成一个 SVG 路径元素 path。如以下代码清单 5.4 所示,我们给每段圆弧都指定了一个具体的类名(即 arc-${year}),然后通过它来选中元素并绑定数据。因为是在 For 循环中创建的环形图,这样一来可以防止 D3 在生成新的环形图时覆盖掉之前的图形。代码的最后,用到了圆弧生成器函数来计算各 path 元素的 d 属性的取值。

代码清单 5.4 生成并绘制圆弧的示例代码(详见 donut-charts.js

const arcGenerator = d3.arc().startAngle(d => d.startAngle) // 配置访问器函数 startAngle() 和 endAngle(),并在带注解的数据集中指定对应取值的 key 值.endAngle(d => d.endAngle)     .innerRadius(60).outerRadius(100).padAngle(0.02).cornerRadius(3);const arcs = donutContainer.selectAll(`.arc-${year}`) // 利用数据绑定机制为每个片段生成一个 path 元素.data(annotatedData)          .join("path")                 .attr("class", `arc-${year}`).attr("d", arcGenerator); // 调用 arcGenerator() 函数来配置 path 中的 d 属性

5.1.3.1 D3 色阶的用法 Using a color scale

保存项目并在浏览器中查看示例页,会看到绘制的环形图虽然形状有了,但圆弧全是黑色的。原因很简单:SVG 元素的默认填充色就是黑色。为了提高环形图的可读性,接下来将为每种音乐格式配置不同的颜色。

一个操作简单又方便复用的解决方案是给每段圆弧都配置好特定的颜色,即声明一组 色阶(color scale);色阶通常可以由 D3 的 d3.scaleOrdinal() 方法创建。D3 的 序数比例尺(ordinal scales) 能够将某个离散型的定义域映射到同样为离散型的某个值域上。在本例中,定义域即不同音乐格式组成的数组,而值域则是某个与格式一一对应的颜色值数组。

找到 scales.js 文件,并在里面声明一个 D3 序数比例尺,然后赋给一个常量 colorScale。然后提取 formatsInfo 数组中的格式 ID 字段,作为比例尺的定义域;对于颜色值也做类似处理。您也可以根据自己的喜好进行相应调整。本章将沿用该色阶来设置示例项目中的所有图表。

const colorScale = d3.scaleOrdinal();const defineScales = (data) => {colorScale.domain(formatsInfo.map(f => f.id)).range(formatsInfo.map(f => f.color));};

然后再回到 donut-charts.js 文件,并通过指定 path 元素的 fill 属性(attribute)来配置每个环形片段的具体颜色。只需按照下列格式调用上面声明的色阶函数即可:

const arcs = donutContainer.selectAll(`.arc-${year}`).data(annotatedData)          .join("path")                 .attr("class", `arc-${year}`).attr("d", arcGenerator).attr("fill", d => colorScale(d.data.format));

保存项目并再次查看浏览器中的页面效果——看上去还不错!如图 5.7 所示,每段圆弧已按照从大到小的顺序排列好了,这样可以进一步提高图表的可读性。从图中可以清晰地看到在 1975 年、1995 年以及 2013 年三年中,每年的销售额在音乐格式方面发生的结构性转变;每年的主流音乐格式都各不相同。

图 5.7 分别代表 1975 年、1995 年以及 2013 年的环形图效果对比

【图 5.7 分别代表 1975 年、1995 年以及 2013 年的环形图效果对比】

译注
本章示例较前面章节都更为复杂,为了便于演示,作者都省略了完整的实现代码。学习时一定记得在本地搭建好服务器环境跟着文中的进度落地实操。以下为我自己的本地实现代码:

// donut-charts.js:
const drawDonutCharts = (data) => {const svg = d3.select("#donut").append("svg").attr("viewBox", `0 0 ${width} ${height}`); // 环形图总容器的声明const donutContainers = svg.append("g").attr("transform", `translate(${margin.left}, ${margin.top})`);// 定义指定的年份数组const years = [1975, 1995, 2013];// 从数据集中筛除年份列,仅保留音乐格式列const formats = data.columns.filter((format) => format !== "year");years.map((year) => {// 添加具体年份的环形图容器(共三个)const donutContainer = donutContainers.append("g").attr("transform", `translate(${xScale(year)}, ${innerHeight/2})`);const yearData = data.filter((d) => d.year === year)[0];const formattedData = formats.map((format) => ({format,sales: yearData[format],}));// 定义饼图布局函数const pieGenerator = d3.pie().value((d) => d.sales);// 获取带注解的数据集const annotatedData = pieGenerator(formattedData);// 定义圆弧生成器const arcGenerator = d3.arc().startAngle(d => d.startAngle).endAngle(d => d.endAngle)     .innerRadius(60).outerRadius(100).padAngle(0.02).cornerRadius(3);// 绘制当前年份对应的环形图const arcs = donutContainer.selectAll(`.arc-${year}`).data(annotatedData)          .join("path")                 .attr("class", `arc-${year}`).attr("d", arcGenerator).attr("fill", d => colorScale(d.data.format)); // 应用 D3 色阶});        
};// scales.js:
// Initialize the scales here
const xScale = d3.scaleBand(); // 声明分段比例尺
const colorScale = d3.scaleOrdinal();const defineScales = (data) => {// Define the scales domain and range herexScale.domain(data.map(d => d.year)).range([0, innerWidth]);colorScale.domain(formatsInfo.map(f => f.id)).range(formatsInfo.map(f => f.color));
};

最终实测页面效果:

补图:实测本节绘制环形图后的页面最终效果

【补图:实测本节绘制环形图后的页面最终效果】

(第三部分完)



另附:专栏文章连载期间 完全免费,后续 不排除 调整为收费专栏。对 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 本章小结
    • 第四章 直线、曲线与弧线的绘制
      • 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.4.1 D3 中的极坐标系
        • 4.4.2 圆弧生成器的使用
        • 4.4.3 圆弧形心的计算
        • 4.4.4 人物专访:Francis Gagnon、Patricia Angkiriwang 和 Olivia Gélinas
      • 4.5 本章小结

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

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

相关文章

【C++】LeetCode:LCR 022. 环形链表 II

题目: 给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环,则返回 null。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位…

Windows环境中Python脚本开机自启动及其监控自启动

1 开机自启动 Windows 10/Windows Server 201X具有一个名为“启动”的已知文件夹,系统每次启动开始自动运行应用程序、快捷方式和脚本时都会检查该文件夹,而无需额外配置。 要在Windows启动时运行脚本,先使用WindowsR快捷键打开“运行”对话…

【QNX+Android虚拟化方案】132 - QNX 系统内存、CPU负载监控

【QNX+Android虚拟化方案】132 - QNX 系统内存、CPU负载监控 1. 获取 showmem 信息2. 获取 thermal adc sensor 信息3. 获取 CPU Load负载信息4. 获取 CPU Freq 频率信息5. 获取 系统开机时间 uptime基于原生纯净代码,自学总结 纯技术分享,不会也不敢涉项目、不泄密、不传播代…

基于JavaSwing的贪吃蛇项目(最新项目)

Java贪吃蛇游戏 目录 文章目录 Java贪吃蛇游戏目录第一章 项目概述1.1 设计背景1.2 设计目的1.3 开发环境 第二章 需求分析2.1 功能需求2.1.1 基础功能2.1.2 扩展功能 2.2 性能需求2.3 用户体验需求 第三章 概要设计3.1 系统架构3.1.1 总体架构3.1.2 类设计 3.2 核心算法设计3…

SpringBoot 赋能:精铸超稳会员制医疗预约系统,夯实就医数据根基

1绪论 1.1开发背景 传统的管理方式都在使用手工记录的方式进行记录,这种方式耗时,而且对于信息量比较大的情况想要快速查找某一信息非常慢,对于会员制医疗预约服务信息的统计获取比较繁琐,随着网络技术的发展,采用电脑…

golang 协程泄漏、协程退出时机、main函数

父协程中生成子协程 问题:如果在一个父goroutine中生成了子goroutine,请问如果父goroutine先执行完毕,那么子协程会自动退出吗? 答案是:不会 先给出结论: 主协程执行完毕后,子协程会继续执行&a…

基于FPGA的智能电子密码指纹锁(开源全免)

基于FPGA的智能电子密码指纹锁 一、功能描述硬件资源需求 二、整体框架知识准备AS608指纹模块4*4数字键盘模块 三、Verilog代码实现以及仿真验证1.AS608_data模块2.check_hand模块3.four_four_key模块4.check_mima模块5.change_mima模块6.seg_ctrl模块7.uart_top模块8.key_debo…

动态计算加载图片

学习啦 别名路径:①npm install path --save-dev②配置 // vite.config,js import { defineConfig } from vite import vue from vitejs/plugin-vueimport { viteStaticCopy } from vite-plugin-static-copy import path from path export default defineConfig({re…

精确的单向延迟测量:使用普通硬件和软件

论文标题:Precise One-way Delay Measurement with Common Hardware and Software(精确的单向延迟测量:使用普通硬件和软件) 作者信息:Maciej Muehleisen 和 Mazen Abdel Latif,来自Ericsson Research Eri…

基于Java+Swing+Mysql的网络聊天室

博主介绍: 大家好,本人精通Java、Python、C#、C、C编程语言,同时也熟练掌握微信小程序、Php和Android等技术,能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验,能够为学生提供各类…

Linux-音频应用编程

ALPHA I.MX6U 开发板支持音频,板上搭载了音频编解码芯片 WM8960,支持播放以及录音功能!本章我们来学习 Linux 下的音频应用编程,音频应用编程相比于前面几个章节所介绍的内容、其难度有所上升,但是笔者仅向大家介绍 Li…

vue3 项目搭建-9-通过 router 在跳转页面时传参

第一步&#xff0c;在跳转链接处挂载方法&#xff0c;将要传输的数据传入&#xff1a; <a href"#" click.prevent"goToArticle(obj.id)" class"click"><h1>{{obj.title}}</h1><p>作者&#xff1a;{{obj.author}}</p&…

【RBF SBN READ】hadoop社区基于RBF的SBN READ请求流转

读写分离功能的背景及架构 当前联邦生产集群的各个子集群只有Active NameNode在工作,当读写任务变得繁忙的时候,只有一个Active负责处理的话,此时集群的响应和处理能力业务侧感知会明显下降,为此,我们将引入Observer架构,实现读写功能的分离,使得Active只负责写请求,而…

利用R包QstFstComp包进行Qst-Fst分析

1.Qst-Fst分析 安装和加载QstFstComp包 首先&#xff0c;你需要安装devtools包&#xff0c;如果尚未安装&#xff0c;可以使用以下命令安装&#xff1a; install.packages("devtools") 2. 然后&#xff0c;使用devtools安装QstFstComp包&#xff1a;R library(de…

视频自学笔记

一、视频技术基本框架 二、视频信号分类 2.1信号形式 2.1.1模拟视频 模拟视频是指由连续的模拟信号组成的视频图像&#xff0c;以前所接触的电影、电视都是模拟信号&#xff0c;之所以将它们称为模拟信号&#xff0c;是因为它们模拟了表示声音、图像信息的物理量。摄像机是获…

操作系统——大容量存储结构

笔记内容及图片整理自XJTUSE “操作系统” 课程ppt&#xff0c;仅供学习交流使用&#xff0c;谢谢。 大容量存储结构概述 磁盘 磁盘为现代计算机系统提供大量外存。每个盘片为平的圆状&#xff08;类似CD&#xff09;&#xff0c;普通盘片直径为4.5~9.0厘米。盘片的两面都涂着…

Python 正则表达式常用特殊字符及其含义

以下是 Python 正则表达式常用特殊字符及其含义 的全面整理&#xff0c;涵盖了常见和重要的正则符号&#xff0c;以及它们的示例&#xff0c;适合用来写博客或学习使用&#xff1a; Python 正则表达式常用特殊字符及其含义 1. . (点号) 含义&#xff1a;匹配除换行符 \n 以外…

子类调用父类同名方法和属性

1、全量代码 class Master:def __init__(self):self.kongfu [古法煎饼果子配方]print(fMaster_self:{self})def make_cake(self):print(f运用{self.kongfu}制作煎饼果子)class School():def __init__(self):self.kongfu [学校煎饼果子配方]print(fSchool_self:{self})def m…

Java Serializable 序列化

Java的Serializable接口是Java序列化机制的核心&#xff0c;它允许一个对象的状态被转换为字节流&#xff0c;从而可以方便地进行存储或传输。 序列化后的对象可以被写到数据库、存储到文件系统&#xff0c;或者通过网络传输。 要在 Java 中使一个类可序列化&#xff0c;你需要…

CSS一些小点 —— 12.7

1. box-sizing: border-box box-sizing 属性&#xff0c;默认值为 content-box box-sizing: border-box 使padding和border的值不会再影响元素的宽高&#xff1b;padding和border的值算在指定宽高的内部&#xff08;但是外边距依然算做外部&#xff09; 2. overflow: hidden …