36

在过去的一周里,我一直在帮助一个朋友在浏览器中试验基于 SVG 的精灵表。我们想提出一个理想的工作流程来在浏览器中准备、发布和运行高质量的动画图形。因此,理想情况下,拥有适用于小型智能手机屏幕、平板电脑、视网膜显示器和桌面浏览器的单一动画数据源。

理论上,(基于矢量的)SVG 应该是理想的,但由于 SVG 通常不常用 - 我们决定对其进行测试。这个想法不是使用 SMIL SVG(因此没有基于 SVG 的动画),而是创建一个动画精灵表(就像您通常使用光栅数据 PNG/JPG 一样),而是使用纯矢量(即 SVG)来执行此操作。它有点大,但如果它可以工作 - 它甚至可以使用更优化的东西。

再加上逐帧矢量动画可以为我们的工作流程做很多事情——它允许我们使用 Flash 编辑器来制作动画,然后将它们导出到 SVG 精灵表。

无论如何,结果出奇地好,但在某些方面也失败了(请注意,出于测试目的,我们只使用基于 Webkit 的浏览器,即 Safari、Chrome、iOS 上的移动 Safari 和 Android ICS)。

在 CSS 中,为这样的精灵表触发硬件加速非常容易(至少在具有关键帧和步骤的现代浏览器中)——你只需这样做:

background-image: url(my.svg);
-webkit-animation: walk 1s steps(12, end) infinite; 

调用此处显示的基于关键帧的动画:

@-webkit-keyframes walk {
    from { -webkit-transform: translate3d(0, 0, 0); }
    to { -webkit-transform: translate3d(-100%, 0, 0); }          
}

在哪里使用 translate3d 应该让 GPU 启动,整个事情应该在 iOS 移动 Safari 和 Android ICS 浏览器中进行硬件加速。

考虑到它是一种蛮力技术和相当大的矢量动画(测试为 600x600px),这足以令人惊讶 - 整个事情都飞了。但它并不完美 - 它在起飞前会在 Safari 中闪烁。而且在 ICS 浏览器中它一直在闪烁,所以它不是真正可用的。

所以我们尝试了常用的技巧来消除闪烁,例如:

-webkit-transform: translateZ(0);    
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;

但这没有用。因此,我们尝试在内存中动态光栅化 SVG,并将其用作纹理-webkit-transform: scale3d(1, 1, 0)但这对以太没有帮助。

最后,我们只是用相同大小的渲染出来的 PNG/JPG 精灵表替换了 SVG,认为复杂的矢量对浏览器来说太多了 - 但你猜怎么着?它是同样的问题 - 所以它根本不是 SVG 渲染 -它是一个浏览器绘图问题。进一步的证明是,如果我们将动画减慢到 1FPS - 闪烁仍然存在。

图像对于 GPU 来说太大了吗?我们是否已达到您能够在浏览器(尤其是移动设备)中轻松绘制/动画的性能极限?

我真的很感激关于如何潜在地摆脱闪烁的想法/黑客(特别是因为它的表现如此之快)。它只是一种有前途的技术——适应不同屏幕尺寸的高性能浏览器动画——HTML5 圣杯;)

通过一些优化,例如

<svg preserveAspectRatio="xMinYMax slice" viewBox="0 0 600 50">

还有一些 CSS 魔法,我们能够让 SVG 完美地适应它的容器,并从单个 CSS 类改变它的大小。它真的会创造奇迹 - 但可惜闪烁。

无论如何 - 请在此处阅读更多相关信息,您也可以尝试一下

4

2 回答 2

3

很酷的想法。

如何更改帧的 zindex 以便将图像分层?这可能会解决闪烁问题,因为在重绘期间最后一帧仍然可见。因此,您只需不断增加最新帧的 zindex 值即可。当然,这是有限制的,您需要再次重置 zindex,但这可能会对减少闪烁产生很大影响。

于 2012-10-16T13:46:31.760 回答
1

我这里没有 ICS 来检查它,但是在 iPhone 5 上的 iOS 6 和 Galaxy Nexus 上的 Jelly Bean 4.1.1 上,动画看起来非常流畅,除非我缩放时,此时我会看到一些闪烁的帧然后它又安定下来了。

这让我想起了一个类似的问题,我在大画布上进行渲染并在屏幕周围进行转换(在任何给定时间,大部分画布都在屏幕外)。

我当时的黑盒分析表明这是一些优化,浏览器不会费心渲染屏幕外的内容,而是等到它变得可见,这完全违背了拥有大图像和硬件加速它的目的。

我的“解决方案”是 -webkit-transform:将整个图像缩小到足够小以确保它全部适合屏幕(因此浏览器别无选择,只能渲染整个图像),让它渲染,然后将其放大到我想要的尺寸。

(顺便说一句:为了对用户隐藏这个hackery,我最初尝试设置 opacity: 0 以便预渲染不可见,但似乎这与离屏渲染具有相同的效果 - 它已被优化。在最后,我将不透明度设置得非常低,并用几乎不透明的“加载”消息覆盖它,这意味着肉眼看不到背景渲染,但浏览器没有绝对可见/不可见的优化。不确定这是否有点矫枉过正,但它似乎适用于我的设置。)

我很想知道类似的技术是否适合您。

于 2012-11-03T22:29:48.477 回答