动画是快速播放的多张照片,人眼对此产生错觉,以为是活动的画面。

浏览器渲染原理

渲染过程

  1. 根据 HTML 构建 DOM(Document Object Model)树
  2. 根据 CSS 构建 CSSOM(CSS Object Model)树
  3. 将二者合并成渲染树(render tree)
  4. layout 布局(文档流、盒模型、计算大小和位置)
  5. paint 绘制(把边框颜色、文字颜色、阴影等画出来)
  6. composite 合成(根据层叠关系展示画面)

如何更新样式

一般用 JS 更新样式,例如:

  • div.style.background = 'red'
  • div.style.display = 'none'
  • div.classList.add('red')
  • div.remove()

三种更新方式:

查看属性的渲染流程

https://csstriggers.com/

CSS 动画优化

transform 属性

transform - CSS: Cascading Style Sheets | MDN

常用功能:

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

语法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
none | <transform-list>
where 
<transform-list> = <transform-function>+

where 
<transform-function> = <matrix()> | <translate()> | <translateX()> | <translateY()> | <scale()> | <scaleX()> | <scaleY()> | <rotate()> | <skew()> | <skewX()> | <skewY()> | <matrix3d()> | <translate3d()> | <translateZ()> | <scale3d()> | <scaleZ()> | <rotate3d()> | <rotateX()> | <rotateY()> | <rotateZ()> | <perspective()>

where 
<matrix()> = matrix( <number>#{6} )
<translate()> = translate( <length-percentage> , <length-percentage>? )
<translateX()> = translateX( <length-percentage> )
<translateY()> = translateY( <length-percentage> )
<scale()> = scale( <number> , <number>? )
<scaleX()> = scaleX( <number> )
<scaleY()> = scaleY( <number> )
<rotate()> = rotate( [ <angle> | <zero> ] )
<skew()> = skew( [ <angle> | <zero> ] , [ <angle> | <zero> ]? )
<skewX()> = skewX( [ <angle> | <zero> ] )
<skewY()> = skewY( [ <angle> | <zero> ] )
<matrix3d()> = matrix3d( <number>#{16} )
<translate3d()> = translate3d( <length-percentage> , <length-percentage> , <length> )
<translateZ()> = translateZ( <length> )
<scale3d()> = scale3d( <number> , <number> , <number> )
<scaleZ()> = scaleZ( <number> )
<rotate3d()> = rotate3d( <number> , <number> , <number> , [ <angle> | <zero> ] )
<rotateX()> = rotateX( [ <angle> | <zero> ] )
<rotateY()> = rotateY( [ <angle> | <zero> ] )
<rotateZ()> = rotateZ( [ <angle> | <zero> ] )
<perspective()> = perspective( <length> )

where 
<length-percentage> = <length> | <percentage>

translate

语法示例:

1
2
3
4
5
transform: translate(12px, 50%); /* X, Y */
transform: translate3d(12px, 50%, 3em);/* X, Y, Z */
transform: translateX(2em);
transform: translateY(3in);
transform: translateZ(2px);

取值效果:

  • X > 0,向右;X < 0,向左。

  • Y > 0,向下;Y < 0,向上。

  • Z > 0 ,远离视点并放大(perspective);Z < 0,接近视点并缩小。

  • translate(-50%, -50%) 可做绝对定位元素的居中

    1
    2
    3
    4
    
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%); 
    

scale

语法示例:

1
2
3
4
5
transform: scale(2, 0.5);
transform: scale3d(2.5, 1.2, 0.3);
transform: scaleX(2);
transform: scaleY(0.5);
transform: scaleZ(0.3);

取值效果:

  • X 横向缩放
  • Y 纵向缩放

scale 使用较少,因为容易模糊。

rotate

语法示例:

1
2
3
4
5
transform: rotate(0.5turn); /* 和 rotateZ 一样 */
transform: rotate3d(1, 2.0, 3.0, 10deg);
transform: rotateX(10deg);
transform: rotateY(10deg);
transform: rotateZ(10deg);

取值效果:

  • rotate 或者 Z > 0,垂直于屏幕顺时针旋转;rotate < 0,逆时针旋转。
  • X 和 Y 值已经无法用语言解释了,只能想象了。

skew

语法示例:

1
2
3
transform: skew(30deg, 20deg);
transform: skewX(30deg);
transform: skewY(1.07rad);

取值效果:

  • X > 0,向左倾斜;X < 0,向右倾斜。
  • Y > 0,向上倾斜;Y < 0,向下倾斜。

组合使用

1
2
transform: scale(0.5) translate(-100%, -100%);
transform: none; /* 取消效果 */

跳动的心

transition | animation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>

<body>
  <div id="heart">
    <div class="left"></div>
    <div class="right"></div>
    <div class="bottom"></div>
  </div>
</body>

</html>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
#heart {
  margin: 100px;
  position: relative;
  display: inline-block;
  transition: all .5s;
}
#heart:hover {
  transform: scale(1.5);
}
#heart > .bottom {
  width: 50px;
  height: 50px;
  transform: rotate(45deg);
  background: red;
}
#heart > .left {
  width: 50px;
  height: 50px;
  border: 1px solid red;
  position: absolute;
  bottom: 100%;
  right: 100%;
  transform: rotate(45deg) translateX(31px);
  border-radius: 50% 0 0 50%;
  background: red;
}
#heart > .right {
  width: 50px;
  height: 50px;
  border: 1px solid red;
  position: absolute;
  bottom: 100%;
  left: 100%;
  transform: rotate(45deg) translateY(31px);
  border-radius: 50% 50% 0 0;
  background: red;
}

transition

transition 用于补充过渡动画。transition 是 transition-property,transition-duration,transition-timing-function 和 transition-delay 的缩写。

语法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* transition 语法 */
transition: 属性名 时长 过渡方式 延迟

/* transition-property 语法*/
transition-property: none;
transition-property: all;
transition-property: height;

/* transition-timing-function 语法 */
transition-timing-function: ease; /* 和 ease-in-out 类似,但开头比结尾稍快 */
transition-timing-function: ease-in; /* 先慢后快 */
transition-timing-function: ease-out; /* 先快后慢 */
transition-timing-function: ease-in-out; /* 先慢,中间快,后慢 */
transition-timing-function: linear; /* 匀速 */
transition-timing-function: step-start;
transition-timing-function: step-end;

/* transition-duration 语法*/
transition-duration: 6s;
transition-duration: 120ms;
transition-duration: 1s, 15s;
transition-duration: 10s, 30s, 230ms;

/* transition-duration 语法*/
transition-duration: 6s;
transition-duration: 120ms;
transition-duration: 1s, 15s;
transition-duration: 10s, 30s, 230ms;

以下情况不能过渡:

  • display: none -> block,一般改为 visibility: visible -> hidden

以下情况可以过渡:

  • background 背景色
  • opacity 透明度

两段动画怎么做过渡

  • 使用两次 transform
    • a -> transform -> b -> transform -> c
  • 使用 animation
    • 声明关键帧
    • 添加动画

@keyframes 语法

1
2
3
4
5
6
7
8
9
@keyframes slidein {
  from {
    transform: translateX(0%);
  }

  to {
    transform: translateX(100%);
  }
}
1
2
3
4
5
6
@keyframes identifier {
  0% { top: 0; left: 0; }
  30% { top: 50px; }
  68%, 72% { left: 50px; }
  100% { top: 100px; left: 100%; }
}

animation 语法

示例

animation 属性是 animation-nameanimation-duration, animation-timing-functionanimation-delayanimation-iteration-countanimation-directionanimation-fill-modeanimation-play-state 的缩写。

语法:

  • animation: 时长 | 过渡方式 | 延迟 | 次数 | 方向 | 填充方式 | 是否暂停 | 动画名
  • 时长:1s | 1000ms
  • 过渡方式:和 transition 一样,如 linear
  • 次数:2 | 2.4 | infinite
  • 方向:reverse | alternate | alternate-reverse
  • 填充模式:none | forwards | backwards | both
  • 是否暂停:paused | running

参考资料

css - Difference between CSS3 transitions' ease-in and ease-out - Stack Overflow