动画定义:

      动画是一种通过定时拍摄一系列多个静止的固态图像(帧)以一定频率连续变化、运动(播放)的速度(如每秒N张)而导致肉眼的视觉残象产生的错觉。---维基百科

 

查看动画渲染过程:

  • 在点开F12性能表查看,随便点击一行代码,
  • 点击ESC会出现一个控制台(console),
  • 点左上角三个小点(more tools),选择出现性能描写(Rendering)。
  • 勾选Paint Flashing,屏幕不断出现的绿色表示浏览器不断渲染。

 

浏览器的渲染过程:

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

合并图示:节点合并

 

a、用left做动画(不推荐,因为会通过浏览器渲染的全部步骤)

      具体代码:http://js.jirengu.com/tunolemepa/1/edit?html,css,js,console,output

b、用transform做动画(只会通过渲染的最后composite步骤) 

      具体代码:http://js.jirengu.com/hifadavuxi/1/edit

由此说明使用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

具体代码:http://js.jirengu.com/yayiluvexo/2/edit?html,css,js,output

可以看到三个方框删掉第一个空白框框后,三个框框原本位置都绿了--》证明浏览器经过了布局,绘制和合成

 

第二种,跳过layout

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

具体代码:http://js.jirengu.com/yahecijugu/1/edit

可以看到第一个方框改变颜色为红时变绿了其他没有变色--》跳过了layout,直接paint和composite

 

第三种,跳过layout和paint

改变transform,直接composite

具体代码:http://js.jirengu.com/zoqovatisu/1/edit

可以看到只有开始和结束被绘制,中间没有被repaint(重新绘制)--》直接composite

 

每个属性对应的渲染流程查看:

要想知道哪个属性触发哪个流程除了自己试一遍别无他法,有个网站把所有属性都试过了

推荐看网站https://csstriggers.com/

可以告诉你每一种属性到底触发的什么流程,相同属性不同浏览器可能触发的流程不同。

 

CSS动画优化:使用 will-change 或 translate

推荐网站:谷歌团队里面详细讲了每个步骤的优化

https://developers.google.com/web/fundamentals/performance/rendering/optimize-javascript-execution

 

JS优化:

使用rquestAnimationFrame 代替 setTimeout 或 setInterval

当使用 setInterval() 计时器时,如果想要停止用 clearInterval( 对应id) 就可以停止

 


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



CSS动画的两种做法?(transition 和 animation)

 

transform(变形)全解:

可以到MDN上查看,里面详细把每个属性都给了一个详细的例子,教会你如何使用。

https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform

 

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)

    具体代码:http://js.jirengu.com/kefewikabe/1/edit

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

         具体代码:http://js.jirengu.com/kiyarowelo/1/edit

 

2.scale-缩放

常用写法:

scale( <number> , <number>? )
scaleX( <number> )
scaleY( <number> )

这里是放大1.5倍

具体代码:http://js.jirengu.com/bojasifenu/1/edit

注:同样也支持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轴转动,默认就是垂直与屏幕的轴*/

具体代码:http://js.jirengu.com/fegajoqece/1/edit

 

4.skew-倾斜

常用写法:

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

具体代码:http://js.jirengu.com/sabokuxowa/1/edit

 

合并:transform的多重效果

可以组合使用,空格隔开。

/*放大1.5倍,旋转45度*/
  transform:scale(1.5) rotate(45deg);
  transform:scale(0.5) translate(-100%,-100%);
  transform:none;/*取消所有*/

具体代码:http://js.jirengu.com/hicozulavo/1/edit



transition:过渡

推荐看MDN:https://developer.mozilla.org/zh-CN/docs/Web/CSS/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>

具体代码:http://js.jirengu.com/lejokexefa/1/edit


语法格式:

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

具体过渡方式:https://developer.mozilla.org/zh-CN/docs/Web/CSS/timing-function

 

注意:

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

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:动画

可以到MDN查看详情:https://developer.mozilla.org/zh-CN/docs/Web/CSS/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/   

具体代码http://js.jirengu.com/dorozamite/1/edit

可以添加任意数量想添加的中间帧,它会按照你给的线路进行移动

 


 

@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

具体代码:http://js.jirengu.com/heleraweva/2/edit

  • 使用animation

具体代码:http://js.jirengu.com/guruzekibo/1/edit