翻译:疯狂的技术宅原文:http://jakearchibald.com/2017…
本文首发微信公众号:jingchengyideng 欢迎关注,每天都给你推送新鲜的前端技术文章
渲染 SVG 图像可能会非常慢
在转换 SVG 图像时,浏览器会试着在每一帧上进行渲染,以便使图像尽可能的清晰。不幸的是,SVG 渲染可能会很慢,特别是对于较大的图像。
这里是一个 DEMO,打开后点击“Scale SVG”查看效果。
图:使用 Devtools 查看 SVG 动画的时间线
这是一个非常复杂的 SVG,在某些帧上消耗的时间是我们帧预算的 10 倍,所以这个动画看起来非常糟糕。这是在一款功能强大的 MacBook 上做的测试。
如果是更简单的 SVG,就不那么糟了。这是用 Firefox 的 logo 演示的另一个例子,看起来效果还可以。
不过新 API 为我们提供了更多的控制方法:
SVG 栅格化的惰性处理
createImageBitmap(imgElement).then(imageBitmap => {
// …
});
createImageBitmap 可以将许多不同的图像栅格化为位图数据,这些数据可以绘制到 canvas 元素上。但是,在 Chrome 61+ 中,启用了 chrome://flags/#enable-experimental-canvas-features,它可以为 SVG 图像启用 HTML 图像元素,并在主线程之外进行异步的栅格化处理,所以不会破坏动画。
另外你还可以只渲染 SVG 的一部分,并以特定大小进行输出:
createImageBitmap(
imgElement,
sourceCropX, sourceCropY,
sourceCropWidth, sourceCropHeight,
{resizeWidth, resizeHeight}
).then(imageBitmap => …);
这允许我们非常方便的使用画布对 SVG 进行位图缩放,同时渲染被裁剪后且非常清晰的版本。一旦清晰版准备就绪,就可以将其包含在动画中。
这里是一个 DEMO,按“Scale canvas”查看效果。需要 Chrome 61+ 中查看,并启用 chrome://flags/#enable-experimental-canvas-features。
图:Devtools 中画布动画的时间线
使用这种方法对 CPU 来说更加友好,动画也很流畅:
查看 SVG 动画与 SVG-in-canvas 两种效果比较的视频演示:https://youtu.be/-yQBbWlXuqg
对于复杂的汽车 SVG 图像,最后才会出现清晰的图像。使用 Firefox 徽标时,清晰版出现得更早,因为渲染时间更短。
DEMO 的所有代码:https://glitch.com/edit/#!/sv…:1:0
平滑光栅化
从上面的时间线可以看出,Chrome 在将更清晰的纹理传到 GPU 时仍然会跳过一帧。这个问题可以通过将工作分块为更小的块来解决,因此 GPU 上传不会破坏帧预算。
OpenSeadragon:可以动态加载图像切片,并创建可缩放图像。它非常适合从网络中获取位图数据,但有点 hack。
Zoomable lazy-rendered tiled SVG:需要 Chrome 61+ 并启用 chrome://flags/#enable-experimental-canvas-features。
是的,边缘有一点粗糙。就像我前面说的那样,这是一个 hack。不过我真的对此很兴奋,对 SVG 图像更加酷炫的处理技术在逐渐用于 web。
本文首发微信公众号:jingchengyideng
欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章