先解决上一篇的遗留问题。
div { width: 300px; height: 200px; background-color: red; -webkit-animation: test1 2s; } @-webkit-keyframes test1 { from {background-color: green;} to {background-color: red;} }
这样定义的动画,实际情况是只跑一次,无论鼠标悬浮还是移出都不会再次启动动画。
why?因为transition和animation的工作模式是不同的,transition可以理解为监听器,一旦触发即启动。而animation则可以理解为命令,当时有效,执行完后作废,除非再下命令。
那这样是否有效呢?
div { width: 300px; height: 200px; background-color: red; -webkit-animation: test1 2s; } div:hover { -webkit-animation: test1 2s; } @-webkit-keyframes test1 { from {background-color: green;} to {background-color: red;} }
结果还是无效,但是
div { width: 300px; height: 200px; background-color: red; -webkit-animation: test1 2s; } div:hover { -webkit-animation: test2 2s; } @-webkit-keyframes test1 { from {background-color: green;} to {background-color: red;} } @-webkit-keyframes test2 { from {background-color: green;} to {background-color: red;} }
这样就有效了。
上面两个例子的区别说明了:
- animation执行完后不是作废了,而是处于end的状态
- 状态跟随animation-name,只有animation-name改变时,状态才初始化
好了,弄清楚了animation和transition最核心的区别,然后来看animation中的所有属性。用上一篇的代码作为初始代码:
div { width: 300px; height: 200px; background-color: red; -webkit-animation: test1 2s forwards; } div:hover { -webkit-animation: test2 2s forwards; } @-webkit-keyframes test1 { from {background-color: green;} to {background-color: red;} } @-webkit-keyframes test2 { from {background-color: red;} to {background-color: green;} }
animation同样是很多属性的缩写:
- animation-name: 对应keyframes的name,keyframes的定义遵循 percentage {css property...},其中from为0%,to为100%
div { width: 300px; height: 200px; background-color: red; -webkit-animation: test1 2s forwards; } div:hover { -webkit-animation: test2 2s forwards; } @-webkit-keyframes test1 { from {background-color: green; width: 500px;} to {background-color: red; width: 300px;} } @-webkit-keyframes test2 { from {background-color: red; width: 300px;} to {background-color: green; width: 500px;} }
与transition表现不同的是,当动画进行的中途改变鼠标悬浮/移出的状态时,元素会先切换到最终的状态也就是新动画初始的状态再执行新动画。而不像transition一样平滑以当前的状态作为开始状态执行新动画。这是因为animation与元素当前的状态毫无关联,只按照keyframes的定义执行动画,而transition只以状态的改变触发的,所以跟元素当前的状态关联密切。
- animation-duration: 动画执行的时间。
- animation-timing-function: 动画执行的方式。
- animation-delay: 动画延迟执行的时间。
以上三个同transition,可以看出两者的设计思想是类似的,但animation无疑更复杂,因为它还有 - animation-iteration-count: number | infinite 动画执行的次数n,当然总时间就是animation-durationn * n了
div { width: 300px; height: 200px; background-color: red; -webkit-animation: test1 2s forwards 2; } div:hover { -webkit-animation: test2 2s forwards 2; } @-webkit-keyframes test1 { from {background-color: green;} to {background-color: red;} } @-webkit-keyframes test2 { from {background-color: red;} to {background-color: green;} }
页面加载时元素由绿慢慢变红,然后立即变绿,最后再次慢慢由绿变红,动画进行了两次,但立即变绿很不平滑。这就要看下面这个属性
- animation-direction: normal(default) / alternate: 当执行次数为偶数时,反转关键帧进行动画
div { width: 300px; height: 200px; background-color: red; -webkit-animation: test1 2s forwards 3 alternate; } div:hover { -webkit-animation: test2 2s forwards 3 alternate; } @-webkit-keyframes test1 { from {background-color: green;} to {background-color: red;} } @-webkit-keyframes test2 { from {background-color: red;} to {background-color: green;} }
元素由绿慢慢变红,然后由红慢慢变绿,最后由绿慢慢变红,动画进行了三次,而且都很平滑。
- animation-fill-mode: 定义动画启动前的delay时间内,和动画完成后的时间内元素的CSS属性。none(default) delay时间内和完成后都使用元素本来的样式,与keyframes毫无关联 | forwards delay时间内使用本来的样式,完成后使用最后一帧的样式 | backwards delay时使用第一帧的样式,完成后使用本来的样式 | both delay时间内和完成后分别使用第一帧和最后一帧的样式
div { width: 300px; height: 200px; background-color: red; /* 将none分别替换成forwards、backwards、both */ -webkit-animation: test1 2s 2s none; } @-webkit-keyframes test1 { from {background-color: blue;} to {background-color: black;} }
- animation-play-state: 规定动画暂停或运行 running(default) | paused 暂停动画。比如先定义动画,然后想在鼠标悬浮的时候再执行。
div { width: 300px; height: 200px; background-color: red; -webkit-animation: test1 2s forwards paused; } div:hover { -webkit-animation-play-state: running; } @-webkit-keyframes test1 { from {background-color: red;} to {background-color: green;} }
还有,animation emit的事件比transition多一个。
总共有三个事件:
- animationstart: 动画正式开始,要等delay的时间过去
- animationend: 动画正式结束,所有animation-iteration-count执行结束
- animationiteration: 动画重新播放时
这三个事件没有被浏览器支持,取而代之是webkit下的webkitAnimationStart、webkitAnimationEnd、webkitAnimationEnd(注意大写字母)。简单的实现如下:
(function setup() { var e = document.getElementsByTagName("div")[0]; e.addEventListener("webkitAnimationStart", listener, false); e.addEventListener("webkitAnimationEnd", listener, false); e.addEventListener("webkitAnimationIteration", listener, false); })(); function listener(e) { var l = document.createElement("li"); switch(e.type) { case "animationstart": case "webkitAnimationStart": console.log("animation start"); break; case "animationend": case "webkitAnimationEnd": console.log("animation end"); break; case "animationiteration": case "webkitAnimationIteration": console.log("animation restart"); break; } }
以上。