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性能好。
浏览器渲染原理
浏览器渲染步骤
- 根据HTML构建HTML树(DOM)
- 根据CSS构建CSS树(CSSOM)
- 将两棵树合并成一颗渲染树(render tree)
- Layout布局(文档流、盒模型、计算大小和位置)
- Paint绘制(把边框颜色、文字颜色、阴影等画出来)
- 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 变形
四个常用功能
- 位移 translate
- 缩放 scale
- 旋转 rotate
- 倾斜 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
以上所有属性都有对应的单独属性