当前内容所在位置:
- 第五章 饼图布局与堆叠布局 ✔️
- 5.1 饼图和环形图的创建 ✔️
- 5.1.1 准备阶段(一)
- 5.1.2 饼图布局生成器(二) ✔️
- 5.1.3 圆弧的绘制(三)
- 5.1.4 数据标签的添加(四)
文章目录
《D3.js in Action》全新第三版封面
【译者按】看似神秘的 D3 饼图布局生成器函数,在作者抽丝剥茧般的讲解和精心制作的示意图下,变得非常浅显易懂。这才是真正的高手,用最简单的话,讲明白最核心的原理。尽管当中的 JavaScript
处理逻辑比较冗长,但瑕不掩瑜。
5.1.2 饼图布局生成器 The pie layout generator
准备工作完成后,就可以专注于环形图的构建了。饼图和环形图通过可视化的方式描述部分与整体之间的关系,或者刻画各部分的数量相对于总量之间的数量关系。利用 D3 的饼图布局生成器,我们可以根据环形图中各个部分相对于总量的百分比,算出其对应的起始角和终止角。
5.1.2.1 数据的格式化处理 Formatting the data
D3 饼图生成器期望的参数类型为数字型数组。例如,对于 1975 年的数据,我们希望它是一个包含各种音乐格式的当年的销售额数组:
const sales1975 = [8061.8, 2770.4, 469.5, 0, 0, 0, 48.5];
虽然这样一个简单的数组已经可以生成饼图了,但我们无从得知每个数字对应的音乐格式是什么。为了补全这些信息,可以将其改为对象数组,其中每个对象都包含音乐格式的 ID 以及对应的年度销售额。
如下列代码清单 5.3 所示,首先从数据集的 columns
属性提取音乐格式信息。例如,在使用 d3.csv()
方法加载数据时,D3 会将一个包含原始 CSV 数据列标题的数组添加到数据集中,并允许开发者通过 data.columns
进行访问。如果将获取到的数据输出到控制台,会在结果数组的末尾看到这个列标题数组,如图 5.5 所示。由于只需要考虑音乐格式,所以要筛选掉数组中的“年份”(即 "year"
)列。
【图 5.5 从 CSV 文件获取数据时,D3 会将一个列标题数组添加到原始数据集中,并可通过 data.columns 访问该列标题数组】
为了制备饼图生成器需要的对象数组,还需要提取待实现的年份数据,然后利用 JavaScript
的 find()
方法找到当年对应的数据项,再赋给常量 yearData
。
接着遍历音乐格式数组,为每种格式创建一个对象,里面包含当前格式的 ID 以及关联年份的销售额数据。最后将该对象添加到提前声明好的 formattedData
数组中。
代码清单 5.3 对数据进行格式化处理(详见 donut-chart.js
文件)
const years = [1975, 1995, 2013];
const formats = data.columns.filter(format => // 从数据 data 的 columns 属性提取出需要的音乐格式,并筛选掉 “年份” 字段
format !== "year");
years.forEach(year => {
...
const yearData = data.find(d => d.year === year); // 读取特定年份的数据项
const formattedData = []; // 初始化一个空数组作为最终的结果数组
formats.forEach(format => { // 遍历每一种音乐格式,分别创建一个对象,令其包含该格式的 ID 以及当年该音乐格式的销售额。然后将当前对象添加到结果数组。
formattedData.push({ format: format,
sales: yearData[format] });
});
});
数据准备就绪后,就得到一个如下所示的对象数组,其中每个对象都包含一个音乐格式 ID 以及当前年份的销售额数据:
// => formattedData = [
{ format: "vinyl", sales: 8061.8 },
{ format: "eight_track", sales: 2770.4 },
{ format: "cassette", sales: 469.5 },
{ format: "cd", sales: 0 },
{ format: "download", sales: 0 },
{ format: "streaming", sales: 0 },
{ format: "other", sales: 48.5 }
];
5.1.2.2 饼图布局生成器的初始化及其调用 Initializing and calling the pie layout generator
既然数据已就绪,接下来就可以初始化我们的饼图布局生成器(pie layout generator)了,用到的方法是 d3.pie()
。该方法隶属于 d3-shape
模块。鉴于数据格式为一个对象数组,我们需要告诉布局生成器:从哪里能获取到控制圆弧长短的数值,具体通过 value()
方法进行配置,如下列代码片段所示。最后,将该生成器赋给一个常量 pieGenerator
,以备后用。
const pieGenerator = d3.pie()
.value(d => d.sales);
为了生成饼图布局带注解的数据,只需调用刚才的生成器函数,然后将格式化处理后的数据作为参数传入即可;然后将得到的结果赋给另一个常量 annotatedData
:
const pieGenerator = d3.pie()
.value(d => d.sales);
const annotatedData = pieGenerator(formattedData);
饼图生成器函数返回的是一个全新的带注解的数据集,里面既有对原始数据项的引用,同时也添加了一些新属性(attributes),比如各部分的值(value
)、当前部分的索引值(index
)、起始角大小(startAngle
)以及终止角大小(startAngle
)(角度值均为弧度制):
// => annotatedData = [
{
data: { format: "vinyl", sales: 8061.8 },
value: 8061.8,
index: 0,
startAngle: 0,
endAngle: 4.5,
padAngle: 0,
},
...
];
注意代码中还包含了一个 padAngle
属性,它是各环形片段间的填充角,当前值为 0
,稍后再进行修改。关键要明白一点:饼图布局生成器并不直接参与 D3 饼图的绘制,它只是一个预处理环节,用于计算绘制饼图各部分对应的角度值。如图 5.1 和 5.6 所示,该环节通常涉及以下三个步骤:
- 格式化数据;
- 初始化饼图布局函数;
- 调用饼图布局函数并将格式化的数据作为参数传入。稍后再利用该函数返回的带注解信息的数据集来具体绘制各段弧线。
【图 5.6 饼图布局生成器是一个预处理步骤,负责生成一个包含每片段起始角、终止角在内的带注解信息的数据集。该过程通常涉及数据的格式化处理、饼图生成器函数的初始化及其调用】
(中篇完)
另附:专栏文章连载期间 完全免费,后续 不排除 调整为收费专栏。对 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 本章小结