在Apache ECharts 5 系列教程(2)视觉设计中,我们了解到,通过在视觉设计方面的调整,我们希望能够让读者更关注图表中重要的信息。而接下来我们要介绍的多状态设计则更进一步地让读者参与交互,交互的丰富性和流畅性使得用户更深刻理解数据之间的关联。
交互能力
状态管理
在 ECharts 中,所有系列的图形和文本都拥有高亮和普通两个交互的状态, 我们可以分别设置这两个状态的图形和文本的样式。
普通状态就是图表默认所呈现的样子,而高亮状态会在在鼠标移入或者图例联动的时候触发达到提示用户的效果,就像下图演示的一样,鼠标移到中间柱子上进入高亮状态变成设置的黄色,移出后回到普通状态的蓝色。
而在一部分交互更加丰富的系列中,还存在着更多的交互状态。比如饼图或者地图中可以点击选择数据,而选中的图形会进入选中态。
或者在旭日图,关系图,桑基图中在高亮一个数据的时候,不相关的数据会进入淡出状态,从而达到聚焦目标数据的效果。
但是这个淡出和选中态在 ECharts 4 及之前的版本中,只在部分系列中提供,而且无法配置这两个状态的样式。所以我们经常会碰到这样的需求,柱状图是否可以像饼图一样提供点击选中的功能,能否给关系图的节点配置淡出时候的不透明度?
为了满足这些需求,我们在 ECharts 5 中对状态管理做了全面的重构,从而能够为所有的系列提供了点击选中以及聚焦淡出其它数据的交互。
并且比如像颜色、阴影、边框,不透明度等高亮状态中可以配置的样式,在选中状态和淡出状态中都可以配置。
跟饼图一样,在其它系列中我们可以通过 selectedMode
配置项来开启数据单选,多选的功能,然后可以通过点击选中数据,选中的数据会被应用设置的选中样式。除此之外,我们可以通过监听 selectedchanged
事件,拿到当前所有选中的数据,从而进行更深度的展现。
ECharts 5 中可以在任意系列上通过设置 focus
来开启系列的聚焦外淡出功能。
比如这个柱状图在鼠标高亮一个数据的时候,其它不想关的系列都会进入淡出状态并且应用设置的淡出样式,被聚焦的系列就可以更清楚的呈现出数据的对比。或者配合我们新的文本优化,也可以实现鼠标移到标签上后聚焦显示该数据的效果。
开发者可以通过不同的 focus
和 blurScope
去灵活的配置聚焦的粒度。focus
用来配置相关的聚焦数据,比如是整个系列,亦或是只是当前数据。如果不希望聚焦淡出的效果影响到其它坐标系的数据,则需要设置 blurScope
来限制淡出的范围。如果设置为 global
则是淡出图表中所有的其它数据。
focus
也可以通过数组更灵活的去指定每一个需要联动聚焦的数据,从而在 circle packing 这样的自定义系列实现的层级图上实现更丰富的交互效果。
性能提升
刚刚我们介绍了 Apache ECharts 5 中新增的交互功能,除此之外,我们在性能上也做了优化去保证交互的流畅性。
性能,一直是 Apache ECharts 非常重要的一个方向,在之前的版本里,我们分别引入了渐进渲染,独立的高亮层,WebGL 渲染等优化技术来提升大数据中交互的流畅性,也通过新增 SVG 模式来提升移动端上的性能,这些技术分别有各自的优劣以及其适用的场景。
在 5 中,我们将引入一个新的技术——脏矩形渲染,来更全面的提升 Apache ECharts 5 的交互性能。
脏矩形渲染
在了解脏矩形渲染之前,我们需要对 ECharts 是如何渲染出一个图表的有一个粗略的了解。
我们对外提供了各种图表类型,比如柱状图、折线图、饼图等等,这些图表类型会被拆解成不同的图形,比如柱状图是多个矩形组成的,折线图是多个线段组成的,饼图是多个扇形组成的等等。而这些图形将被进一步地拆解成画线,画圆弧这样单位的路径操作。为了保证上层绘图接口的简单一致,我们使用了一层代理去隔离路径操作和底层不同渲染引擎的实现。最后到浏览器图形接口这一层,Canvas 会调用相应的绘制指令,SVG 则是更新 DOM 去做最终的绘制。
其中 Canvas 的优势是重绘快,所以适合大数据量。而 SVG 的优势则是内存占用低,更适合移动端。我们这次新增的脏矩形优化,是希望把 Canvas 的大数据量重绘性能继续提升一个台阶。为更多场景提供更流畅的交互体验。
对于 Canvas 渲染引擎,在鼠标 hover 高亮这样的交互导致图形发生变化时,ECharts 就会对整个画布进行重绘。也就是擦除整个画布,然后依次绘制所有元素。这种方式很简单可靠,而且在几百甚至上千个图形的时候能保持非常流畅的交互。
但是如果图形再多一点,比如像这样有上万个图形的热力图,因为每帧全部重绘的时间过长,就有可能发生交互的卡顿。
在之前版本,我们采用了一个额外的 Canvas 层作为高亮层来解决渲染性能的问题。也就是将鼠标高亮引起改变的图形放到一个单独的层中进行渲染。这种方式非常简单粗暴地解决了大数据下的交互流畅性。
但是它也不是银弹,也存在一些问题。
首先,这个额外的 Canvas 层会带来额外的内存消耗;其次,由于这种算法并没有擦除原先的元素,所以并不适合复杂的样式变化,比如不透明度或者阴影发生改变的时候就会露馅。另外,有的平台并不适合多层 Canvas 叠加,比如 Node.js 或者小程序。
因此在 ECharts 5 中,我们引入了脏矩形渲染这个更加通用的技术方案来弥补这些问题。通过每次只擦除和重绘画面中有修改的部分来减少每次重绘的图形,提升交互流畅度。
脏矩形的开启非常简单,只需要在 init
创建图表的时候把 useDirtyRect
参数设置为 true
就行了。
首先,我们用一个非常简单的例子来看下脏矩形是怎么做到提升重绘性能的。假设画面中有这样四个矩形。
其中两个现在改变了颜色,因此需要重新绘制。
ECharts 会追踪到这两个发生改变的图形并计算出包围盒得到需要更新的区域,并擦除这个重绘区域。
然后在这个范围内,依次绘制在这个重绘区域内的元素。这样只需要绘制这两个变动的就可以得到更新后的画面。
如果画面中有非常多的元素而只有少部分才发生了变化,脏矩形渲染就可以有效减少每次需要重绘的内容。
当然这只是最简单的一个演示,实际算法处理的场景是会更复杂的,我们做了很多工作保证了脏矩形算法在各个场景的正确和高效。
我们再来看在实际场景中脏矩形的应用。大家在我们新的示例页上的渲染设置中选择开启脏矩形优化就可以非常方便的看到效果。
这是一个在日历上每天绘制饼图的的例子,红色的框框标出了每次重绘的内容。在进行交互的时候每次都只重绘了其中一个饼图,重绘的效率自然也是大大的提高了。
除此之外,现在的绝大多数现代浏览器也会通过脏矩形技术只对画面改动部分做重绘和合成,这个额外的加成更进一步的提升了我们的重绘性能。下图绿色的框表示了 Chrome 中重绘的区域。
最后我们通过一个例子来直观得看看脏矩形所带来的性能提升。
这是一个带了阴影,半透明效果,比较复杂的矩形树图。鼠标移到图形上的时候会有一个阴影放大的上浮动画效果。在关闭脏矩形的时候,这个动画是非常卡的,平均只有 10 帧,已经严重的影响到了整个交互的流畅性。图中底部大量红色的帧就代表了这个动画已经严重阻塞了整个页面。
在开启脏矩形后,帧数有了非常大的提升,尽管中间还有一些少量的卡顿,但是整体的交互已经非常流畅了。
上面介绍了脏矩形渲染在 ECharts 5 中的应用,如果你在自己复杂的图表中碰到了交互上的性能问题,就不妨试试开启我们脏矩形渲染。
折线图优化
在 ECharts 中,折线图常常会被用来可视化 CPU,内存这样的实时时序数据, 这些数据往往更新频率很高,几百毫秒甚至几十毫秒就需要更新一次,而且每次更新的数据量都往往很大。之前 ECharts 的折线图对这种高频大量的数据的优化并不是很好,所以经常会有开发者反馈折线图更新重绘会卡顿,而且内存占用高。
因此在 ECharts 5 中,我们对于折线图中做了集中的优化去降低内存占用和初始化的耗时。
我们将内部图形数据的存储都从原先的动态数组改为使用 TypedArray
来做静态存储,从而可以大幅度降低浏览器的堆内存占用以及垃圾回收的时间,进一步有效降低初始化开销,从这两张图可以看出,这一优化在数据量越大的时候,对初始化时间和内存占用的提升越明显,在百万数据量的级别下可以达到 10x 甚至更多的提升。
同时,我们也在原先降采样的功能上新增了采用 LTTB 算法的降采样,LTTB 算法能够做到在保留折线图局部趋势和极值的前提下,将需要绘制的点降低到只需要几千个,从而进一步减少折线图的初始化时间。而我们原先使用的平均值,最大值等降采样策略则会丢失过多的数据信息。
再加上一系列对内部代码细致的性能调优,配合浏览器的 JIT,对于百万级别的数据,ECharts 可以做到 30ms 内完成一次数据的更新和重新渲染,从而满足实时更新的需求。
当然这些性能提升并不只是针对于时序数据,所有类型的大数据量折线图都可以从中获得性能优化所带来的收益。
而对于更极端的千万数据的场景,ECharts 可以做到 0.76s 渲染完一个拥有一千万数据的折线图,内存占用仅为 370MB,并且依旧可以已 60fps 的帧率流畅得进行 tooltip 等交互。
可能你在自己的应用中并不一定会碰到这么极端量级的数据,但是相信这个优化后的效果可以让你在用 ECharts 实现大数据折线图时更加游刃有余。
其他
除了用户体验之外,我们也非常重视开发者的体验。在下一篇文章中,我们将会介绍 Apache ECharts 5 在开发者体验提升方面的努力。