CSS动画

443 阅读2分钟

CSS动画

一个最简单的例子

  • 将div从左往右移动
var n = 1;
var id = setInterval(() => {
  if (n <= 200) {
    demo.style.left = n + 'px';
    n = n + 1;
  }else{
    clearInterval(id);
  }
}, 1000 / 60);

原理:使用setInterval,每过一段时间将div移动一小段距离,直到移动到目标地点。

但是中间一直在重新绘制(repaint),性能不好。

改用transform(变形)

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>

<body>
  <div class="wrapper">
    <div id="demo"></div>
  </div>
</body>

</html>
#demo{
  width: 100px;
  height: 100px;
  border: 1px solid red;
  transition: all 1s linear;
}

#demo.end{
  transform: translateX(200px);
}
setTimeout(()=>{
  demo.classList.add('end');
},0);

中间过程没有repaint,比改left性能好。

浏览器渲染原理

浏览器渲染步骤

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

如何更新样式

一般我们用js来更新样式

比如 div.style.background = 'red'

比如 div.style.display = 'none'

比如 div.classList.add('red') (加样式不如加类)

比如 div.remote() 直接删除节点

那么这些方法有什么不同?

  • 第一种,全走

    div.remove()会触发当前消失,其他元素relayout

  • 第二种,跳过layout

    改变背景颜色,直接repaint+composite

  • 第三种,跳过layout和paint

    改变transform,只需要composite

注意必须全部查看效果,在iframe里看有问题

transform 变形

四个常用功能

  1. 位移 translate
  2. 缩放 scale
  3. 旋转 rotate
  4. 倾斜 skew

translate

常用写法:

translateX(<length>|<percentage>)

translateY(<length>|<percentage>)

translate(<length>|<percentage>, <length>|<percentage>?)

translateZ(<length>) 且父容器perspective

translate3d(x,y,z)

transform: translateX(50px); /* x轴方向向右移动50px */
transform: translateY(50px); /* y轴方向向下移动50px */
#demo:hover {
  transform: translateZ(0px);
}
.wrapper {
  perspective: 1000px; /* 父容器创建视点 */
  border: 1px solid black;
}

scale

常用写法:

scaleX(<number>)

scaleY(<number>)

scale(<number,number>?)

rotate

常用写法:

rotate([<angle>|<zero>])

rotateZ([<angle>|<zero>])

rotateY([<angle>|<zero>])

skew

常用写法:

skewX([<angle>|<zero>])

skewY([<angle>|<zero>])

skew([<angle>|<zero>],[<angle>|<zero>]?)

transform多重效果

组合使用:

transform: scale(0.5) tanslate(-100%,-100%);

transform: none;取消所有

transition 过渡

作用

补充中间帧

语法

transition: 属性名 时长 过渡方式 延迟;(transition: left 200ms linear 1s;

可以用逗号分隔两个不同的属性(transform: left 200ms, top 400ms;

可以用all代表所有属性(transition: all 200ms;

过渡方式有:linear | ease | ease-in | ease-out | ease-in-out | cubic-bezier | step-start | step-end | steps

animation

使用方法:

声明关键帧

添加动画

@Keyframes

一种是写from to

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

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

另一种是写百分比

@keyframes identifier {
  0% { top: 0; }
  50% { top: 30px; left: 20px; }
  50% { top: 10px; }
  100% { top: 0; }
}

语法

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

时长:1s或1000ms

过渡方式:跟transition取值一样

次数:3或者2.4或者infinite

方向:reverse | alternate | alternate-reverse

填充模式:none | forwards | backwards | both

是否暂停: paused | running

以上所有属性都有对应的单独属性