CSS 动画

本文详细阐述了浏览器的渲染步骤,包括构建DOM、CSSOM、渲染树、布局、绘制和合成。讨论了更新样式的方式以及不同修改引发的不同渲染流程。重点介绍了CSS动画优化技巧,如使用requestAnimationFrame、transform属性、transition属性以及CSS动画的关键帧动画。同时,解释了如何利用这些特性减少重排和重绘,提高页面性能。
摘要由CSDN通过智能技术生成

浏览器的渲染步骤

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

如何更新样式?

一般使用 JS 来更新样式

比如 div.style.background = 'red'

比如 div.style.display = 'none'

比如 div.classList.add('red')

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

三种不同的渲染样式

  • 第一种:全走

JS / CSS > 样式 > 布局 > 绘制 > 合成

如果修改元素的 layout 属性,也就是改变了元素的几何属性(例如宽度、高度、左侧或顶部位置等),那么浏览器将必须检查所有其他元素,然后“自动重排”页面。任何受影响的部分都需要重新绘制,而且最终绘制的元素需进行合成

  • 第二种:跳过 layout

JS / CSS > 样式 > 绘制 > 合成

如果修改 paint 属性(例如背景图片、文字颜色或阴影等),即不会影响页面布局的属性,则浏览器会跳过布局,但仍将执行绘制

  • 第三种:跳过 layout 和 paint

JS / CSS > 样式 > 合成

如果更改一个既不要布局也不要绘制的属性,则浏览器将跳到只执行合成。

查询不同的CSS属性会触发的不同过程:

https://csstriggers.com/

 

CSS 动画优化

JS 优化

使用 requestAnimationFrame 代替 setTimeout 或 setlnterval

CSS 优化

使用 will-change 或 translate

transform 属性

CSS transform 属性允许你旋转,缩放,倾斜或平移给定元素。这是通过修改CSS视觉格式化模型的坐标空间来实现的。

常用功能

  • translate 位移
transform: translate(12px, 50%);
transform: translateX(2em);
transform: translateY(3in);
transform: translateZ(2px);
transform: translate3d(12px, 50%, 3em);

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

  • scale 缩放
transform: scale(2, 0.5);
transform: scaleX(2);
transform: scaleY(0.5);

用的较少,容易出现模糊

  • rotate 旋转
transform: rotateX(10deg);
transform: rotateY(10deg);
transform: rotateZ(10deg);
transform: rotate(0.5turn);
transform: rotate3d(1, 2.0, 3.0, 10deg);

一般用于360度旋转制作 loading

  • skew 倾斜
transform: skewX(30deg);
transform: skewY(1.07rad);
transform: skew(30deg, 20deg);
  • 组合使用
transform: scale(0.5) translate(-100%,-100%);
transform: none;取消所有

transition 属性

transtion 属性是 transition-property,transition-duration,transition-timing-function 和 transition-delay 的一个简写属性,作用是补充中间帧。

  • transition-property(属性名)

none

没有过渡动画

all

所有可被动画的属性都表现出过渡动画

IDENT

属性名称。由小写字母 a 到 z,数字 0 到 9,下划线(_)和破折号(-)。第一个非破折号字符不能是数字。同时,不能以两个破折号开头

transtion 属性可以被指定为一个或多个 CSS 属性的过渡效果,多个属性之间用逗号进行分隔

transition-property: none;
transition-property: all;
transition-property: test_05;
transition-property: -specific;
transition-property: sliding-vertically;

transition-property: test1;
transition-property: test1, animation4;
transition-property: all, height, all;
transition-property: all, -moz-specific, sliding;
  • transition-duration(时长)

表示过渡属性从旧的值转变到新的值所需要的时间。如果时长是 0s ,表示不会呈现过渡动画,属性会瞬间完成转变。不接受负值

/* <time> 值 */
transition-duration: 6s;
transition-duration: 120ms;
transition-duration: 1s, 15s;
transition-duration: 10s, 30s, 230ms;
  • transition-timing-function(过度方式)

liner 此关键字表示定时函数 cubic-bezier(0.0, 0.0, 1.0, 1.0)。使用这个定时函数,动画会以恒定的速度从初始状态过渡到结束状态

ease 此关键字表示定时函数 cubic-bezier(0.25, 0.1, 0.25, 1.0)。 这个函数类似于 ease-in-out, 尽管它在开始时加速地更快,但在接近中间中,加速已经开始变慢了

ease-in 此关键字表示定时函数 cubic-bezier(0.42, 0.0, 1.0, 1.0)。动画开始时缓慢,然后逐步加速,知道达到最后状态,动画突然停止

easy-out  此关键字表示定时函数 cubic-bezier(0.0, 0.0, 0.58, 1.0)。动画开始很快,然后逐渐减慢,直到最终状态

easy-in-out  此关键字表示定时函数 cubic-bezier(0.42, 0.0, 0.58, 1.0)。使用这个定时函数,动画开始的行为类似于 ease-in 函数,动画结束时的行为类似于 ease-out函数

step-start  此关键字表示定时函数 steps(1, start)。使用这个定时函数,动画会立刻跳转到结束状态,并一直停留在结束状态直到动画结束

step-end  此关键字表示定时函数 steps(1, end)。使用这个定时函数,动画会一直保持初始状态直到动画结束,然后立刻跳转到结束状态

transition-timing-function: ease
transition-timing-function: ease-in
transition-timing-function: ease-out
transition-timing-function: ease-in-out
transition-timing-function: linear
transition-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1)
transition-timing-function: step-start
transition-timing-function: step-end
transition-timing-function: steps(4, end)

transition-timing-function: ease, step-start, cubic-bezier(0.1, 0.7, 1.0, 0.1)
  • transition-delay(延迟)

表明动画效果属性生效之前需要等待的时间

transition-delay: 3s;
transition-delay: 2s, 4ms;

缩写语法

/* Apply to 1 property */
/* property name | duration */
transition: margin-right 4s;

/* property name | duration | delay */
transition: margin-right 4s 1s;

/* property name | duration | timing function */
transition: margin-right 4s ease-in-out;

/* property name | duration | timing function | delay */
transition: margin-right 4s ease-in-out 1s;

/* Apply to 2 properties */
transition: margin-right 4s, color 1s;

/* Apply to all changed properties */
transition: all 0.5s ease-out;

注意

  • 并不是所有属性都能过渡

display:none => block 无法过渡,一般改成 visibility:hidden => visible

display: none 是彻底消失,不在文档流中占位,浏览器也不会解析该元素;不会被子元素继承

visibility:hidden 是视觉上消失了,在文档流中占位,浏览器会解析该元素;会被子元素继承

如果想隐藏某元素,但在页面上保留该元素的空间的话,应该使用visibility:hidden,如果想在隐藏某元素的同时让其它内容填充空白的话应该使用display:none

  • 过渡必须要有起始,一般只有一次或两次动画,比如 hover 和非 hover 状态的过渡
  • 如果除了起始还有中间点,有两种方法

1.使用两次transform

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

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

如何知道到了中间点?

用 setTimeout 或者监听 transitionend 事件

css

#demo{
  width: 100px;
  height: 100px;
  border: 1px solid red;
  margin: 50px;
  transition: transform 1s linear;
}

#demo.b{
  transform: translateX(200px);
}
#demo.c{
  transform: translateX(200px) translateY(100px);

js

button.onclick = ()=>{
  
  demo.classList.add('b')
  setTimeout(()=>{
    demo.classList.remove('b')
    demo.classList.add('c')
  },1000)
}

2.使用 animation 申明关键帧,添加动画

#demo{
  width: 100px;
  height: 100px;
  border: 1px solid red;
  margin: 50px;
  transition: transform 1s linear;
}

#demo.start{
  animation: xxx 1.5s;
}


@keyframes xxx {
  0% {
    transform: none;
  }
  66.66%{
    transform: translateX(200px);
  }
  100%{
    transform: translateX(200px) translateY(100px);
  }
}
  • 如何让动画停在最后一帧?

加上 forwards

#demo{
  width: 100px;
  height: 100px;
  border: 1px solid red;
  margin: 50px;
}

#demo.start{
  animation: xxx 1.5s forwards;
}


@keyframes xxx {
  0% {
    transform: none;
  }
  66.66%{
    transform: translateX(200px);
  }
  100%{
    transform: translateX(200px) translateY(100px);
  }
}

@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%; }
}

animation 属性

CSS animation 属性是 animation-name,animation-duration, animation-timing-function,animation-delay,animation-iteration-count,animation-direction,animation-fill-mode 和 animation-play-state 属性的一个简写属性形式。

  • animation-name (动画名)

指定应用的一系列动画,每个名称代表一个由@keyframes定义的动画序列

/* Single animation */
animation-name: none;
animation-name: test_05;
animation-name: -specific;
animation-name: sliding-vertically;

/* Multiple animations */
animation-name: test1, animation4;
animation-name: none, -moz-specific, sliding;
  • animation-duration(时长)

指定一个动画周期的时长,单位为秒(s)或者毫秒(ms),无单位值无效

animation-duration: 6s
animation-duration: 120ms
animation-duration: 1s, 15s
animation-duration: 10s, 30s, 230ms
  • animation-timing-function(过渡方式)
/* Keyword values */
animation-timing-function: ease;
animation-timing-function: ease-in;
animation-timing-function: ease-out;
animation-timing-function: ease-in-out;
animation-timing-function: linear;
animation-timing-function: step-start;
animation-timing-function: step-end;

/* Function values */
animation-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1);
animation-timing-function: steps(4, end);
animation-timing-function: frames(10);

/* Multiple animations */
animation-timing-function: ease, step-start, cubic-bezier(0.1, 0.7, 1.0, 0.1);
  • animation-delay(延迟)

从动画应用在元素上到动画开始的这段时间的长度,0s是该属性的默认值,代表动画在应用到元素上后立即开始执行。定义一个负值会让动画立即开始。但是动画会从它的动画序列中某位置开始。例如,如果设定值为-1s,动画会从它的动画序列的第1秒位置处立即开始

animation-delay: 3s;
animation-delay: 2s, 4ms;
  • animation-iteration-count(次数)

动画在结束前运行的次数 可以是1次 无限循环,如果指定了多个值,每次播放动画时,将使用列表中的下一个值,在使用最后一个值后循环回第一个值

/* 值为关键字 */
animation-iteration-count: infinite;

/* 值为数字 */
animation-iteration-count: 3;
animation-iteration-count: 2.4;

/* 指定多个值 */
animation-iteration-count: 2, 0, infinite;
  • animation-direction(方向)

动画是否反向播放

normal

每个循环内动画向前循环,换言之,每个动画循环结束,动画重置到起点重新开始,这是默认属性

alternate

动画交替反向运行,反向运行时,动画按步后退,同时,带时间功能的函数也反向,比如,ease-in 在反向时成为ease-out。计数取决于开始时是奇数迭代还是偶数迭代

reverse

反向运行动画,每周期结束动画由尾到头运行

alternate-reverse

反向交替, 反向开始交替

动画第一次运行时是反向的,然后下一次是正向,后面依次循环。决定奇数次或偶数次的计数从1开始

animation-direction: normal
animation-direction: reverse
animation-direction: alternate
animation-direction: alternate-reverse
animation-direction: normal, reverse
animation-direction: alternate, reverse, normal
  • animation-fill-mode(填充模式)

动画在执行之前和之后如何将样式应用于其目标

none
当动画未执行时,动画将不会将任何样式应用于目标,而是已经赋予给该元素的 CSS 规则来显示该元素。这是默认值

forwards
目标将保留由执行期间遇到的最后一个关键帧计算值。 最后一个关键帧取决于 animation-direction和animation-iteration-count 的值

backwards
动画将在应用于目标时立即应用第一个关键帧中定义的值,并在 animation-delay 期间保留此值。 第一个关键帧取决于 animation-direction 的值

both
动画将遵循 forwards 和 backwards 的规则,从而在两个方向上扩展动画属性。

在 animation-*属性上指定多个以逗号分隔的值时,它们将根据值的数量以不同的方式分配给 animation-name 属性中指定的动画

/* Single animation */
animation-fill-mode: none;
animation-fill-mode: forwards;
animation-fill-mode: backwards;
animation-fill-mode: both;

/* Multiple animations */
animation-fill-mode: none, backwards;
animation-fill-mode: both, forwards, none;

animation-play-state(是否暂停)

一个动画是否运行或者暂停

running
当前动画正在运行
paused
当前动画已被停止

/* Single animation */
animation-play-state: running;
animation-play-state: paused;

/* Multiple animations */
animation-play-state: paused, running, running;

缩写语法

/* @keyframes duration | timing-function | delay |
   iteration-count | direction | fill-mode | play-state | name */
animation: 3s ease-in 1s 2 reverse both paused slidein;

/* @keyframes duration | timing-function | delay | name */
animation: 3s linear 1s slidein;

/* @keyframes duration | name */
animation: 3s slidein;

*本文为鲲游北冥的原创文章,著作权归本人和饥人谷所有,转载务必注明来源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值