CSS 动画

CSS 中的 transformtransitionanimation 是分开的三部份内容,其中 transfrom 主要是控制元素变形,并无一个时间控制的概念,而 transitionanimation 才是动画的部分,它们能够控制在一个时间段里,元素在两个或以上的状态切换的效果。css

基本上咱们会有这样的一个简单的概念,CSS 的动画效果由浏览器控制和渲染,理论上比 JavaScript 的动画效果性能好,可是控制上没有 JavaScript 那么灵活方便。html

迪士尼出版的一本书中说起了动画效果的十二个原则,这篇文章讲解得比较详细,而且将其结合到页面动画中:网页动画的十二原则css3

transition

transition 容许咱们在 CSS 属性变化时给它添加一个过分的动画效果。一般状况下,CSS 属性变化是当即生效的,新的属性值在超级短的时间内替换掉旧的属性值,而后浏览器从新绘制样式内容(多是 reflow 或者 repaint)。大部分状况下会感受样式变化突兀,而 transition 则能够添加顺滑的一个变化效果。例如:git

.content {
  background: magenta;
  transition: background 200ms ease-in 50ms;
}

.content:hover {
  background: yellow;
  transition: background 200ms ease-out 50ms;
}

transition 的兼容性,不算差,基本上移动设备均可以使用了,而且能作到渐进加强,支持的便有过渡效果,不支持的即是直接切换,因此能够放心使用。github

transition 属性

CSS 的 transition 有四个属性:web

  • transition-delay 延迟多久后开始动画算法

  • transition-duration 过渡动画的一个持续时间chrome

  • transition-property 执行动画对应的属性,例如 colorbackground 等,可使用 all 来指定全部的属性浏览器

  • transition-timing-function 随着时间推动,动画变化轨迹的计算方式,常见的有:linear,ease,ease-in,ease-out,cubic-bezier(...) 等。详细参考:transition-timing-function,里边有各个效果的简单例子。网络

这四个属性能够简写成为:

.class {
  transition: <property> <duration> <timing-function> <delay>  
}

例如前边的那个例子,当 .content 元素 hover 时,50 毫秒后背景颜色从 magenta 渐变到 yellow,持续时间 200 毫秒,使用的是 ease-out 的算法。留意下:transition 生效的是对应的选择器的属性,例如 .content:hover 中的 transition 即是从 .content 的 magenta 到 yellow 过渡效果的控制,而 .content 中的 transition 则是控制不 hover 时,背景颜色从 yellow 到 magenta 的变化过程。

all 这个属性值是这样的,它对应选择器下的元素的全部 CSS 属性生效,不管在哪里声明的 CSS 规则,并不局限于在同个代码块下。

若是须要不一样属性对应不一样的效果,能够这么来写:

.demo {
  transition-property: all, border-radius, opacity;
  transition-duration: 1s, 2s, 3s;
  /* 当这样使用时,确保 all 在第一个,由于若是 all 在后边的话,它的规则会覆盖掉前边的属性 */
}

transitionnone 属性较少用到,通常用于移除本来有的动画效果。none 无法和逗号一块儿使用来移除特定属性的动画效果,只能直接干掉 transition,若是要移除特定的属性效果,能够重写 transition 而不把要移除的属性写进去,或者比较 trick 的作法是设置 duration 为 0。

并非全部的 CSS 属性都是能够添加 transition 效果的。详细能够参考文档:animatable properties。可能常常遇到的就是 display 这个属性并不能添加 transition 效果,你能够考虑使用 visibility 或者后边会说起的 animation

关于 transition-timing-function 的各个算法的一个变化曲线是怎么样的,咱们可使用 chrome 的开发者工具来看一下,CSS 中你编写了对应的 transition 后,把鼠标移到 transition-timing-function 的那个值前边,以下图:

Timing function

这样你即可以很清晰地看到这个算法的一个变化轨迹是怎么用的,而后选择符合本身须要的一个算法。

transition 相关的事件

transitionend 事件会在 transition 动画结束的时候触发。一般咱们会在动画结束后执行一些方法,例如继续下一个动画效果或者其余。Zepto.js 中的动画方法都是使用 CSS 动画属性来处理,而其中动画运行后的回调便应该是使用这个事件来处理。

transitionend 事件触发时会传入一些动画相关的参数,例如:propertyNameelapsedTime,详细内容能够参考:transitionend

transition 应用

transition 在不少 UI 框架中是很常见的属性,当咱们开发一个交互效果的时候,从某个状态到达另一个状态时,transition 可使得这个过程变得更加温馨和顺滑。例如上边的 hover 时的背景颜色的切换,控制元素的显示和隐藏时使用 opacity 来实现渐隐渐现。

transition 配合上 transform 提供的多样化的元素变化能力后,即可以绘制出不少有趣的交互渐变效果了。最近使用过程当中作的一个简单效果的例子,点击查看

很常见还有表单 input 报错时边框变红,按钮 hover 时背景渐变等,不少的 CSS 交互效果会由于 transition 变得更加天然。

animation

虽然 transition 已经提供了很棒的动画效果了,可是咱们只可以控制从一个状态到达另一个状态,无法来控制多个状态的不断变化,而 animation 而帮助咱们实现了这一点。使用 animation 的前提是咱们须要先使用 @keyframes 来定义一个动画效果,@keyframes 定义的规则能够用来控制动画过程当中的各个状态的状况,语法大抵是这个样子:

@keyframes W {
  from { left: 0; top: 0; }
  to { left: 100%; top: 100%; }
}

@keyframes 关键词后跟动画的名字,而后是一个块,块中有动画进度的各个选择器,选择器后的块则依旧是咱们常见的各个 CSS 样式属性。

在这里,控制动画的整个过程的选择器很重要,语法相对简单,你可使用 from 或者 0% 来表示起始状态,而 to100% 来表示结束状态。中间的部分你均可以使用百分比来进行表示。选择器后的块则是在到达这个进度状态时元素的样式应该是怎么样的,整个的过渡动画在这个的控制基础上由浏览器去绘制。

一样地,不是全部的属性均可以有动画效果,MDN 维护了一份 CSS 动画的属性列表 可供参考。

一般来讲,多个状态下的相同属性的值应该是能够取到它们的中间值的,例如 left 从 0% 到 100%,若是无法取到中间值,如 height 从 auto 到 100px,有可能出现奇怪的一些情况,而且不一样浏览器对此的处理也不尽相同,因此请尽可能避免这种状况。

animation 属性

animation 的属性比 transition 多,以下:

  • animation-name 你须要的动画效果的 @keyframes 的名字。

  • animation-delaytransition-delay 同样,动画延迟的时间。

  • animtaion-durationtransition-duration 同样,动画持续的时间。

  • animation-direction 动画的一个方向控制。
    默认是 normal,若是是上述的 left 从 0% 到 100%,那么默认是从左到右。若是这个值是 reverse,那么即是从右到左。

因为 animation 提供了循环的控制,因此还有两个值是 alternatealternate-reverse,这两个值会在每次循环开始的时候调转动画方向,只不过是起始的方向不一样。

例如仍是 left 的例子,假设设置了 animation-direction: alternate; animation-iteration-count: infinite;,那么这个元素从左到右移动后,便调转方向,从右到左,如此循环。

  • animation-fill-mode 这个属性用来控制动画先后,@keyframes 中提供的 CSS 属性如何应用到元素上。
    默认值是 none,还有其余三个选择:forwardsbackwardsboth

假设是 none,那么动画先后,动画中声明的 CSS 属性都不会应用到元素上。即动画效果执行后,元素便恢复正常状态。

若是是 forwards,那么动画结束后,会把最后状态的 CSS 属性应用到元素上,即保持动画最后的样子。而 backwards 则相反,both 则都会,计算得出最后的一个结果。

  • animation-timing-functiontransition-timing-function 同样,动画变化轨迹的算法。

  • animation-iteration-count 动画循环次数,若是是 infinite 则无限次。有趣的是,支持小数,即 0.5 表示动画执行到一半。

  • animation-play-state 动画执行的状态,两个值 running 或者 paused,能够用来控制动画是否执行。

上述这些属性能够简写为:

.class {
  animation: <duration> <timing-function> <delay> <iteration-count> <direction> <fill-mode> <play-state> <name>
}

略长,固然,平时使用中多是省略部分参数的。

animation 须要留意的东西

优先级

记得 CSS 中的层叠概念么,优先级高的属性会覆盖优先级低的属性,当 animation 应用到元素中时,动画运行过程当中,@keyframes 声明的 CSS 属性优先级最高,比行内声明 !important 的样式还要高。如今浏览器的实现是这样子的,可是标准文档中的说法应该是能够被 !important 声明的属性所覆盖。

多个动画的顺序

因为 animation-name 是能够指定多个动画效果的,因此这里便会出现动画的一个顺序问题。后指定的动画会覆盖掉前边的,例如:

#colors {
  animation-name: red, green, blue; /* 假设这些 keyframe 都是修改 color 这个属性 */
  animation-duration: 5s, 4s, 3s;
}

上述代码的动画效果会是这样:前 3 秒是 blue,而后接着 1 秒是 green,最后 1 秒是 red。整个覆盖的规则是比较简单的。

display 的影响

若是一个元素的 display 设置为 none,那么在它或者它的子元素上的动画效果便会中止,而从新设置 display 为可见后,动画效果会从新重头开始执行。

animation 相关事件

咱们能够经过绑定事件来监听 animation 的几个状态,这些事件分别是:

  • animationstart 动画开始事件,若是有 delay 属性的话,那么等到动画真正开始再触发,若是是没有 delay,那么当动画效果应用到元素时,这个事件会被触发。

  • animationend 动画结束的事件,和 transitionend 相似。若是有多个动画,那么这个事件会触发屡次,像上边的例子,这个事件会触发三次。若是 animation-iteration-count 设置为 infinite,那么这个事件则不会被触发。

  • animationiteration 动画循环一个生命周期结束的事件,和上一个事件不同的是,这个在每次循环结束一段动画时会触发,而不是整个动画结束时触发。无限循环时,除非 duration 为 0,不然这个事件会无限触发。

animation event 相关的属性能够参考:animationEvent

animation 应用

animation 能够实现控制在多个状态下进行动画切换,因此应用的场景比 transition 要普遍得多,可使用 animation 实现大量的动效,具体能够查看下 animate.css 这个库。

我上边提到的 简单例子 中也包括了一个简单地使用 animation 来缩放字体,和一个简单进度条的例子。

CSS 动画的性能

如今愈来愈多的页面开发是面向移动端,因此咱们会更加关注性能方面的问题。浏览器绘制动画的过程当中,涉及的主要是 Layout,Paint,Composite 的处理,当一个动画触发的浏览器处理越少,影响的区域越少,那么便消耗越低,性能上越好。

咱们能够参考这个 CSS Triggers 网站提供的列表,这里展现了修改属性时对应的浏览器内核所须要作的处理。简单归纳来讲,动画尽可能少涉及布局相关的调整,由于布局上一旦变化,会涉及外部元素和内部元素的位置调整,对浏览器的消耗至关大,而在现代浏览器中,拥有比较好动画性能的属性就是 transformopacity,建议须要动画的时候多往这两个属性考虑,例如字体要放大,避免使用 font-size,而是用 transform: scale() 等。

咱们可使用 will-change 来声明即将变化的属性,这可让浏览器提早作一些优化工做,关于这个属性,更多内容能够参考: will-change。值得留意的是,别滥用 will-change,在太多的元素上使用或者应用太多的属性都会致使浏览器资源浪费。

Chrome 浏览器的开发者工具提供的 Timeline 工具能够帮助咱们来查看页面渲染的一个性能表现状况,以下图:

Chrome Timeline

Timeline 能够用来获取脚本执行性能,网络请求性能等的表现数据,可是这里咱们只是关于动画渲染,因此只是勾选了 paint。咱们能够看到渲染能够保持在 60 FPS,便不会感受到卡顿。当渲染 FPS 太低的时候,图示那里会出现红色的提示,经过这个工具能够帮助咱们在须要的时候作针对性的优化。

对于 CSS 动画性能上的东西,本人还比较缺少实践经验,最近 w3cplus 上出现了大量的关于 CSS 动画性能相关的文章,有兴趣能够查阅。

相关文章
相关标签/搜索