CSS动画

482 阅读5分钟

动画的原理

人脑的bug

定义

  • 由许多精致的画面(帧)
  • 以一定的速度(如每秒30张)连续播放时
  • 肉眼因视觉残象产生错觉
  • 而误以为是活动的画面

概念

  • 帧:每个静止的画面都叫做帧
  • 播放速度:每秒24帧(影视)或者每秒30帧(游戏)

一个简单的CSS动画例子

将div从左往右移动

  • 一个坏处,setInterval计时器他不会停止
  • 解决办法,替换成var id = setInterval·····,else{clearInterval(id)}

原理

  • 每过一段时间(用setInterval做到)
  • 将div移动一小段距离
  • 直到移动到目标地点

注意性能

  • 绿色表示重新绘制了(repaint)了。什么是绿色,在开发者工具里任意一个tap,按一下esc,点击出现的控制台左边三个点按钮,找到Rendering(渲染),勾选Paint flashing就能看到绿色了,代表在重新渲染

  • CSS渲染过程依次包含布局、绘制、合成

  • 其中布局和绘制有可能被省略

  • 拓展:换一个实现方式

css:

#demo:{
    xxx
    transition: all 1s linear;
}
#demo{
    transform: translateX(200px);
}

js:

setTimeout(()=>{
    demo.classList.add('end');
},3000);

结论就是,通过开发者工具可以看到这个动画过程只在起点和终点渲染了,中途没有进行渲染,是正面优化

浏览器渲染原理

  • 掌握浏览器第一手资料,就去看谷歌、火狐等团队的文章

浏览器渲染过程

  • 步骤
  1. 根据HTML构建HTML树(DOM)
  2. 根据CSS构建CSS树(CSSOM)
  3. 将两棵树合并成一颗渲染树(render tree)
  4. Layout布局(文档流、盒模型、计算大小和位置)
  5. Paint绘制(把边框颜色、文字颜色、阴影等画出来)
  6. Composite合成(根据层叠关系展示画面)

更新过程

  • 一般我们用JS来更新样式
  1. 比如 div.style.background ='red'
  2. 比如 div.style.display = 'none'
  3. 比如 div.classList.add('red')
  4. 比如 div.remove()直接删除节点
  5. 加样式不如加类,因为写类效率更高
  • 那么这些方法有什么不同吗

    • 有三种不同的渲染方式
    1. JS>S>L>P>C 比如用了remove()
    2. JS>S>P>C 比如布局没变
    3. JS>S>C 比如用了transform
  • 那么我怎么知道每个属性触发什么流程:自己一个一个尝试吧

  • 这里有个网址 csstriggers.com查看,第一列是chrome,第二个是firefox,第三个是苹果,第四个是IE

前端高手不用left做动画

  • 用transform

  • 原理
  1. transform:translateX(0=> 300px)
  2. 直接修改会被合成,需要等一会修改
  3. transition过渡属性可以自动脑补中间帧

  • 注意性能
  1. 并没有repaint(重新绘制)
  2. 比改left性能好

提升:CSS动画优化

没什么技术含量

  • 答案都在Google写的文章里,谁看完谁牛X

JS优化

  • 使用requestAnimationFrame代替setTimeout或setInterval

CSS优化

  • 使用will-change或translate

没错

  • 完全就是死记硬背

transform全解

最好的办法就是去看MDN

四个常用功能

  • 位移 translate
  • 缩放 scale
  • 旋转 rotate
  • 倾斜 skew

ps:可以用空格隔开组合使用

经验

  • 一般都需要配合transition过渡
  • inline元素不支持transform,需要先变成block

tranform之translate

常用写法

  • translateX()
  • translateY()
  • translate(,?)问号表示可以省略
  • translateZ()且父容器perspective
  • translate3d(x,y,z)

经验

  • 要学会看懂MDN的语法示例
  • translate(-50%,-50%)配合top,left可做绝对定位元素的居中

tranform之scale

  • 很简单,用的比较少,因为变形容易变模糊

tranform之rotate

常用写法

  • rotate([<angle|<zero])angle是角度的意思
  • rotateZ([<angle|])
  • rotateX([<angle|<zero])
  • rotateY([<angle|<zero])
  • rotate3d太复杂,无法用语言表述
  • 不能补全尖括号,掘金会吞掉

经验

  • 一般用于360度旋转制作loading
  • 用到时再搜索rotate MDN看文档

tranform之skew

常用写法

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

经验

  • 用得较少
  • 用到时再搜skew MDN 文档

transform实践:跳动的❤

源代码

做一个红心

让他跳

心得

  • CSS需要你有想象力,而不是逻辑
  • CSS给出的属性都很简单,但是可以组合得很复杂

transition 过渡

作用

补充中间帧

语法

  • transition:属性名 时长 过渡方式 延迟
  • transition:left 200ms linear
  • 可以用逗号分隔两个不通水性
  • transition:left 200ms,top400ms
  • 可以用all代表所有属性
  • transition:all 200ms
  • 过渡方式有: linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier|step-start|step-end|steps,具体含义要靠数学知识

注意

  • 并不是所有属性都能过渡
  • display:none=>block 没法过渡
  • 一般改成visibility:hidden=>visible(不要问为什么)
  • display和visibility的区别自己搜一下
  • background颜色可以过渡吗?可
  • opacity透明度可以过渡吗?可,不推荐

过渡必须要有起始和结尾

如果除了起始,还有中间点

两种办法

使用两次transform

  • .a===transform ===>.b
  • .b===transform ===>.c
  • 如何知道到了中间点呢?
  • 用setTimeout或者监听transitionend事件

使用animation

  • 声明关键帧
  • 添加动画
  • 使用forward实现“不回去”

animation的keyframes 完整语法

  • 标准语法
  • 搜索keyframesMDN讲得很清楚
  • 一种写法是from to


  • 另一种写法是百分数

animation

缩写语法

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

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

复现跳动的心

animation跳动的❤