最近一直在研究数据可视化的相关理论和实现方案,相关实现技术和工具也了解使用了不少,需要写篇综述性的文章做整理。由于本人之前主要是做web开发的,故而我所找到的数据可视化的实现技术和工具大部分都是基于web的。这很正常,因为web便于分享和查看,如无意外我们都希望用浏览器直接访问可视化作品。这篇文章主要记录我使用心得。
1. HTML5 canvas
乔教主去世的前后两年,HTML5非常火,在乔教主的指引下,HTML5仿佛是未来的明灯,将一统移动端和桌面的浏览器,甚至制造各种原生应用,似乎开个web相关会议不谈谈HTML5大方向就落伍了。但是到了2013年,HTML5的话题一下子沉寂了下来,仿佛之前的热闹都是假象——事实上这是因为这个东西已经从未来变成的现实,一个新技术进入了平稳发展期,自然没必要像宣传普及期那么大张旗鼓了。
HTML5标准主要是给给浏览器厂商看的,就是要让浏览器支持从调用摄像头到3d绘图等一系列功能,通过统一标准来减轻web开发者的负担。不过HTML5推进过程也不像原来想象得那么顺利。HTML5遇到的最大问题是浏览器兼容性,标准不断地补充修改,但是并非所有浏览器都能使用。造成这种现状的原因有二,一方面有浏览器厂商因为利益原因大打出手(例如google反对h.264导致video标签难产),一方面有个别浏览器厂商不求上进半天不支持主要标准(微软现在也着急了,IE12已经迎头赶上了)。
从2010年末起我就开始接触使用HTML5相关的新技术。而用的最多的就是绘图相关的canvas标签。canvas标签的浏览器兼容性比较好。根据最新的统计(百度统计|流量研究院 )。国内还在使用IE6的用户已经接近10%。
<canvas></canvas>是html5出现的新标签,像所有的dom对象一样它有自己本身的属性、方法和事件。 使用canvas的基本方式是,使用js调用canvas的API绘图。例如,绘制一段贝塞尔曲线,需要用写这样一段javascript来生成:
function draw24(id) { var canvas = document.getElementById(id); if (canvas == null) { return false; } var context = canvas.getContext("2d"); //获取convas 2d对象,其中封装了很多绘图方法(现在canvas只有2D对象可以调用) context.moveTo(50, 50); //移动绘图中心点 context.bezierCurveTo(50, 50,150, 50, 150, 150); //绘制贝塞尔曲线 context.stroke(); //绘制边框 context.quadraticCurveTo(150, 250, 250, 250); //绘制2次样条曲线 context.stroke(); //绘制边框 }
最后绘制的结果如下图所示:
但是实际使用的时候我们通常不需要这样直接调用API。如同原生的javascript API很繁琐,调用起来比较麻烦,于是有很多JS库(如jquery等)将其封装以方便使用,HTML5 canvas也有相应的JS库。我用过并感觉不错的有如下一些:
- flot, 我第一个使用的canvas库。基于jquery,支持有限的视觉形式(折线、条形、面积、点)和缩放等动画效果,简单易用。
- RGraph,我第二个使用的canvas库。有优秀的动画效果,特点是有大量的传统统计图的例子,并且很容易对这些例子做定制。
- chartJS, 该库将很多基本统计图的实现方法封装起来,只要通过简单调用即可以实现。这货的优点就是简单易用,不过如果要做深度定制恐怕还不太够用。
- kineticJS, 是近来来canvas类库中的新秀。这个库的优点是在处理大量对象的时候很快,因为使用了多canvas技术。在它的官网上甚至能找到很多类似与flash动画的例子。另外它的教程不错。考虑到其他库很多时候依赖例子定制,而这个文档写的好对于自主设计更有效,可能是目前最强的库。
- porcessingJS, 它是著名的Processing语言的一个接口,用processing的语法以canvas进行绘图,之后讲processing的时候还会讲到。优点是自由度大,缺点是没有预定义模版,你可能需要到处找一些例子来学习。
- Echart, 一个由百度前端发起的canvas国产类库。这个echart其实是在canvas类库zrender的基础上做的主题图库,优点有数据驱动,图例丰富,功能强大,支持数据拖拽重计算,数据区域漫游,全中文文档非常过瘾。跟同样是国产的前端脚手架fis一样(官网http://fis.baidu.com/),都是诚意满满的国产套餐,体现了现今国内不俗的前端开发实力。我试用后感觉非常好,在我参与的一些项目中直接采用。关于我使用经验参见:百度数据可视化图表套件echart实战
此外,我使用过但是感觉很糟糕的有:
dataV.js, 此乃浙大CAD&CG国家重点实验室可视化与可视分析小组和阿里集团数据产品部门合作开发的开源可视化组件库。我2012年初就关注并试用了。当时我兴致勃勃地从github上下载了源码,企图用在自己的项目中。谁知第一个测试demo就各种出错,我查了半天,竟然发现原始demo里就有错误,bug出在类库的源码里,而且不止一个官方demo有错误。这个类库口号响亮令人震惊,但更新速度之缓慢令人震惊,文档不全也令人震惊。为此我不得不替换成RGraph.js。现在已经过了两年了,我回到他们的官网http://datavlab.org/,发现两年来官网就没怎么更新过!唯一的区别恐怕是原来官网上的几个例子的链接还失效了(想当初我可是把他们的例子、文章全部点击查看过)......从实用性上讲,跟现在百度新推出的Echart类库相比,2年前的datav.js弱爆了。而且官网长期不更新也让我很难对现在的它抱有信任。
这里有一篇翻译文章《知名html5 canvas库对比》,比较了github上更多的此种类库。有需要的朋友可以再到里面去看看。
最后再说说canvas这个技术本身的优缺点:
缺点:
- 只能绘制2D图像,暂时不支持3D图像。
- canvas绘制图形出并非可以直接操作的dom对象。如果要对其进行类似dom的操作,例如添加属性等等,比较麻烦(这就是为什么必须使用类库)。
优点:
- 由于canvas绘图不会给每个点生成对象,所以绘制速度快,消耗内存少。(这点主要是相对于SVG,VML技术而言)
- 兼容性较好。除了IE6,其他浏览器都可以支持。(IE7,8需要载入扩展JS,终究还是能用的)
2. SVG
关于SVG技术,在w3c的定义如下:
- SVG 指可伸缩矢量图形 (Scalable Vector Graphics)
- SVG 用来定义用于网络的基于矢量的图形
- SVG 使用 XML 格式定义图形
- SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失
- SVG 是万维网联盟的标准
- SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体
由于矢量图形技术的优越性(图像在放大或改变尺寸的情况下其图形质量不会有所损失,便于操作和编辑),因而将其应用于网络成了板上钉钉的事情。SVG标准很早就出现了,2003年初就成为了W3C标准。但是,它的普及花费了很长时间,其中主要原因就在于微软。由于2000年依赖微软取得了在浏览器市场的垄断地位,为了保持这种优势,微软有意地在IE系列中维持着一大批微软标准,而无视w3c。当然对于当时的微软来说它有这个底气。本着垄断的天性,微软于微软1999年9月附带IE5.0一起发布了VML矢量图形标记标准,有些人认为VML就是IE里的画笔。VML其实是Word和HTML结合的产物,也是用XML词表来定义。但是VML本质是word里图形程序在IE上的迁移,不仅不开源,而且操作复杂,效率低。令人遗憾的是在IE长达10年的垄断中一直只支持VM。IE6,7,8都不支持SVG,直到IE9才支持SVG。而现在,丧失浏览器垄断地位的微软终于认清现实,VML是已经过时的技术,在IE10中不予支持。详见微软的申明。
SVG最大的优点就是绘制和控制简单。直接在html页面里加入xml语句就可以编辑绘制。例如下面的代码就是画一个圆、一个椭圆和一道黑线,把这段代码另存为一个html文档再用谷歌浏览器打开就能看到效果了:
<html> <svg> <circle cx="25" cy="25" r="22" fill="blue" stroke="gray" stroke-width="2" /> <ellipse cx="250" cy="250" rx="100" ry="200" fill="yellow"/> <line x1="0" y1="0" x2="500" y2="50" stroke="black"/> </svg> </html>
跟前文中canvas绘图的方式比一比,就知道SVG是多么容易控制了。
当然,使用SVG时我们通常也是使用类库来提升效率。这里的类库主要有三种:
- highcharts.JS, 在现代浏览器中使用SVG绘图,在IE6,7,8中用VML绘图。包含一堆预定义的图表和样式。唯一的问题是,这货收费。只对非商业用途免费。
- raphael.js,以著名画家拉斐尔之名命名的绘图JS库,跟highcharts类似,也是SVG + VML兼容性方案。 但它是开源的,应用也比较广泛。使用它的时候有必要再下一个gRaphael图表库作为参考。
- D3.js,D3js是应用在web开发上的开源JS组件库,是一个数据可视化工具。D3应用的最为广泛,不过只支持SVG,我会重点讲述。
D3的全称是Data-Driven Documents(数据驱动文档),在github上关注数量超过了2万人(超过了所有canvas类库的关注数量),是非常受欢迎的开源工具。使用d3的有开发者,有设计师,有艺术家,资料非常丰富(虽然中文的很少)。关于D3的我的应用案例可以见我之前的文章《D3js初探及数据可视化案例设计实战》。
那么接着说说D3的优缺点(基本上也就是SVG的优缺点):
优点:
- D3最大的优点在于其资料丰富,案例非常多。这是真的是一个极大的优点。
- SVG矢量图形的特点是无损缩放,这个优势在显示2D图形式会有非常好的效果,并且兼容各种分辨率。
- SVG图形的节点可以像dom元素一样控制,这就让自主创作图形变得更容易。相对于canvas这也是非常大的优势。
缺点;
- SVG是2D矢量图,不能画3D图形。(用2D矢量可以画很多带透视效果的伪3D图,那并不是真正的3D图!)
- d3.不支持IE6,7,8。如果想要IE8使用d3,请用r2d3.js(一个结合了 Raphael.js的扩展库)。Raphael.js是一个跨浏览器的矢量图形库,它实现IE6,7,8兼容的方法是:在IE6,7,8中使用VML,在其他浏览器中使用SVG。另外,如果图形复杂,就不要指望用Raphael.js在IE上能跟D3画出一样酷炫的效果。
- SVG的节点都是对象,非常占用内存。例如论坛里一个朋友使用d3绘制超过12000个节点的图,直接导致每个试图打开它的浏览器都崩溃了。这个时候如果不愿意做简化那么应该试试canvas绘图。
最后,补充一个问题,如何在IE6这样的古董浏览器上绘制可交互的统计图形?
经过我长期摸索实践,结论是,不要试图这样做。即便是VML兼容方案性能也很差。在IE6上最靠谱的做法是用php或者java直接在后台绘制一个jpg图片,然后发到IE6上显示。这个方法也是5,6年前最通用的做法,现在已经过时了。最好的策略是,不要对IE6兼容,实在不行的话就显示一个不能动的图片吧!珍惜时间,珍惜生命,远离IE6!
3. webGL
前面说的绘图技术,无论canvas还是SVG都不能绘制3D图形。我曾经见过很多在网页上显示3d图形的方案,但都需要你的电脑上安装相应的插件(例如flash, silverlight)或者事先安装虚拟机(例如java)。之前曾经有过很多web 3D渲染技术,但不是要下插件,就是编程复杂,于是渐渐被时代淘汰,例如VRML,约翰•卡马克已经宣布了它的死亡。难道就没有一个开源的通用标准显示3D图形吗?
当然是有的。这货叫webGL, 是一项使用JavaScript实现3D绘图的技术,浏览器无需插件支持,Web开发者直接使用js调用相关API就能借助系统显卡(GPU)进行编写代码从而呈现3D场景和对象。
WebGL标准由科纳斯组织(Khronos Group)开发和维护,Google、Mozilla、Opera和Apple 等浏览器厂商都是其中的成员,为这一标准做出了显著贡献。从名称上我们就可以知道WebGL跟openGL肯定是小弟与大哥的关系。事实上webGL是基于OpenGL ES 2.0开发的,OpenGL ES 是 OpenGL 三维图形 API 的子集,针对手机、平板电脑和游戏主机等嵌入式设备而设计。浏览器内核通过对OpenGL API的封装,实现了通过JavaScript调用3D的能力。WebGL 内容作为 HTML5 中的Canvas标签的特殊上下文实现在浏览器中(这下canvas终于可以画3D图了,虽然用的是不同技术)。
webGL技术从初创到现在也不过2年多的时间(2011年发布标准),但是发展很快。一开始傲娇的微软认为该技术有极大的安全漏洞而拒绝使用(因为相当于让web脚本直接控制了显卡这么重要的硬件,同时有没有类似windows update这样的更新程序来弥补漏洞),但是现在也放下身段在IE12里面支持了此物。原因无他,就是HTML5带来的潮流:在功能上,web应用将会越来越像内建应用。它可以调用显卡,调用麦克风,调用摄像头,调用一切能用的硬件去提升服务质量。这一切都基于浏览器的支持。
webGL的各大浏览器支持情况(截至2013年11月):
桌面浏览器
- Mozilla Firefox 4+
- Google Chrome 8+
- Internet Explorer 11+
- Safari 5.1+
- Opera 12+
移动浏览器
- Firefox 25+
- Google Chrome 31+
- Opera Mobile 12+
- Android Browser 暂不支持
- iOS Safari暂不支持
- IE Mobile 暂不支持
从上面的支持情况列表我们可以发现,支持情况还是比较可喜的,至少现代浏览器都支持,移动端和IE略有落后。不过毕竟这个技术还是新鲜事物,在国内能找到的资料还很少,国内前端技术圈讨论也不多,是真正的技术蓝海。本人并没有实际开发过webGL程序,目前还停留在观察阶段。若有工作需求,会将其列入研究重点。
让我们查看一些webGL的案例,当然是mozilla demostudio的最好。
最后,让我们提一提webGL的JS框架,它们可以减少工作量并提供一些有趣的例子。
- philoGL,专注于3D可视化的一个webGL框架。
- threee.js, 谷歌团队Data Arts出品的基于webGL的3D场景库,它的演示十分有趣。
4.flash & actionscript
flash这个东西我是又爱又恨。爱是说我从初衷起就接触过这个东西,很喜欢它做的flash动画,并在大一大二也学过一阵;恨的是flash与web页面其实是完全分离的玩意,不仅要用自己的一套actionscript编写(并且as不如JS好使,我个人感觉),加载也要下载插件。在HMTL5+JS+CSS3的时代,越发觉得flash的大多数功能已被替代。
犹记当年乔教主2010年就怒喷过flash,认为它是移动端的阻碍,不适合触摸设备,技术封闭,已经过时。并且宣布苹果公司的产品在日后不支持flash。此举立即得到了微软、谷歌的响应。尤其是在经过HTML5的一番宣传以后,2010年前后大家都看淡flash的前景而看好HTML5。但是作为flash的老东家Adobe公司的发言人却一再表示:flash已经应用的非常普遍,想把我们一脚踹开是不可能的。现在究竟是鹿死谁手呢?经过3年的折腾,我们看到flash还是好端端地活着,当然份额确实减少了些。苹果还是立场坚定地拒绝flash支持html5,但是html5发展并不顺利;谷歌一面支持html5,一面也支持flash(你看现在的android手机不支持个flash都不好意思出门),同时还在折腾自己的视频标准害的HMTL5的视频标准一再难产;微软则在旁观,同时养活着flash,html5和自家的silverlight。可以说HMTL5联盟曾经试图联手杯葛flash, 结果由于各家心怀鬼胎而失利。HTML5的最终效果也没有完全达到flash的水准,虽然在很多领域(例如样式、绘图等等)已经基本上差不多了,但是至少在动画编辑这一块,HTML5至今也没有一个像adobe flash cs5 这么强大易用的编辑工具。
当初flash之所以能实现很多web页面不能实现的功能,是因为web标准从一开始就被设计地注重安全性,不能操作本地资源(典型的例子,到现在JS都不能操作内存);而flash是个本地程序,可以自由地调动本地资源,所以可以实现很多需要耗费大量本地资源的效果,例如2D动画、3D动画。但是随着计算机功能越发完善,很多2000年初很耗费资源的功能,现在看起来不值一提。HTML5则是从浏览器标准一级,要求浏览器能调用这些本地资源。这就是之前所说的HTML5带来的潮流:在功能上,web应用将会越来越像内建应用。所以未来flash终将被淘汰。但是adobe不会因此饿死,因为Adobe也不是用flash来赚钱,而是用flash编辑器来赚钱,如今也在flash编辑器中加入了html5元素,保证就算flash完蛋也能继续挣钱。
那么谈谈用flash构建可视化应用吧。由于flash在绘图、动画效果上长期保持的优势,所以过去有很多人用flash创建可交互的额数据可视化图表。并且如同那些js canvas类库一样,flash也有这样的类库。
5.java & processing
processing是久负盛名的为了实现交互式可视化创作的Java语言扩展,我在《Benjamin Fry的《可视化数据》和processing语言》一文中有过介绍。不过我并没有直接用过processing,而只用过processingJS, 一个使用processing语法的使用html5 canvas绘图的JS类库。在前文中已经有过推介。
6. R
R语言之前我已经多次提到了。这段时间我也开始试用,不过说句实话这个东西我觉得不能称为语言,我感觉它不像C++,更像mathlab这样的应用程序。它的图标很简陋,GUI更简陋,简直除了控制台再没有别的了。我想这是制作它的统计学家的心声:科学不是花里胡哨的玩意,它其实很枯燥,但很注重内在美!
SPSS和SAS是数据分析行业的标准工具,也能生成各种统计图形。不过这两个软件授权费那是相当昂贵。SAS我在高校实验室蹭过,但是目前手头上能用的只有R和盗版mathlab。R语言的操作跟mathlab很像,基本上都是自己写一段程序让它去运行。这里要谈谈R语言跟mathlab的区别。
- mathlab是商业软件,R是开源软件;mathlab我们几乎都在用盗版,R我们想用就用;由于是商业软件,别的程序很难调用mathlab程序;而R就是希望别人调用它,并且它自己也可以引用其他高于语言C, java ,python, ruby等写的代码。
- mathlab是数学家发明的,而R是数学家中的统计学家发明的;
- 有人说mathlab在某些算法上比R快,不过我还没感觉到;
- mathlab的3D图像要比R丰富;R画画2D图还行,画3D图又丑又慢。当然,R一直在改进。