美文网首页让前端飞
css技巧:逐帧动画抖动如何解决?

css技巧:逐帧动画抖动如何解决?

作者: 子瑜说IT | 来源:发表于2019-03-29 20:51 被阅读3次

一个抖动的例子

做一个8帧的逐帧动画,每帧的尺寸为:360x540。


image.png

观察在主流(手机)分辨率下的播放情况:

|iPhone 6(375x667) iPhone 6+ (414x736) iPhone 5 (320x568) Android (360x640)

四种分辨率下,可以看到除了iP6 其它的三种分辨率都发生了抖动。(iP6 不抖动的原因是适配方案是基本于 iP6 的分辨率订制的。)

分析抖动

图像由终端(屏幕)显示,而终端则是一个个光点(物理像素)组成的矩阵,换句话说图片也一组光点矩阵。为了方便描述,笔者假设终端上的一个光点代表css中的1px。

以下是一张 9px * 3px 的sprite:

9px * 3px

每帧的尺寸为 3px * 3px,逐帧的取位过程如下:

9px * 3px

把 sprite 的 background-size 的宽度取一半,那么终端会怎么处理?
9 / 2 = 4.5
终端的光点都是以自然数的形式出现的,这里需要做取整处理。取整一般是三种方式:round/ceil/floor。假设是 round ,那么 background-size: 5px,sprite 会是以下三种的一个:

image.png
理论上,5 / 3 = 1.666...。但实际上光点取整后,三个帧的宽度都不可能等于 1.666...,而是有一个帧的宽度降级为 1px(亏),另外两个宽度升级为 2px(盈),笔者把这个现象称作「盈亏互补」。

再看一下盈亏互补后,逐帧的取位过程:

image.png
可以看到由于盈亏互补导致了三个帧的宽度不一致,亏的那一帧在动画中的表示就是抖动

个人总结抖动的原因是:sprite在尺寸缩放后,帧与帧之间的盈亏互补现象导致动画抖动

附注:1px 由几个光点表示是由以终端的 dpr 决定

解决方案

「盈亏互补」也可以说是「盈亏不一致」,如果尺寸在缩放后「盈亏一致」那么抖动现象可以解决。

解决构想一

根据「盈亏一致」设计了「解决构想一」:

image.png
根据上图,其实很容易就联想到一个简单的方案:不用雪碧图(即一帧对应一张图片)
这个方案确实是可以解决抖问题,不过笔者并不推荐使用它,因为它有两个负面的东西:
  • KB变大与请求数增多
  • 多余的 animation 代码

这个方案很简单,这里就不赘述了。

解决构想二

把逐帧取位与图像缩放拆分成两个独立的过程,就是我的「解决构想二」:


image.png

实现「构想二」,我首先想到的是使用 transform: scale(),于是整理了一个实现方案A:


image.png
这个实现方案A存在明显的缺陷:scale 的值需要写很多断点代码。于是笔者结全一段 js 代码来改善这个实现方案B:

css:


image.png

javascript:


image.png
通过改善后的方案 CSS 的断点没了,感觉是不错了,不过我觉得这个方案不是个纯粹的构建方案。

我们知道 <img> 是可以根据指定的尺寸自适应缩放尺寸的,如果逐帧动画也能与 <img> 自适应缩放,那就可以从纯构建角度实现「构想二」。

SVG刚好可以解决难题!!!SVG 的表现与 <img> 类似同时可以做动画。以下是我的实现方案C。

html:


image.png

css:


image.png

方案C的改良

实现方案C很好地解决了方案A和方案B的缺陷,不过方案C也有它的问题:不利于自动化工具去处理图片

自动化工具一般是怎么处理图片的?
自动化工具一般是扫描 CSS 文件找出所有的 url(...) 语句,然后再处理这些语句指向的图片文件。

如果 <image> 可以改用 CSS 的 background-image 就可以解决这个问题,不过 SVG 不支持 CSS 的 background-image。但是,SVG有一个扩展标签:foreignObject,它允许向 <svg></svg> 插入 html 代码。在使用它前,先看一下它的兼容情况:

caniuse

iOS 与 Android 4.3 一片草绿兼容情况算是良好,实机测试腾讯 X5 内核的浏览器兼容仍旧良好。以下是改良后的方案。

html:

image.png
css:
image.png
改良后的方案DEMO: http://jdc.jd.com/fd/promote/leeenx/201708/svg-sprite.html

结语

感谢阅读完本文章的读者。本文是个人观点,希望能帮助到有相关问题的朋友,如果本文有不妥之处请不吝赐教。

我是一名前端工程师,自己整理了一份2019最全面前端学习资料,从最基础的HTML+CSS+JS到移动端HTML5到各种框架都有整理,送给每一位前端小伙伴,这里是小白聚集地,欢迎初学和进阶中的小伙伴从最基础的HTML+CSS+JS到移动端HTML5到各种框架都有整理,送给每一位前端小伙伴,这里是小白聚集地,欢迎初学和进阶中的小伙伴web前端资料分享圈

相关文章

  • css技巧:逐帧动画抖动如何解决?

    一个抖动的例子 做一个8帧的逐帧动画,每帧的尺寸为:360x540。 观察在主流(手机)分辨率下的播放情况: 四种...

  • css逐帧动画

    我们经常使用css3中的animation动画,比如这样: 这样就实现了延时1s,一共0.5s的淡入动画。其中ea...

  • css3 animation 动画

    css3 steps 逐帧动画------https://www.cnblogs.com/liulangmao/p...

  • Android 动画总结

    Android 中的动画可以分为以下几类: 逐帧动画 补间动画 属性动画 一、逐帧动画 逐帧动画的原理就是让一系列...

  • 安卓动画

    Android 中的动画可以分为以下几类: 逐帧动画 补间动画 属性动画 1、逐帧动画 逐帧动画的原理就是让一系列...

  • Android动画

    文章脑图 1、Android动画种类 逐帧动画、补间动画、属性动画 逐帧动画 逐帧动画的原理就是让一系列的静态图片...

  • Android 动画

    Android中动画分为三种: 逐帧动画 补间动画 属性动画 逐帧动画 逐帧动画类似于gif或是电影的原理,通过将...

  • Android动画之逐帧动画FrameAnimation

    1 逐帧动画介绍 视图动画由两部分组成,补间动画和逐帧动画,前面文章已经讲解了补间动画,下面讲解逐帧动画。Fram...

  • Android 动画机制(一)

    逐帧动画(Frame Animation) 逐帧动画也叫Drawable Animation,是最简单最直...

  • Android 动画锦集

    Android 动画可分为逐帧动画、补间动画、属性动画。使用传统的逐帧动画、补间动画可以实现 Android 基本...

网友评论

    本文标题:css技巧:逐帧动画抖动如何解决?

    本文链接:https://www.haomeiwen.com/subject/tfvrbqtx.html