SVG与Canvas图表性能对比
Author:zhoulujun Date:
选择 Canvas 还是 SVG
比如我们使用echarts、highcharts、antV等图表库的时候,到底是使用svg还是使用canvas模式,如何选择呢?
一般的说法会告诉你:SVG性能比Canvas性能差!真的这样吗?
看看echarts官网的说法:https://echarts.apache.org/handbook/zh/best-practices/canvas-vs-svg/
Canvas 更适合绘制图形元素数量较多(这一般是由数据量大导致)的图表(如热力图、地理坐标系或平行坐标系上的大规模线图或散点图等),也利于实现某些视觉 特效。但是,在不少场景中,SVG 具有重要的优势:它的内存占用更低(这对移动端尤其重要)、并且用户使用浏览器内置的缩放功能时不会模糊。
在小数据量的情况下,SVG性能更好:内存占用会更小,做缩放、平移等操作的时候往往帧率也更高。
性能差异
参看:https://g2-v3.antv.vision/en/docs/manual/tutorial/renderers
能对比要看场景。从底层来看,Canvas 的性能受画布尺寸影响更大,而 SVG 的性能受图形元素个数影响更大。下图是微软 MSDN 上给的一个对比图。
SVG 与 Canvas 不同的是,图形数量增多的时候,SVG 的帧率下降会更明显,因此,一般来说,
当图形数量小于 1000 时,我们可以考虑使用 SVG
当图形数量大于 1000 但不超过 3000 时,我们考虑使用 Canvas2D
图形数量超过 3000 时,用 Canvas2D 也很难达到比较理想的帧率了,这时候,我们就要使用 WebGL 渲染。
WebGL 有支持的批量绘制的技术,叫做 InstancedDrawing(实例化渲染),在 OGL 库中,只需要给几何体数据传递带有 instanced 属性的顶点数据,就可以自动使用 instanced drawing 技术来批量绘制图形。
WebGL,绘制 30000 个小球:WebGL 渲染之所以能达到这么高的性能,是因为 WebGL 利用 GPU 并行执行的特性,无论批量绘制多少个小球,都能够同时完成计算并渲染出来。
当谈论图形渲染技术时,就不得不提到DOM驻留模式和Canvas快速模式。
DOM驻留模式
DOM驻留模式是一种基于文档对象模型(DOM)的渲染技术。在DOM驻留模式下,页面的布局和样式是由DOM树来掌管的。当页面需要更新时,浏览器会重新计算布局和样式并重新渲染。此模式非常灵活,特别适用于处理动态页面交互和多样化的样式控制。然而,由于需要频繁地重新计算布局和样式,对于复杂的图形渲染任务来说,性能开销相对较高。
SVG是使用 XML 来描述二维图形和绘图程序的语言。在H5地图引擎中会用SVG技术做图形绘制,特别是在 Android 浏览器中进行图形操作时会遇到明显的性能问题,以下是针对SVG在浏览器绘制过程的一些优化总结与实践。
SVG性能优化
将属性“Pointer-event”设置为"None"
其实如果一个元素如果要是不需要产生任何事件的话,最好吧这个属性设置成none。其实每个元素都有很多事情,一次鼠标移动就可以让有用没有用的事件被激活,即便是没有事件处理函数,SVG解析器也是要处理这些事件消息的。所以为了减少解析器的工作负担,就直接屏蔽掉最好。
重复标签定义在Defs中
Defs标签的作用就是为了复用,其实在软件开发过程中复用的思想是不可或缺的,在SVG技术中也是如此。Defs和g标签是容器元素,但是在Defs元素的子元素在解析的时候不会渲染,只有在use的时候才会渲染,所以这就是一次解析,到处渲染。
Filter属性百分比
在filter元素中的属性x、y、width、height最好用百分比,能够将计算路径效果的区域减少到最小,加快图形的显示速度。
减少透明度使用
对于opacity透明度来说,使用透明度确实能够增加美观度,但是却牺牲了很大的性能,如果有可能的话尽量使用fill-opacity或者stroke-opacity这两个开销小些的属性。
重绘区域尽可能小
读者可以自己写一个SVG的移动的DEMO,一个将重绘区域即移动的位移大一些,一个小一些,再来观察CPU的占用率,会发现重绘区域是非常消耗性能的,所以需要将重绘区域尽可能小。
使用shape-rendering="optimizeSeed"来替代反锯齿效果
这样做虽然会牺牲一些图质量,但对子“clipPaths”和某些图象的动画而言,却有很好的性能效果
使用内部CSS属性
使用内部CSS样式表的渲染速度,要比使用外部的CSS样式表更快。
尽量让多条元素合并成一个元素
这样可以减少内存占,加快渲染的速度。这条技功在ASV中屡试不爽,但在Opera和Firfox的SVG解释析器中却有着完全相反的效果,渲染速度会变得更慢。
减少色彩渐变和滤镜
这两个效果也都是性能的消耗大户,需要尽量少使用。
减少stroke属性使用
Stroke属性也是非常消耗性能,主要是内部计算的开销会比较大,所以如果能用fill的地方就不要用stroke属性。
另外一种就是从服务器端生成SVG发送到客户端
这种方法主要目的就是让客户端的事情更加单一些,主要负责图形的渲染,从而降低性能开销。
Viewbox
Viewbox属性定义了SVG图形的显示区域。通过合理设置Viewbox,我们可以控制图形的渲染范围,从而减少不必要的计算和渲染。
例如,假设我们有一个大的SVG图形,其中只有一部分区域需要显示。我们可以将Viewbox属性设置为只包含需要显示的区域,从而减少浏览器渲染整个图形的工作量。
Transform属性
Transform属性允许我们对SVG图形进行旋转、缩放、平移等变换操作。合理使用Transform可以避免不必要的重绘和重排,提高性能。
在svg.js中,可以使用transform方法对图形进行变换。
var svg = SVG().addTo('#container').size(500, 500); var rect = svg.rect(100, 100).attr({ fill: 'red' }).move(50, 50); rect.transform({ scale: 2 }); // 放大两倍
为了进一步优化性能,我们可以结合使用Viewbox和Transform属性。例如,在拖动和缩放操作中,我们可以根据用户的交互动态调整Viewbox和Transform属性,只更新必要的部分,避免不必要的渲染和计算。
Canvas快速模式
Canvas快速模式利用HTML5的Canvas元素进行图形渲染。在这种模式下,开发者可以使用Canvas提供的2D或3D绘图API直接在画布上绘制图形。相比于DOM驻留模式,Canvas快速模式更加高效。它不关心页面的布局和样式,而是在需要时只重绘受影响的部分。这样就避免了频繁的布局和样式计算,提高了渲染性能。
canvas如何做性能优化,这个需要讲的实在太多了,这里就不说了
参考文章:
https://www.jointjs.com/blog/svg-versus-canvas
https://medium.com/stackanatomy/svg-vs-canvas-a-comparison-1b58e6c84326
【性能篇】28 # Canvas、SVG与WebGL在性能上的优势与劣势 https://developer.aliyun.com/article/1171678
转载本站文章《SVG与Canvas图表性能对比》,
请注明出处:https://www.zhoulujun.cn/html/webfront/visualization/charts/9236.html