Heim >Web-Frontend >HTML-Tutorial >CSS秘密花园: 逐帧动画_html/css_WEB-ITnose

CSS秘密花园: 逐帧动画_html/css_WEB-ITnose

WBOY
WBOYOriginal
2016-06-21 08:51:09835Durchsuche

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

问题

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

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

  • 所有帧中被限制使用256色调色板
  • 他们不能具有透明度,这是一个很大的问题。例如,下图所示的效果是很常见的。
  • 在CSS中有些方面无法做修改,比如时间、重复和停顿等等。一旦生成gif文件,一切都存在文件中,只能通过一个图像编辑器来做修改或生成另一个文件。

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

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

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

解决方案

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

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

<div class="loader">Loading...</div>.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;}

目前结果如下图所示:

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

@keyframes loader {    to { background-position: -800px 0; }}.loader {    animation: loader 1s infinite linear;    /*省略其他样式*/}

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

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

虽然我们还没有实现逐帧动画效果,但实际上我们已经非常接近解决方案。这里有一个秘密,将使用 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 (默认的),用来设定每个时间间隔开关,如下图所示:

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

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

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn