<audio id="audio" title="42 | 如何整理出我们自己的可视化工具集？" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/16/9b/169c4556ea87100eb2ff21b128c8289b.mp3"></audio>

你好，我是月影。

我们知道，可视化虽然可以认为是前端的一个小分支，但总体来说它也是一个比较有广度的领域，从内容上大体包括数据图表、图形绘制、地理信息可视化、3D场景和数字孪生应用等等，从设备上包括移动端、PC浏览器和可视化大屏等等。

作为刚刚入门可视化领域的工程师，我们经常会因为知识面不够广、工具不够丰富，而寄望于用单一的工具来解决我们遇到的所有问题，所谓“手里有锤子，看什么都像是钉子”。想想也知道，这并不能很好地处理所有的可视化应用。因为，一旦我们选择了错误的、不适合于当前场景的工具，就会让最终实现的结果不理想，或者开发效率不高。

因此，想要成为一名优秀的可视化工程师，我们必须要知道如何丰富自己手中的工具集，来应对各种场景和挑战。丰富工具集，并不意味着我们需要从头开发一切适合各种场景使用的工具。大部分时候，我们可以利用行业发展和社区的力量，站在巨人的肩膀上，使用各种成熟的工具，来更好地完成我们的项目。

那今天，我带你一起系统地梳理目前行业里，适合可视化应用的优秀且成熟的工具，来丰富你的工具箱，让你在面对各种可视化需求时能够游刃有余。

首先，我们来看看可视化应用的主体需求分类，搞清楚了这些，我们才能选择出更合适的工具来完成这些需求。根据可视化场景，主体需求一般可以分成5种，分别是绘制基本图形、绘制基础图表、绘制关系图和流程图、绘制地理信息以及绘制三维模型和数字孪生应用。接下来，我就一一来说。

<img src="https://static001.geekbang.org/resource/image/88/a8/8869a44444710e25556fd1b801a400a8.jpeg" alt="">

## 选择绘制基本图形的工具

我们先来说说绘制基本图形要选择的工具。简单情况下，我们用浏览器原生的四类基本图形系统就可以完成绘制，分别是HTML/CSS、SVG、Canvas和WebGL。

HTML/CSS比较简单，也有很多丰富的前端领域的工具，这里就不多说了。SVG原生的API使用起来也并不复杂，不过我们也可以用一些成熟的绘图库，它能够让我们更方便地绘制各种图形。我比较推荐  [Snap.svg](http://snapsvg.io/) 这个库，它提供的API能够非常方便地绘制各种SVG图形。尤其值得赞扬的是它提供了一套[交互式教学文档](http://snapsvg.io/start/)，能够让你快速上手整个库的使用。

如果你使用Canvas和WebGL来绘制图形，可选的工具就比较多了。比较成熟的2D渲染引擎包括 [Fabric.js](https://github.com/fabricjs/fabric.js)、[Pixi.js](https://github.com/pixijs/pixi.js) 等，比较成熟的2D/3D引擎包括 [SpriteJS](https://spritejs.org/#/)、[P5.js](https://github.com/processing/p5.js) 等，以及比较成熟的3D引擎包括 [ThreeJS](https://github.com/mrdoob/three.js)、[Babylon.js](https://github.com/BabylonJS/Babylon.js) 等。这些库各有特点，它们的官方使用文档和示例都比较完善，我建议你多花一些时间去学习它们的使用方法。这能帮助你在绘制基本图形的时候，灵活选用适合的库。

另外，既然说到了Canvas2D绘制图形，那我还要提一下[Rough.js](https://github.com/rough-stuff/rough)这个库。这是个非常有特点的库，它能够绘制出带有手绘风格的图形，比如，我们在[第5课](https://time.geekbang.org/column/article/255584)就使用过它。

我刚才说的这些工具，对于绘制基本的2D/3D图形来说已经足够了。但是，功能相对更强大和丰富的库，体积也会更大一些，使用上也会复杂一些，所以我们还是应该根据实际需求复杂程度来灵活选择。

## 选择绘制基础图表的工具

绘制基础图表是可视化项目中很常见的需求，我们可以采用图表库和数据驱动框架来完成。常用的成熟图表库包括 [ECharts](https://echarts.apache.org/)、[Chart.js](https://github.com/chartjs/Chart.js)、[Highcharts](https://github.com/highcharts/highcharts)、[AntV G2](https://antv-2018.alipay.com/zh-cn/g2/3.x/index.html)  这4种。大部分图表库在使用上大同小异，效果也差别不大，好像选什么都没有差别。但在选择图表库的时候，我们也需要考虑底层的图形系统或图形库，这关系到复杂图表渲染和交互的性能，另外在同时需要绘制图表和基本图形的时候，选择统一的图形系统可以保持一致性，也能更好地实现图表与图形的协同交互。

这里，我就说几个常见的搭配组合。如果你使用SpriteJS作为底层图形库，还可以选择[QCharts](https://www.qcharts.cn/#/home)。如果你是在移动端设备渲染图表，可以考虑使用[AntV F2](https://antv-2018.alipay.com/zh-cn/f2/3.x/index.html)，这是一个专为移动端场景设计的图表库。如果你要绘制更加灵活的图表，以及关系图和流程图，可以选择数据驱动框架，例如[D3.js](https://github.com/d3/d3)。不过D3.js虽然很好用，但它是一个足够复杂的框架，如果你希望在可视化领域深入发展，最好能再多花一些时间，彻底掌握它的使用方法。

最后，我还想再说说[Vega](https://vega.github.io/vega/)这个库。这也是一个图表库，它定义了一套基于JSON规范的可视化语法，以声明式的方式来绘制各种图表。最关键的是，Vega定义可视化语法规范的思路，对我们自己设计和实现图表库有着非常大的借鉴意义。如果你打算自己设计一套图表库，我希望你能好好研究一下Vega，相信你会有所收获的。

## 选择绘制关系图和流程图的工具

接着，我们再来说一类特殊的图表，比如关系图、流程图、脑图等等。我们一般将它们单独归为一类应用，称为图可视化。

图可视化怎么实现呢？我们在[第38课](https://time.geekbang.org/column/article/291822)里使用D3.js实现过相关的例子。除了D3.js以外，还有一类直接绘制这些图形的图可视化库，常用的有[Mermaid.js](https://github.com/mermaid-js/mermaid)、[Sigma.js](http://sigmajs.org/)以及[AntV G6](https://antv-2018.alipay.com/zh-cn/g6/3.x/index.html)等等。

其中Mermaid.js量级更轻，主要是以声明的方式来绘制各种流程图。而Sigma.js和AntV G6的功能更丰富，实现的图可视化不仅类型更多，还能包含复杂的用户交互效果。

此外，还有一个特殊的库[Dagre](https://github.com/dagrejs/dagre)。它是绘制流程图的底层库，主要是用来计算图的元素布局，使用它再结合图形库，我们就能自己实现一个绘制流程图的图可视化库。这个图可视化库实现起来也不是很难，我把这个任务留在本节课的末尾，你可以试着去挑战一下。

## 选择地理信息可视化工具

前面两节课，我们一起完成了3D地理信息可视化的实战。地理信息可视化是可视化项目中很重要的一类应用，大部分可视化大屏应用场景都会包含地图或者3D地球，因为许多数据本就和地理信息相关。由于需求很多，因此市场上有许多地理信息可视化的库可供我们选择。

比较成熟的地理信息可视化库包括[MapBox](https://www.mapbox.com/)、[MapTalks](https://maptalks.org/)、[Leaflet.js](https://leafletjs.com/)、[MapV](https://github.com/huiyan-fe/mapv)、[AntV L7](https://antv-2018.alipay.com/zh-cn/l7/1.x/index.html)等等，它们都支持简单的geoJSON、topoJSON数据和分片加载的瓦片地图。另外d3的子模块[d3-geo](https://github.com/d3/d3-geo)也能够处理地理信息可视化，尤其是它提供了多种地图投影，非常适合与其他库联动，实现各种不同的地图场景应用。

总体而言，地理信息可视化是可视化领域里比较复杂的方向，这些地理信息可视化库的功能也较为丰富，使用场景很多，如果详细来讲的话，内容足够支撑起一门单独的课程了。我们前面花了3节课来讲的地理信息可视化案例，其实也只是给地理信息可视化应用开了一个头，如果你有兴趣深入学习，可以通过这些地理信息可视化库，再结合实战来真正深入掌握地理信息可视化的方法，这也是成为优秀可视化工程师的必经之路。

## 处理三维模型和数字孪生应用

在学习3D图形的绘制的时候，我讲到，3D绘制一般有两种方式，一种是加载静态的3D模型数据，然后将3D物体渲染出来。这些3D模型数据，通常是通过设计工具离线生成的。这种应用场景在游戏领域比较常见。

[<img src="https://static001.geekbang.org/resource/image/1a/37/1af60e98b43a3b35a6e42e75d38e8937.jpeg" alt="" title="SpriteJS加载的3D模型数据，图片来源：spritejs.org">](https://spritejs.org/demo/#/3d/fox)

另一类则是动态加载3D几何模型，用前面绘制基本图形的工具就可以实现。在可视化应用中，这类场景通常更普遍。

[<img src="https://static001.geekbang.org/resource/image/be/f9/be76cd097e373b9c225dd361f58ee2f9.jpeg" alt="" title="动态加载的几何图形，图片来源：OGL">](https://oframe.github.io/ogl/examples/?src=scene-graph.html)

不过，在可视化领域中，有一类应用也会用到非常多的3D模型，那就是数字孪生应用。所谓数字孪生，是对物理世界实体或系统的数字化表达。简单来说，就是在虚拟世界中，通过3D渲染来还原真实物理世界，这需要我们将现实世界中的物体模型化为虚拟世界中的3D几何体。

[<img src="https://static001.geekbang.org/resource/image/3b/fa/3bf6256eabca8c8d5a0bcd152154fdfa.jpeg" alt="" title="物理世界和数字孪生示意图，图片来源：36kr.com">](https://36kr.com/p/1723581366273)

在这样的应用场景中，有时候我们可以考虑采用游戏的方式，使用游戏引擎和框架，例如[Unity](https://store.unity.com/products/unity-pro?gclid=CjwKCAjwq_D7BRADEiwAVMDdHsaPnsc1S8jvT8yY47lLFn_jH6WvSTdhlDwf5RJtrC6Leu3LN--2HhoCUqIQAvD_BwE)或者[虚幻引擎](https://www.unrealengine.com/zh-CN/)来完成我们的可视化应用。当然，这也就进入了另一个领域，游戏创作的领域。这部分内容，我们简单了解一下就可以了。

## 要点总结

可视化有着丰富的使用场景，大致上可以分为5类，分别是：绘制基本图形、绘制基础图表、图可视化、地理信息可视化以及数字孪生。

这些场景各自有适合的工具库和框架可供我们选择，我在这里整理了一个脑图，供你在具体应用中参考。

<img src="https://static001.geekbang.org/resource/image/4d/53/4d546e0ff09bfa513767ba71612c5e53.jpg" alt="">

这是我们专栏最后一个模块的最后一节课了，在这几个月的时间里，我们先后学习了图形学与数学、视觉基础、视觉高级以及数据处理的相关知识。其中，我们通过一些可视化实战，学习了部分图形系统与图形库和工具的使用，这当中主要包括SpriteJS、D3.js、QCharts等等。这和我们这节课列出的各类工具相比，可以说是非常少了。

我想有的同学可能会有疑问，还有这么多的工具我们并没有详细来讲，那我学习到这里，算是真正入门可视化了吗？我想说的是，工具和库都是为我们服务的，正确使用这些工具和库的基础，其实就是我们前面学过的图形学与数学基础、视觉呈现技术，以及数据处理的原则，这些内容才是可视化的本质。而上层的工具和库的使用虽然复杂，但并不难，基本上照着文档学习和实践，就能够一步步掌握。

而如果缺少扎实的基础，那么在使用工具遇到缺失功能或者性能问题的时候，你就可能会束手无策。因此，这门课，更多的还是为你打好基础，领你进入可视化的世界，今后的路，就要靠你自己一步一步地走了。

## 小试牛刀

今天，我特意提到了Dagre这个库。它是一个基础库，经常用来给流程图的元素布局，不涉及渲染的部分。你能用它作为基础，再以SpriteJS为渲染引擎，来实现一个高效、强大的流程图库吗（提示：在API方面你可以借鉴Mermaid.js）？

除此之外，这节课，我们介绍的工具和库非常多，你肯定很难在短时间内完全掌握，但我也不希望你只是泛泛了解。所以，我希望你能选择自己最感兴趣的同类库中的两个库，利用我之前在GitHub仓库里留的北京天气和空气质量数据，分别使用它们做一些可视化应用，比较两个库在使用上的不同，以及各自的优、劣势。

欢迎把你实现的效果分享到留言区，也欢迎你把自己在工具整理上的心得体会分享出来，我们一起交流！

## 推荐阅读

[1] [Snap.svg](http://snapsvg.io/)、[2] [Fabric.js](https://github.com/fabricjs/fabric.js)、[3] [Pixi.js](https://github.com/pixijs/pixi.js)

[4] [SpriteJS](https://spritejs.org/#/)、[5] [P5.js](https://github.com/processing/p5.js)、[6] [ThreeJS](https://github.com/mrdoob/three.js)

[7] [Babylon.js](https://github.com/BabylonJS/Babylon.js)、[8] [Rough.js](https://github.com/rough-stuff/rough)、[9] [ECharts](https://echarts.apache.org/)

[10] [Chart.js](https://github.com/chartjs/Chart.js)、[11] [Highcharts](https://github.com/highcharts/highcharts)、[12] [AntV G2](https://antv-2018.alipay.com/zh-cn/g2/3.x/index.html)

[13] [QCharts](https://www.qcharts.cn/#/home)、[14] [AntV F2](https://antv-2018.alipay.com/zh-cn/f2/3.x/index.html)、[15] [Vega](https://vega.github.io/vega/)

[16] [Mermaid.js](https://github.com/mermaid-js/mermaid)、[17] [Sigma.js](http://sigmajs.org/)、[18] [AntV G6](https://antv-2018.alipay.com/zh-cn/g6/3.x/index.html)

[19] [Dagre](https://github.com/dagrejs/dagre)、[20] [MapBox](https://www.mapbox.com/)、[21] [MapTalks](https://maptalks.org/)

[22] [Leafletjs](https://leafletjs.com/)、[23] [MapV](https://github.com/huiyan-fe/mapv)、[24] [AntV L7](https://antv-2018.alipay.com/zh-cn/l7/1.x/index.html)

[25] [d3-geo](https://github.com/d3/d3-geo)、[26] [Unity](https://store.unity.com/products/unity-pro?gclid=CjwKCAjwq_D7BRADEiwAVMDdHsaPnsc1S8jvT8yY47lLFn_jH6WvSTdhlDwf5RJtrC6Leu3LN--2HhoCUqIQAvD_BwE)、[27] [Unreal Engine](https://www.unrealengine.com/zh-CN/)
