浏览器的渲染过程和css动画的两种做法

动画定义:
      动画是一种通过定时拍摄一系列多个静止的固态图像(帧)以一定频率连续变化、运动(播放)的速度(如每秒N张)而导致肉眼的视觉残象产生的错觉。---维基百科
 
查看动画渲染过程:
  • 在点开F12性能表查看,随便点击一行代码,
  • 点击ESC会出现一个控制台(console),
  • 点左上角三个小点(more tools),选择出现性能描写(Rendering)。
  • 勾选Paint Flashing,屏幕不断出现的绿色表示浏览器不断渲染。
 
浏览器的渲染过程:
  •  根据HTML构建HTML树(DOM)
  •  根据CSS构建CSS树 (CSSDOM)
  •  将两棵树合并成一颗渲染树  
  •   Layout布局(文档流、盒模型、计算大小和位置)
  •   Paint绘制(把边框颜色、文字颜色、阴影等画出来)
  •   Compose合成(就是将层叠样式合并起来展示画面)
合并图示:节点合并
 
a、用left做动画(不推荐,因为会通过浏览器渲染的全部步骤)
b、用transform做动画(只会通过渲染的最后composite步骤) 
由此说明使用transform比left性能高。
 

三种不同的渲染方式:
  • JS / CSS > 样式 > 布局 > 绘制 > 合成
      如果修改了元素的“layout”属性,也就是改变了元素的几何属性(例如宽度、高度、左侧或顶部位置等),那么浏览器将必须检查所有其他元素,然后“自动重排”页面。任何受影响的部分都需要重新绘制,而且最终绘制的元素需进行合成。对style进行重新计算,可能还要走Layout,Paint,Conposite三步合成
  • JS / CSS > 样式 > 绘制 > 合成
      如果修改了“paint only”属性(例如背景图片、文字颜色或阴影等),即不会影响页面布局的属性,则浏览器会跳过布局,但仍将执行绘制。
  • JS / CSS > 样式 > 合成
      如果您更改一个既不要布局也不要绘制的属性,比如transform,则浏览器将跳到只执行合成。
 
更新样式的方式:一般用JS更新样式,
如:div.styel.background = 'red'
       div.style.display = 'none'
       div.classList.add('red') *
       div.remove()直接删掉节点
 
三种渲染方式实例:
第一种,全走
div.remove()会触发当前消失,其他元素relayout
可以看到三个方框删掉第一个空白框框后,三个框框原本位置都绿了--》证明浏览器经过了布局,绘制和合成
 
第二种,跳过layout
改变背景颜色,直接repaint + composite
可以看到第一个方框改变颜色为红时变绿了其他没有变色--》跳过了layout,直接paint和composite
 
第三种,跳过layout和paint
改变transform,直接composite
可以看到只有开始和结束被绘制,中间没有被repaint(重新绘制)--》直接composite
 
每个属性对应的渲染流程查看:
要想知道哪个属性触发哪个流程除了自己试一遍别无他法,有个网站把所有属性都试过了
可以告诉你每一种属性到底触发的什么流程,相同属性不同浏览器可能触发的流程不同。
 
CSS动画优化:使用 will-change 或 translate
推荐网站:谷歌团队里面详细讲了每个步骤的优化
 
JS优化:
使用rquestAnimationFrame 代替 setTimeout 或 setInterval
当使用 setInterval() 计时器时,如果想要停止用 clearInterval( 对应id) 就可以停止
 

详细的浏览器渲染可以查看Google团队
 

CSS动画的两种做法?(transition 和 animation)
 
transform(变形)全解:
可以到MDN上查看,里面详细把每个属性都给了一个详细的例子,教会你如何使用。
 
transform常用的四个功能:
  • translate-位移
  • scale-缩放
  • rotate-旋转
  • skew-倾斜
注释:一般都要配合使用transition过渡,inline元素不支持transform,需要先变成block
 
1.translate-移动
常用写法:
translate( <length-percentage> , <length-percentage>? )
translateX( <length-percentage> )在X轴上移动,左右
translateY( <length-percentage> )在Y轴上移动,上下
translateZ( <length>)  当需要设置Z点时,垂直于屏幕的点。
   就必须要告诉视点(xyz交点)父容器  perspective  (透视图原点在什么位置),在Z轴上移动,默认垂直于屏幕方向,
translate3d(x,y,z)
translate(-50%,-50%)可以做绝对定位元素的居中
         具体代码:http://js.jirengu.com/kiyarowelo/1/edit
 
2.scale-缩放
常用写法:
scale( <number> , <number>? )
scaleX( <number> )
scaleY( <number> )
这里是放大1.5倍
注:同样也支持X,Y轴,变胖,变高。但是它的border也会相应的变形,容易出现模糊,所以一般不用scale
 
3.rotate-旋转
常用写法:一般用于做360度旋转制作loading
<rotate()> = rotate( [ <angle> | <zero> ] )
<rotate3d()> = rotate3d( <number> , <number> , <number> , [ <angle> | <zero> ] )/*太复杂了*/
<rotateX()> = rotateX( [ <angle> | <zero> ] )/*围绕X轴转动*/
<rotateY()> = rotateY( [ <angle> | <zero> ] )/*围绕Y轴转动*/
<rotateZ()> = rotateZ( [ <angle> | <zero> ] )/*围绕Z轴转动,默认就是垂直与屏幕的轴*/
 
4.skew-倾斜
常用写法:
<skew()> = skew( [ <angle> | <zero> ] , [ <angle> | <zero> ]? )
<skewX()> = skewX( [ <angle> | <zero> ] )
<skewY()> = skewY( [ <angle> | <zero> ] )
 
合并:transform的多重效果
可以组合使用,空格隔开。
  /*放大1.5倍,旋转45度*/
  transform:scale(1.5) rotate(45deg);
  transform:scale(0.5) translate(-100%,-100%);
  transform:none;/*取消所有*/
 

transition:过渡
 
作用:
transition作用是添加中间帧(告诉开头和结尾怎么样,中间自动补齐)
 
比如:宽高开始,当hover时宽变为100px,transition补中间过程
<head>
  ...
  <style>
   #demo{
    width: 50px;
    height: 50px;
    border: 1px solid red;
    transition: width 1s;
    /*如果宽度变化,就添加1s的中间动画*/
  }
  #demo:hover{
    width: 100px;
  }
  </style>
</head>
<body>
  <div id="demo"></div>
</body>
 
语法格式:
transition: 属性名 时长 过渡方式 延迟(过多久开始运动)
          eg:transition: left 200ms linear 1s
 
可以用逗号分隔开两个不同属性
         eg:transition: left 200ms, top 400ms
 
可以用all代表所有的属性,上面写transform就用的all
          eg:transition: all 200ms
 
过渡方式有: linear(匀速线性) | ease | ease-in(淡入) | ease-out(淡出) | ease-in-out(缓入)
           | cubic-bezier | steep-start | step-end | steeps
 
注意:
并不是所有的属性都能过渡
display: none;=>block没法过度(从看不见到看的间没法过渡)
可以用opacity: 1;=>0(透明度从1到0看不见,但位置还占着的)
如果想要从看不见到看得见一般用visibility: hidden;=>visible(位置也占着)
background颜色可以过渡,是16进制的
 
过渡须要有起始
  • 一般只有一次动画或者两次,比如hover状态(鼠标移到目标位置)和非hover状态(移开)的过渡。
 
如果除了起始还想要在中间有变化呢,中间该怎么过渡?
有两种方法:
  • 一种是使用两次transform
注:因为transition每一次只能加载一种变化。
具体代码:http://js.jirengu.com/tokipivaqe/1/edit
 
  • 还有一种就是animation动画
 

 
animation:动画
 
使用animation:
  • 声明关键帧
  • 添加动画
#demo.start{
  animation: xxx 1.5s;
  /*js的点击事件后开始xxx,总时间1.5s,要想停在最后一帧,可以加上forwards*/
}
@keyframes xxx {
  0% {
    transform: none;
  }
  60%{
    transform: translateX(200px);
  }
  100%{
    transform: translateX(200px) translateY(100px);
  }
}
/*给了三个关键帧,分别是0%*,60%和100%,0-60%向由移动200px,60-100%向下移动100px/   
可以添加任意数量想添加的中间帧,它会按照你给的线路进行移动
 

 
@keyframes语法
 
使用@keyframes:
  • 一种写法是from to
  • 另一种写法是百分数
 
from to就智能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: 时长 | 过渡方式 | 延迟 | 次数 | 方向 | 填充模式 | 是否暂停 | 动画名 ;
时长: 写运动的时间。
过渡方式: 和transition取值一样,如ease。
次数: 执行的次数,也可以infinite(无限次)
方向: reverse(反方向运动),alternate(交替的,适合加载动画,过去又回来),alternate-reverse(反方向交替)。
填充模式: none | forwards(定格) | backwards(一开始就把动画第一帧复制到原始的位置) | both
是否暂停: paused | running

 


彩蛋:创建一个跳动的心
  • 使用transform
  • 使用animation
 
 
 
 
 
posted @ 2021-01-17 23:10  蛰鸣  阅读(108)  评论(0编辑  收藏  举报