# 42 | 如何整理出我们自己的可视化工具集? 你好,我是月影。 我们知道,可视化虽然可以认为是前端的一个小分支,但总体来说它也是一个比较有广度的领域,从内容上大体包括数据图表、图形绘制、地理信息可视化、3D场景和数字孪生应用等等,从设备上包括移动端、PC浏览器和可视化大屏等等。 作为刚刚入门可视化领域的工程师,我们经常会因为知识面不够广、工具不够丰富,而寄望于用单一的工具来解决我们遇到的所有问题,所谓“手里有锤子,看什么都像是钉子”。想想也知道,这并不能很好地处理所有的可视化应用。因为,一旦我们选择了错误的、不适合于当前场景的工具,就会让最终实现的结果不理想,或者开发效率不高。 因此,想要成为一名优秀的可视化工程师,我们必须要知道如何丰富自己手中的工具集,来应对各种场景和挑战。丰富工具集,并不意味着我们需要从头开发一切适合各种场景使用的工具。大部分时候,我们可以利用行业发展和社区的力量,站在巨人的肩膀上,使用各种成熟的工具,来更好地完成我们的项目。 那今天,我带你一起系统地梳理目前行业里,适合可视化应用的优秀且成熟的工具,来丰富你的工具箱,让你在面对各种可视化需求时能够游刃有余。 首先,我们来看看可视化应用的主体需求分类,搞清楚了这些,我们才能选择出更合适的工具来完成这些需求。根据可视化场景,主体需求一般可以分成5种,分别是绘制基本图形、绘制基础图表、绘制关系图和流程图、绘制地理信息以及绘制三维模型和数字孪生应用。接下来,我就一一来说。 ![](https://static001.geekbang.org/resource/image/88/a8/8869a44444710e25556fd1b801a400a8.jpeg) ## 选择绘制基本图形的工具 我们先来说说绘制基本图形要选择的工具。简单情况下,我们用浏览器原生的四类基本图形系统就可以完成绘制,分别是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模型数据,通常是通过设计工具离线生成的。这种应用场景在游戏领域比较常见。 [![](https://static001.geekbang.org/resource/image/1a/37/1af60e98b43a3b35a6e42e75d38e8937.jpeg "SpriteJS加载的3D模型数据,图片来源:spritejs.org")](https://spritejs.org/demo/#/3d/fox) 另一类则是动态加载3D几何模型,用前面绘制基本图形的工具就可以实现。在可视化应用中,这类场景通常更普遍。 [![](https://static001.geekbang.org/resource/image/be/f9/be76cd097e373b9c225dd361f58ee2f9.jpeg "动态加载的几何图形,图片来源:OGL")](https://oframe.github.io/ogl/examples/?src=scene-graph.html) 不过,在可视化领域中,有一类应用也会用到非常多的3D模型,那就是数字孪生应用。所谓数字孪生,是对物理世界实体或系统的数字化表达。简单来说,就是在虚拟世界中,通过3D渲染来还原真实物理世界,这需要我们将现实世界中的物体模型化为虚拟世界中的3D几何体。 [![](https://static001.geekbang.org/resource/image/3b/fa/3bf6256eabca8c8d5a0bcd152154fdfa.jpeg "物理世界和数字孪生示意图,图片来源: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类,分别是:绘制基本图形、绘制基础图表、图可视化、地理信息可视化以及数字孪生。 这些场景各自有适合的工具库和框架可供我们选择,我在这里整理了一个脑图,供你在具体应用中参考。 ![](https://static001.geekbang.org/resource/image/4d/53/4d546e0ff09bfa513767ba71612c5e53.jpg) 这是我们专栏最后一个模块的最后一节课了,在这几个月的时间里,我们先后学习了图形学与数学、视觉基础、视觉高级以及数据处理的相关知识。其中,我们通过一些可视化实战,学习了部分图形系统与图形库和工具的使用,这当中主要包括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/)