canvas和svg渲染及其他
本文介绍下canvas和svg相关内容
渲染层面
在目前前端2d层面,图形化开发有两种方案:canvas和svg。借助它们都能帮我们绘制各种图形,但是两者底层原理完全不同。
canvas本质就是批量绘制像素点,从dom结构看,他就是一个完整的dom节点,不管你在上面绘制了多少path,最终就是一个dom节点canvas。但是用svg则完全不同,svg绘制的path本身,就是一个个的dom节点。所以如果是海量数据,很显然,使用canvas批量绘制像素点的效率,远高于创建海量的dom节点。但是svg也有优点,因为是一个个的dom,所以支持原生事件(click/hover)、CSS 样式控制,交互开发成本低,且矢量图形缩放无失真。
性能考量-canvas
有时候有些极端场景不可避免,比如Canvas 渲染 10 万条折线时出现卡顿,该如何优化?
视图渲染。这种手段的叫法有很多,什么脏矩阵、局部渲染等,但都是一个逻辑:只渲染视图范围内的数据。数据抽稀。说白了就是减少数据点。比如2d图形开发,本质就是一个个的点组成的。那么一条线段可以用10000个点描述,也可以只用两个点描述(起始点)。这里有一些算法如道格拉斯 - 普克算法可以帮助实现。3d层面中的图形都是一个个小三角构成的,三角形越多模型就会越精细,但有时为了性能可以减少三角形个数来优化。离屏 Canvas 预渲染。说白了把费时费力的性能开销扔给其他线程,不要阻塞主线程。将静态的折线背景绘制到 OffscreenCanvas(离屏画布),再复制到主 Canvas,避免每帧都重新计算 / 绘制静态内容;分块渲染。将 10 万条折线拆分成多个块,利用requestIdleCallback在浏览器空闲时逐块绘制,避免主线程阻塞。
-硬件加速 + 帧率控制。用 requestAnimationFrame 控制绘制帧率(固定 60FPS),开启 Canvas 的 GPU 加速(避免使用 fillText 等 CPU 密集型操作);
性能考量-svg
SVG 做复杂动画(如上千个图形的路径动画)时卡顿,又该如何优化?卡顿的本质:上千个 SVG 元素的动画会触发高频 DOM 重排 / 重绘、每个 SVG 元素都绑定了独立的动画监听 / 事件,内存占用高,GC 频繁。
方案:
动画属性优化:仅用 transform/opacity 做动画(这两个属性可触发 GPU 加速,不会触发重排),避免直接修改 x/y/d 等布局属性;减少 DOM 节点: 将多个小图形合并为单个path
最后顺带提一句,paperjs库的底层就是canvas,同时能够实现不失真的放大缩小及各类交互事件。基于 Canvas 却能做矢量图形,原因在于其矢量图形模型,就是用数学去模拟。
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
