html逐帧动画,CSS秘密花园: 逐帧动画

本文介绍了如何利用CSS和精灵图实现逐帧动画,详细解释了当传统CSS transition或animation无法满足复杂动画需求时,如何借助steps()时间函数创建逐帧效果。文章通过实例展示了如何解决GIF动画的局限性,如色彩限制和透明度问题,以及如何通过调整background-position和使用steps()代替平滑过渡来实现所需动画效果。
摘要由CSDN通过智能技术生成

《CSS Secrets》是@Lea Verou最新著作,这本书讲解了有关于CSS中一些小秘密。是一本CSSer值得一读的一本书,经过一段时间的阅读,我、@南北和@彦子一起将在W3cplus发布一系列相关的读后感,与大家一起分享。

e5f24a5009a75a71236f46a3b4696930.png

问题

通常,我们需要一个动画效果是比较难的或者说使用CSS的transition是不可能实现的。例如,一个卡通移动或一个复杂的进度条。在这种情况下,基于图像的逐帧动画是完美的,但是实现这种效果是具有挑战性的。

在这一点上,你可能会说:难道我们不能使用gif动画?很多情况下,答案是肯定的,gif动画是完美的。然而,他们也有一些缺点,可能在一些地方无法使用:

所有帧中被限制使用256色调色板

他们不能具有透明度,这是一个很大的问题。例如,下图所示的效果是很常见的。

在CSS中有些方面无法做修改,比如时间、重复和停顿等等。一旦生成gif文件,一切都存在文件中,只能通过一个图像编辑器来做修改或生成另一个文件。

f8d95c8f7781eefdab7d168728a8fda6.png

上图是一个半透明的进度指示器(dabblet.com),这个是Gif图无法实现的效果。

早在2004年,Mozilla团队就解决了前两个问题,他们通过逐帧动画PNG文件,实现类似静态的方式或者动画的GIF文件。他们把这种设计称为APNG。但是,直到今天,支持APNG的浏览器和制图软件都非常有限。

开发人员甚至通过使用一个Sprite图和使用JavaScript脚本来动态更改background-position值,在浏览器中实现灵活的逐帧动画。你甚至可以找到一个小的库来完成,那么有没有一个简单的方法,使用CSS来实现这样的效果呢?

解决方案

假设我们所有帧动画用到的Sprites的PNG图如下所示:

0cb41460c96e272c556b292f314a8457.png

我们有一个元素,用来制作加载动画(别忘了,在元素里面放些文本,提搞可访性!),元素大小是单帧动画的尺寸:

Loading...

.loader {

width: 100px;

height: 100px;

position: absolute;

top: 50%;

left: 50%;

transform: translate(-50%,-50%);

text-indent: 999px;

overflow: hidden;

background: url(http://www.w3cplus.com/sites/default/files/blogs/2015/1507/loader.png) 0 0;

}

目前结果如下图所示:

bd01e7079e3ac40d21ab5bc6eb1bb083.png

将显示的是第一帧,但是没有动画效果。如果我们对background-position进行不同值的设置,比如-100px,0是第二帧,-200px 0是第三帧等等。这样一来,首先想到的他可能是一个动画:

@keyframes loader {

to { background-position: -800px 0; }

}

.loader {

animation: loader 1s infinite linear;

/*省略其他样式*/

}

然而,正如下图所看到的图片(每167ms),这并不是真正需要的效果:

5a3be5ccaef90a098d1570b118c937eb.png

当我们不需要关键帧之间的插值时,我们最初尝试的逐帧动画效果失败了。

虽然我们还没有实现逐帧动画效果,但实际上我们已经非常接近解决方案。这里有一个秘密,将使用steps()时间函数来替代前面介绍的“Bézier-based”时间函数。

你可能会问,这是什么时间函数?正如上一节介绍的,我们看到的都是有关于“Bézier-based”时间函数来控制关键帧之间的平滑过渡。通常情况之下,在transition和animation都可以实现平滑过渡。然而,在这种情况这下,这种平滑过渡时间函数直接摧毁了我们使用Sprite制作的动画。

steps()时间函数和“Bézier-based”很不一样,他可以根据整个动画的关键帧步骤指定步骤的数量,并且可以对插值进行开关的设置。在CSS中,有关于steps()讨论不太多。至于CSS中有关于时间函数功能,“Bézier-based”才是亲妈的生,很受欢迎,但steps()是后妈的,一直不受人待。然而,在这种情况下,steps()才正是我们需要的。一旦把这个用到加载的动画中,动画才变得正常,也是我们需要的效果:

animation: loader 1s infinite steps(8);

请记住,steps()还可以接受第二个参数,而且这个参数是可选的。start或end(默认的),用来设定每个时间间隔开关,如下图所示:

3bbcaf39c932353ceff7d94585997ee9.png

如果我们只需要一个步骤,也可以通过step-start和step-end快捷键,其相当于steps(1,start)和steps(1,end)。

提示:Simurai给Sprites动画提供了一个使用steps()技术。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值