css动画

2020-10-16
2 min read

将div左右移动的例子

原理

每过段时间(用setInterval做到)

将div移动一小段距离

直到移动到目标点

注意性能

绿色表示重新绘制(repaint)了

css渲染过程依次包含布局,绘制,合成

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

image

第2种方式

前端高手不用left做动画,用transform(变形),性能会好很多

原理

transform:translateX(0=>300px)

直接修改会被合成,需要等一会修改

transition过渡属性可以自动脑补中间帧

注意性能

并没有repaint重新绘制

比改left性能好

使用transform让浏览器渲染次数变少了,性能好

浏览器渲染原理

查看浏览器渲染

开发者工具,选中任意一个tab,按esc键,勾选Paint flashing。

刷新页面,绿色出现的次数,就是浏览器渲染的次数

浏览器渲染过程

根据HTML构建HTML树(DOM)

根据CSS构建CSS树(CSSOM)

将两棵树合并成一颗渲染树

Layout布局(文档流,盒模型,计算大小和位置)

Paint绘制(把边框颜色,文字颜色,阴影等画出来)

Compose合成(根据层叠关系展示画面)

如何更新样式

一般用JS来更新样式

比如div.style.background='red'
比如div.style.display='none'
比如div.classList.add('red') 

加类比加样式更好!高手都是加类更快,新手才加style。工作中也是直接加类

比如div.remove()直接删掉节点

这些方法有什么不同吗?

用js更新样式有3种不同的渲染更新方式

image

第一种,全走

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

第二种,跳过layout

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

第三种,跳过layout和paint

改变transform,只需composite


不同属性有不同的渲染流程,怎么知道每个属性触发什么流程?

CSS Triggers

浏览器渲染性能优化

js/css/样式/Layout布局/Paint绘制/Composited合成

5个过程每一个都可以被优化

1.优化JavaScript执行(优化js)

TL;DR

  • 对于动画效果的实现,避免使用 setTimeout 或 setInterval,请使用 requestAnimationFrame。

  • 将长时间运行的 JavaScript 从主线程移到 Web Worker。

  • 使用微任务来执行对多个帧的 DOM 更改。

  • 使用 Chrome DevTools 的 Timeline 和 JavaScript 分析器来评估 JavaScript 的影响。

2.缩小样式计算的范围并降低其复杂性(优化style计算范围)

TL;DR

  • 降低选择器的复杂性;使用以类为中心的方法,例如 BEM。

  • 减少必须计算其样式的元素数量。

3.避免大型、复杂的布局和布局抖动(优化布局layout)

TL;DR

  • 布局的作用范围一般为整个文档。

  • DOM 元素的数量将影响性能;应尽可能避免触发布局。

  • 评估布局模型的性能;新版 Flexbox 一般比旧版 Flexbox 或基于浮动的布局模型更快。

  • 避免强制同步布局和布局抖动;先读取样式值,然后进行样式更改。

4.简化绘制的复杂度、减小绘制区域(优化绘制paint)

TL;DR

  • 除 transform 或 opacity 属性之外,更改任何属性始终都会触发绘制。

  • 绘制通常是像素管道中开销最大的部分;应尽可能避免绘制。

  • 通过层的提升和动画的编排来减少绘制区域。

  • 使用 Chrome DevTools 绘制分析器来评估绘制的复杂性和开销;应尽可能降低复杂性并减少开销。

5.坚持仅合成器的属性和管理层计数(优化合成composite)

TL;DR

  • 坚持使用 transform 和 opacity 属性更改来实现动画。

  • 使用 will-change 或 translateZ 提升移动的元素。

  • 避免过度使用提升规则;各层都需要内存和管理开销。

transform(变形)

4个常用功能

位移 transform:translate
缩放 transform:scale 放大/缩小
旋转 transform:rotate
倾斜 transform:skew

经验

一般都需要配合transition过渡 代码:transition:all 1s;

inline元素不支持transform,需要先变成block

一.transform:translate位移(常用)

常用写法

translate(<length-percentage>,<length-percentage>?)
translateX(<length-percentage>)
translateY(<length-percentage>)
垂直于视点translateZ(<length>)且父容器 perspective
translate3d(x,y,z)

经验

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

可用于场景:loading加载中…

不支持IE 其它都支持

2.要学会看懂MDN的语法示例

image

?表示该值可省略

长度length 百分数percentage 角度angle(例:360deg)

二.transform:scale 缩放

常用写法

scaleX(<number>)需要配合transition:all 1s;过渡
scaleY(<number>)
scale(<number>,<number>?)

经验

用的较少,因为容易出现模糊

代码:transition:all 1s;过渡
     transform: scale(1.5);

三.transform:rotate旋转

常用写法

rotate([<angle>|<zero>])
rotateX([<angle>|<zero>])
rotateY([<angle>|<zero>])
rotateZ([<angle>|<zero>])
rotate3d太复杂,无法用语言表述

经验

1.一般用于360度旋转制作loading或者按钮的交互

2.用到时再搜索rotate mdn看文档

代码 transform: rotate(45deg);

四.transform:skew倾斜

常用写法

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

经验

用的较少

用时再搜skew mdn

transform多重效果

组合使用

transform:scale(0.5)translate(-100%,-100%);
transform:none;取消所有

transition过渡

其它

1.#demo.end 注意不能有空格,表示demo拥有end的时候(#demo .end表示demo后代里面的end)

意思是用css给demo增加一个class=“end”

注意要配合js

button.onclick=()=>{

demo.classList.add(‘start’)

}

作用

补充中间帧

语法

1.transition:属性名 时长 过渡方式 延迟 //4个值

  transition:left 200ms linear

2.可以用逗号分隔两个不同属性

  transition:left 200ms,top 400ms

3.可以用all代表所有属性

  transition:all 200ms ease-in-out 300ms;//再延迟300ms淡入淡出

4.过渡方式有:

  linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier|step-start|step-end|steps

变态

注意,并不是所有属性都能过渡

display:none;=>block没法过渡

一般改成visibility:hidden=>visible

image

animation动画

过渡必须要有起始

一般只有一次动画,比如hover和非hover状态的过渡

接下来介绍两次动画animation(更高级的过渡效果)

语法

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

时长:1s

过渡方式:跟transition一样,如linear

次数:3或者infinite

方向:reverse|alternate|alternate-reverse

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

是否暂停:paused|running

以上所有属性都有对应的单独属性(都可单独设置)

image

两种办法

1’使用两次transform也可实现两次动画

.a===transform===>.b

.b===transform===>.c

如何知道到了中间点呢?

用setTimeout或者监听transitionend事件

image

2’使用animation

声明关键帧@keyframes

添加动画

image

@keyframes完整语法

标准写法

一种写法是from to

另一种写法是百分数(更广泛)

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

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