D3 迎来全新版本 5.0 发布

1,955 阅读6分钟


原文链接 - zhuanlan.zhihu.com/p/34853267 

还是那个熟悉的界面,但 D3 已经悄悄迎来了一个全新的版本——5.0。

就在几个小时前,Mike Bostock 修改了 D3 仓库主分支的 CHANGES.md,意味着 D3 5.0 正式发布。相比 D3 4.0 版本大刀阔斧的自我革命式更新(包括整体代码模块化切分、多个二级 API 改动、采用 ES2015 modules 重写等等),5.0 版本 更新的 feature 中只有少量向后不兼容的改动。
从2011年2月18日发布 D3 1.0.0 版本开始,D3 已经稳步向前走到了第八个年头,观察如今的可视化领域,众多依赖 D3 高级封装的可视化库层出不穷,NVD3C3D4等等,在他们的 introduction 部分无一例外的都会写上一句:
… is a visualization library based on D3.
有些库紧随 D3 的更新而迭代发版,而有些库止步于前年的那次版本大更新。由于 D3 对界面中的可视化元素具有很大的可控性,这也意味着该库的上手难度相比其他 JavaScript 库会更大一些。而由于历史和现实原因,很多开发人员并非专职做可视化设计与研发,所以对他们来说可视化只是他们众多需求中一个需要快速完成的任务。

基于此现状,国内很多可视化团队也在不断研发更适合国人开发的可视化工具库,一方面是为了降低可视化研发的入门门槛,另一方面应该也是受 Mike 的鼓舞,想在可视化工具库领域做点有意思的事吧。Echarts,由于涵盖了多个图表类型、较早采用 canvas + SVG 平衡渲染性能以及几乎零配置的开发成本,其名声被传遍大街小巷。

G2,基于 The Grammar of Graphics 开发,由于遵循一套比较完整的从数据到图形的映射关系,为开发人员提供了较强的定制化图表开发能力,其优秀的表现同时也获得了 The Grammar of Graphics 一书作者的肯定:
扯远了,我们回到 D3 上来吧。总而言之,在 Web 可视化领域,经过多年的发展,D3 可以算得上是全球最知名的 JavaScript 开源库了,这里都不用加上之一。D3.js,或者称为 D3,全称是 Data-Driven Documents,一个用动态图形显示数据的 JavaScript 库,一个数据可视化的工具。基于 Web 层面,D3 通过操纵三类对象来达到数据驱动可视化展现的目的,这三类对象分别是 SVG,Canvas 和 HTML 上的基本 DOM。它兼容 W3C 标准,并且利用广泛实现的 SVG,JavaScript 和 CSS 标准来封装底层接口。接下来,我们细细看看 D3 在全新的版本中都有哪些改变。

在 5.0 版本中,D3 开始采用 Promises 而不是传统的异步回调来加载数据。熟悉 Promise 的同学应该知道, Promise 可以简化异步代码的结构,特别是在支持 async/await 用法的现代浏览器中(详情可以参阅 ObservablePromise 介绍一文)。例如,在 D3 4.X 版本中加载一个 CSV 文件,你也许会这样操作:

d3.csv("file.csv", function(error, data) {
  if (error) throw error;
  console.log(data);
});
而在 D3 5.X 版本中,你可以使用 promise 这样书写:
d3.csv("file.csv").then(function(data) {
  console.log(data);
});
值得注意的是,你不再需要重新抛出获得的 error——promise 会自动 reject 产生的错误,如果需要的话你可以通过 promise.catch 来处理它。如果使用 await 语法,你的代码将更加简洁:
const data = await d3.csv("file.csv");
console.log(data);
随着 promises 在 D3 中的采用,D3 现在使用 Fetch API 替代原有的 XMLHttpRequest,随之对应的是 d3-request 木块被 d3-fetch 替代。Fetch 支持很多强大的功能,例如 streaming responses。D3 5.0 同时也弃用并删除了 d3-queue 模块。你可以使用 Promise.all 来并行运行批量的异步任务,或者使用 p-queue 等辅助库来控制并发

D3 不再提供类似 d3.schemeCategory20* 的分类颜色方案。这二十种颜色方案存在明显缺陷,因它们的分组设计可能会错误的暗示数据之间的关系:一份共享的色调可能意味着对应的数据会归属到同一组别中,而颜色亮度的深浅可能会暗示数据的顺序。 取而代之的是,D3现在包含一个库叫 d3-scale-chromatic,它实现了 ColorBrewer 中的一些优秀的配色方案,这包括分类发散连续单色以及连续多色 等方案。这些方案既支持离散变量同时也支持连续变量赋值。

D3 现在提供了通过 d3-contour 来实现 marching squares 算法和密度估计的可视化效果!现在有两种新的 d3-selection 方法:其中,*selection*.clone API 用于插入所选节点的克隆版本,而 d3.create 可以用于创建分离的元素节点。d3-geo 地理投影模块现在支持 *projection*.angle API,这促使我们现在可以使用由 Philippe Rivière 开发提供的若干全新的多面投影方法(模块)了。

最后,D3 的 package.json 文件不再引用从属于 D3 模块的精确版本号了。这解决了 D3 模块重复安装的一个问题。

相比 D3 4.0 版本长篇阔论对其中的多个改动进行详细介绍,5.0 CHANGES 只包含短短几段就将新版本的功能介绍完毕。不论你是第一次听说 D3,还是曾经听过 D3 但不熟悉利用 D3 进行开发,又或者一直尾随 D3 从 v3 一路走来,现在 D3 5.0 已经发布,何不上手试试呢?

直接从官网引入库,利用 CDNJS 或者 unpkg 又或者从 npm 上下载,总有一种方式适合你。引入整个包文件或者只引入一个 D3 小模块也是任你挑选:
// 引入整个库文件
<script src="https://d3js.org/d3.v5.js"></script>

// 引入压缩后的整个库文件
<script src="https://d3js.org/d3.v5.min.js"></script>

// 只引入 d3-selection 模块
<script src="https://d3js.org/d3-selection.v1.js"></script>

// 使用 import 语法引入具体的 D3 模块
import {scaleLinear} from "d3-scale";

// 使用 import 语法引入整个 D3
import * as d3 from "d3";

// 在 Node 中引入 D3
var d3 = require("d3");

// 针对多个 D3 模块独立引入后合并至 d3 命名空间
var d3 = Object.assign({}, require("d3-format"), require("d3-geo"), require("d3-geo-projection"));
更多 D3 及官方示例可以移步 D3 官网,关于 D3 历次版本 Changes log 可以查看 CHANGES.md。不少同学还留恋于 D3 V3 的开发,关于这方面的中文文档可以移步由 VisualCrew 小组组织翻译的 API V3 中文手册,D3 V4 版本中文文档可以查看 中文手册v4

WebGL 方面的三维可视化可以参考 mrdoob 的 three.js,关于地理空间的可视化可以参考 mapbox,leaflet 和 openstreetmap 的相关开源库,例如 mapbox-gl-js 等等。

更多 D3 代码示例可以查看 D3 Gallery,当然,更好的 D3 作品等待你的呈现。

个人公众号,微信搜索「黯晓」或扫描 二维码 关注,会同步我在知乎个人博客上发表的文章,谈谈前端技术与日常有趣事。知乎专栏是 初级前端工程师

生活中难免犯错,请多多指教!