CSS动画

197 阅读4分钟

动画原理

动画是由许多静止的画面(帧)以一定的速度连续播放组成,由于人的肉眼因视觉残像产生错觉,而错以为是活动的画面。例如影视画面以每秒24帧播放,游戏以每秒30帧进行播放。

简单实例

使用demo.style.left = n / 100 * 300 + 'px'做动画, 移动Div

  • 配合使用SetInterval每隔一小段时间移动Div,知道移动到目的点
  • 移动过程中CSS一直在绘制repaint,耗费性能

使用transform: translateX(300px)做动画,移动Div

  • 需要配合使用SetTimeout计时器,因为直接运行,会直接合成
  • 并没有repaint,性能要比上面的例子好

浏览器渲染过程

过程

  1. 根据HTML构建HTML树,为DOM
  2. 根据CSS构建CSS树,为CSSOM
  3. 将上面两棵树合并为一颗树,为render tree
  4. 进入Layout布局,包含构建文档流,盒模型,计算大小和位置
  5. 进入Paint绘制,绘制边框,文字,背景等等
  6. 进入Composite合成,根据不同层,和层叠关系组合最终画面展示

三种更新方式

  • 第一种, 全过程
    例如div.remove()会触发更新,经历布局,绘制,合成全过程
  • 第二种
    例如div.style.background='red会触发更新跳过布局,直接进入绘制,合成过程
  • 第三种 例如改变transform: translateX(300px)将触发更新,跳过布局,绘制,直接进入合成过程

使用JS更新样式

  • 设置Div的背景色div.style.background='red'
  • 设置Div为不展示div.style.display='none'
  • 修改Div类的名称div.classList.add('red')
  • 移除Div节点div.remove()

CSS动画优化

  • JS优化 使用requestAnimationFram代替setTimeout或者setInterval
  • CSS优化 使用will-change或者Translate

Transform

transform属性允许你旋转,缩放,倾斜或平移给定元素。这是通过修改CSS视觉格式化模型的坐标空间来实现的。

Translate位移

  • transltateX(<length-percentage>)
  • translateY(<length-percentage>)
  • translate(<length-percentage>,<length-percentage>?)
  • translateZ(<length>) 父容器为perspective
  • translated3d(x,y,z)
  • top:50%;top:50%,translate(-50%,-50%)可以做到绝对定位元素的居中

Scale缩放

用法

  • scaleX(<number>)
  • scaleY(<number>)
  • scaleY(<number>,<number>)
  • 容易出现模糊

Rotate旋转

用法

  • rotate([<angle>|<zero>])
  • rotateZ([<angle>|<zero>])
  • rotateX([<angle>|<zero>])
  • rotateY([<angle>|<zero>])
  • rotate3D
  • 用来旋转360度查看文档

倾斜Skew

用法

  • skewX([<angle>|<zero>])
  • skewY([<angle>|<zero>])
  • skew([<angle>|<zero>],[<angle>|<zero>])

Transform多重效果

  • transform: scale(0.5) translate(-100%,-100%);
  • transform: none;

注意事项

  • 通常需要配合transition过渡
  • inline元素不支持transforme,需要先转化为block,再使用

Transition过渡

transition属性是transition-propertytransition-durationtransition-timing-functiontransition-delay的一个简写属性

用法

用来补充中间帧

语法

  • transition: (属性名 时长 过渡方式 延迟);
  • transition: left 200ms linear;
  • transition: left 200ms, top 400ms; 使用逗号,分割不同的两个属性
  • transition: all 200ms; 可以用all代表所有属性
  • 过渡方式有:linear | ease | ease-in | ease-out | ease-in-out | cubic-bezier | step-start | step-end | steps

注意事项

并不是所有的属性都能过渡

  • display:none转化为display: block不能过渡
  • 这种情况可以设置visibility:hidden转化为visibility:visible
  • backgound的颜色可以过渡
  • opacity的颜色可以过渡
  • 过渡必须要有开始和结束,动画为一次或者两次,例如hover和非hover的过渡

过渡中间点

除了上述情况,还可以设置过渡的中间点

使用两次transform

  • .a===transform===>.b
  • .b===transform===>.c
  • 使用setTimeout或者监听transition事件得知到了中间点

使用animation

  • 声明关键帧
  • 添加动画

Animation

语法1

@keyframes slidein {
  from {
    transform: translateX(0%);
  }

  to {
    transform: translateX(100%);
  }
}

语法2

@keyframes identifier {
  0% { top: 0; left: 0; }
  30% { top: 50px; }
  68%, 72% { left: 50px; }
  100% { top: 100px; left: 100%; }
}

缩写语法

animation: 时长 | 过渡方式 | 延迟 | 次数 | 方向 | 填充模式 | 是否暂停 | 动画;

  • 时长: 1s或者1000ms
  • 过渡方式: 和transtion取值一样,如linear
  • 次数: 3或者2.4或则和infinite
  • 方向: reverse | alternate | alternate-reverse
  • 填充模式: none | forwards | backwards | both
  • 是否暂停: paused | running
  • 以上所有属性都有对应的单独属性

让动画停止在最后一帧

更多信息

CSSOM

CSS render performance

transform animation

CSS trigger website

如何优化css动画 google

Transform MDN

Transiton MDN

timing-function MDN