• home > webfront > visualization > charts >

    SVG与Canvas图表性能对比

    Author:zhoulujun Date:

    选择 Canvas 还是 SVG比如我们使用echarts、highcharts、antV等图表库的时候,到底是使用svg还是使用canvas模式,如何选择呢?一般的说

    选择 Canvas 还是 SVG

    比如我们使用echarts、highcharts、antV等图表库的时候,到底是使用svg还是使用canvas模式,如何选择呢?

    Canvas vs SVG

    一般的说法会告诉你: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 上给的一个对比图。

    Canvas vs SVG: pref

    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