CSS动画属性关键帧keyframes全解析

大概有多久没有更新专栏文章了。半年?下半年忙到起飞,或者绝不夸张的说是发射?仅有的一点我的时间,上半年贡献给了Python,如今差很少已忘掉了七七八八(一首《凉凉》送给本身),下半年贡献给了JavaScript,终于鼓起勇气系统的开始学习JS了(换台,梁静茹《勇气》走起)。原本想一直等等等,等到webapi学完后放个大招,svg+CSS动画搭乘上JavaScript简直如虎添翼长驱直入。可是,看掘金做者群里讨论的风生水起,忽然感受本身全然是陌生人(此处应放蔡健雅?),因此,更一篇文章刷一下存在感。css

这篇文章原本是写的《SVG+CSS动画》小册中的一个小节选,小册由于各类莫名的缘由,搁浅了,搁浅……起航时间遥遥无期,但keyframes关键帧做为控制动画在不一样时间的状态的重要元素,决定了七十二变的终极形态,因此此次更新专栏拿它下手。至于小册嘛,若是能发的话,里面再换成其余的案例就好,此为后话。web

关键帧keyframes的基础概念此处可省略,下面才是满满的干货。api

案例:一路向前永不停歇的圆

由于只是来解释关键帧,因此只搞了一个简易的仅水平位移的动效。所以,这篇文章得以脱离SVG单独存在仅和CSS3动画属性相关。浏览器

这是一个努力从起点滚向终点的圆圈,整个路程为800px,但我在它的必经之路的三处设置了三个驿站。如今就要经过关键帧的定义让圆圈在行进的路上进入驿站并稍做停顿。

1.先来一个最基础的

CSS部分定义一个最基础的位移动画,4s完成,线性速度case-关键帧演示1-基础svg

@keyframes  move{
0%{transform:translateX(0)}
100%{transform:translateX(800px)}
}
.c_move{animation:move 4s linear both} /*both:运动结束后停留在终点*/
复制代码

这个发挥做用主要是在定义了无限循环动画时。学习

基础的设置天然带来毫无特点平淡无奇的基础动效。动画

2.延迟开始(扔掉animation-delay属性)

下面,我想让圆圈在起点停留2s后再开始移动,第一反应是用动画属性中的延迟animation-delay,把时间定义成2s,行不行?行,但这里用个更高级的方法。咱们在定义关键帧时用了大量的百分比,这里百分比值表明的是时间节点,也就是说关键帧定义的是不一样时间节点的状态属性。 下面再来看一张图,这张图必定不要和上面的路径演示弄混了,这是一张动画的时间轴的图。ui

让圆圈在起点停留2s那是表象说法,转化成咱们的动画定义语言,就是在4s动画周期内前2s是没有动画效果的。因此,动画规则我来这样定义:

@keyframes  move{
0%{transform:translateX(0)}
50%{transform:translateX(0px)}
100%{transform:translateX(800px)}
}
复制代码

对照上面时间轴的分割来看,更容易理解一些,这样就获得了在起点处停留2s后,在后面的2s完成整个动画的动效。这里亦或用一种更简单的写法为0%, 50%{transform:translateX(0)},属性相同的能够合并在一块儿,用逗号分隔。case-关键帧演示-延迟开始spa

因此,从如今开始,扔掉animation中的动画开始时间属性animation-dalay吧,经过keyframes的时间定义彻底能够完美来取代它,并没有差的参与循环。

3.提早结束

有了延迟开始的基础,提早结束是否是已经能够类推出来了。为了区分一下,我让动画提早3s结束。照例先画出时间轴的解析。设计

对应关键帧的定义以下:

@keyframes  move{
0%{transform:translateX(0)}
25%,100%{transform:translateX(800px)}
}
复制代码

最终结果圆圈必定是4倍速度尽心尽力加速完成旅程(毕竟要把原来4s的时间压缩到1s完成),而后悠然自得的在终点等待整个动画时间结束。case-关键帧演示-提早结束

4.中途停留

那些已准备稳当的驿站,如今能够发挥做用了,我但愿圆圈这样运动:整个旅程中仅在第一个驿站(移动200px后)停留1s,稍做整顿。映射到时间轴上是什么样子的呢?

这里,出现了一些看上去很奇怪的数字,须要解释一下。先来明确一点,咱们分析时间轴,最终要得到是时间节点。针对咱们的设计,停留1s,那运动的时间就是3s,而这3s的时间是分红两部分的,第一部分是前200px,第二部分是后600px,由于是线性匀速,因此当时间轴分红A+B+C三部分后,在A时间段跑完200px,在C时间段跑完600px,计算出A对应的时间0.75s,C对应的时间2.25s,B的时间是停留的时间1s,再换算成对应的百分比,这就是最终中间两个时间节点的计算方法。时间轴解析完成后,CSS部分的定义手到擒来:

@keyframes  move{
0%{transform:translateX(0)}
18.75%, 43.75%{transform:translateX(200px)} /*对应停留的1s*/
100%{transform:translateX(800px)}
}
复制代码

case-关键帧演示-第一个驿站停留1s

5.像虫洞同样跳跃式前进

增长些难度,在中途任意点做停留已经不是什么问题了,停留在一个点和多个点是相同的思路,如今,我让圆圈跳跃式前进,进入第一个驿站后,停留1s,跨过第二个驿站,直接进入第三个驿站,停留1s,完成旅程。根据空间折叠原理,200和600处发生了跃迁。分析时间轴:

重点看红色的部分,那里就是跃迁的时间点,在无时间变化的状况下位移了200px。按照时间轴的分析,CSS部分理论上是这样的:

@keyframes  move{
0%{transform:translateX(0)}
25%,50%{transform:translateX(200px)}
50%,75%{transform:translateX(600px)}
100%{transform:translateX(800px)}
}
复制代码

效果如何呢?

彻底和想象的不同,问题出在哪里呢?就是时间的50%节点处,浏览器可不知道你真实的想法,它只会觉得你定义错了,当有两个相同的50%的关键帧的不一样属性值定义时,会自动忽略第一个,而以最后一个有效值为准,因此上面的定义至关于给浏览器传达的讯息是这样的:

@keyframes  move{
0%{transform:translateX(0)}
25%{transform:translateX(200px)}
50%,75%{transform:translateX(600px)} /*在位移600px后停留1s*/
100%{transform:translateX(800px)}
}
复制代码

这就是为何看上去是到达第一驿站后加速跑向第三个驿站,而后停留后再完成剩下的路程的缘由。如今游戏愈来愈有意思了,或许咱们能够试试骗过浏览器。既然一样的时间点只容许定义一个属性值,那若是我在紧邻的旁边增长一个时间点来定义,会发生什么?

@keyframes  move{
0%{transform:translateX(0)}
25%,50%{transform:translateX(200px)}
50.0001%,75%{transform:translateX(600px)} 
100%{transform:translateX(800px)}
}
复制代码

看上面出现的50.0001% 这个时间点,猜猜发生了什么?这就是上面所谓的“骗过浏览器”的方法了。在50%→50.0001%这个区间,发生了400px(200→600)的位移变化。因此就获得了下面这种效果:case-关键帧演示-跃迁

从原理上来说,这是一种视觉欺骗,在极短的时间内在两个位置间发生位移,由于时间短到能够忽略,因此会有一种跳跃的假象。

总结

看完上面的几种表明性实例,是否是对关键帧的定义有了一个全新的认识,你可能会以为对于“延迟开始”和“提早结束”这两种需求,是彻底能够经过定义延迟时间以及动画周期的时间来达到相同的效果的,可是,对于一个无限循环的动效而言,延迟开始永远只做用一次,当动画一旦开始进入周而复始的循环后,再也不支持这个属性设置。所以,若是能够的话,尽可能用关键帧的定义来完成。

敲黑板,划重点

对于关键帧,最重要的是时间节点,而最好的方法,就是粗略绘制一个时间轴,把事件按照顺序依次映射到时间轴上。

相关文章
相关标签/搜索