CSS动画

125 阅读4分钟

动画

1.定义

  1. 由许多静止的画面(帧),以一定的速度连续播放时,因肉眼产生的错觉。
  2. 播放速度:每秒24帧(影视),每秒30帧(游戏)。
  3. 一个div从左向右移动的例子: 使用setInterval。
  • 使用浏览器的paint flshing(右上角more tools =>rendering => paint flashing).发现重绘了(repaint)。
  • css渲染过程依次包括布局、绘制、合成。其中布局和绘制可能会省略

性能问题,使用transform

  • demo
  • transform会自动脑补中间帧
  • 没有repaint重绘,性能好

2.文档流相关

3.浏览器渲染原理

相关文章

  1. 渲染树构建、布局、绘制
  2. 渲染性能
  3. 使用transform
  4. css触发什么

浏览器渲染过程

  • 步骤
  1. 根据HTML构建HTML树(DOM)
  2. 根据CSS构建CSS树(CSSOM)
  3. 将2棵树合并成一颗渲染树(render tee)
  4. Layout布局(文档流、盒模型、计算大小和位置)
  5. paint绘制(把边框颜色、文字颜色、阴影等画出来)
  6. compose合成(根据层叠关系型展示画面)
  • 三棵树 sushCD.png

如何更新样式

  • 用JS更新样式
  1. div.style.background='red'
  2. div.style.display='none'
  3. div.classList.add('red')
  4. div.remove()

三种更新方式

sJT9ds.png

  1. 第一种:全更新
  1. 第二种: 跳过layout
  1. 第三章: 跳过layout和paint
  • 改变transform,只需要composite
  1. csstriggers.com/ 所有属性

性能优化

1. css优化:使用will-change 或translate 2. js优化:使用requestAnimationFrame代替setTimeout或者setInterval. 3. 背下来就行

4.transform 全解

  • 四个常用功能
  1. 位移translate
  • translateX()
    where = | ),加问号表示可以省略
  • translateY()
  • translateZ() 且父容器perspective
  • translate(,?)
  • translate(x,y,z)
  • demo
  • 经验
  1. translate(-50%,-50%)可以做绝对定位元素得居中
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>translate 50% 50% </title>
</head>
<body>
  <div class="wrapper">
  <div id="demo">
      
  </div>
</div>
</body>
</html>

#demo{
  width:100px;
  height:100px;
  border:1px solid red;
  position:absolute;
  left:50%;/* 左边缘处于黑框的中间 */
  top:50%;/* 上边线处于中线 */
  transform:translateX(-50%)  translateY(-50%); /* 向左,向上回半个身位。中线对准 。可以缩写为transform:translate(-50%,-50%)。除了IE,是绝对剧中的完美答案*/
  
}
.wrapper{
  border:1px solid black;
  position:relative;
  height:500px;
}

sYSs1J.png

  1. 不会的看文档
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <style>
  #demo{
  width: 100px;
  height: 200px;
  border: 1px solid red;
  margin: 50px;
}

#demo:hover{
  xtransform: translateX(50px);
  xtransform: translateY(-50px);
  transform: translateZ(-200px);
}

.wrapper{
  perspective: 1000px;
  border: 1px solid black;
}
  </style>
</head>
<body>
  <div class="wrapper">
    <div id="demo"></div>
  </div>
</body>
</html>

  1. scale 缩放
  • scaleX() (number倍,如1.5倍)
  • scaleY()
  • scale(<number,?)
  • 用得少,因为容易出现模糊
  1. rotate旋转
  • rotate([ | ])
  • rotateX([ | ])
  • rotateY([ | ])
  • rotateZ([ | ])
  • 一般用360°旋转制作loading
  • 代码
  1. skew倾斜
  1. 代码
<!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:200px;
  border:1px solid red;
  margin:50px;
 transition:all 1s;/*加入动画效果,1s变大 */
}
 #demo:hover{
 /*  transform:scale(1.5);hover上去,变为原来的1.5被 */
   transform:rotate(45deg);/* 默认以垂直屏幕的轴转动 */
  
}

  • 经验
  1. 一般需要配合transition过度
  2. inline元素不支持transform,需要先变为block
  3. translate(50%)
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>translate 50% 50% </title>
</head>
<body>
  <div class="wrapper">
  <div id="demo">
      
  </div>
</div>
</body>
</html>
#demo{
  width:100px;
  height:100px;
  border:1px solid red;
  position:absolute;
  left:50%;/* 左边缘处于黑框的中间 */
  top:50%;/* 上边线处于中线 */
  transform:translateX(-50%)  translateY(-50%); /* 向左,向上回半个身位。中线对准 。可以缩写为transform:translate(-50%,-50%)。除了IE,是绝对剧中的完美答案*/
  
}
.wrapper{
  border:1px solid black;
  position:relative;
  height:500px;
}
  1. transform多重效果
  • transform:scale(0.5) translate(-100%, -100%);
  • transform:none ;取消所有
  1. 练习:跳动的心
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>跳到的心</title>
   <style type="text/css">

       *{
  box-sizing:border-box;
  padding:0px;
  margin:0px;
       }
    #heart{
  margin:100px;
  position:relative;
 /*  border:1px solid black; */
  display:inline-block;
  transition:all 0.5s;
    }
    #heart:hover{
  transform:scale(1.5)
    }
    #heart > .bottom{
  height:50px;
  width:50px;
 /*  border:1px solid red; */
  background:red;
  transform:rotate(45deg);
}    
     #heart > .left{
  height:50px;
  width:50px;
/*   border:1px solid green; */
    background:red;
  border-radius:50%  0  0 50%; /* 四个值,试一下 */
   position:absolute;
  bottom:100%;
  right:100%;
   transform:rotate(45deg) translateX(31px);/* j具体需要试一下 */
 
}  
    #heart > .right{
  height:50px;
  width:50px;
/*   border:1px solid red; */
    background:red;
  border-radius: 50% 50%  0  0;
   position:absolute;
   bottom:100%;
  left:100%;
   transform:rotate(45deg) translateY(31px);
}  

    </style>
</head>
<body>
<div id="heart">
    <div class="left"></div>
    <div class="right"></div>
    <div class="bottom"></div>
  </div>
</body>
</html>

demo

5. transition过渡

文档

文档

作用

补充中间帧

语法

  • transition:属性名 时长 过渡方式 延迟
  • transition: left 200ms linear ;
  • 可以用逗号分隔两个不同的属性, transition:left 200ms, top 400ms;
  • 可以用all代表所有属性,transition: all 200ms;
  • 过渡方式有: linear | ease | ease-in | ease-out | ease-in-out | cubic-bezier |step-start | step-end |steps. 具体查文档。 linear:线性 ease:缓动

demo

demo

并不是所有属性都可以过渡

  1. display:none => block没法过渡
  2. 一般改成visibility:hidden => visible
  3. background渐变:可以过渡
  4. opacity:可以过渡,但不建议用
  5. 过渡必须要有起始。一般只有1次或2次动画。如hover和非hover状态的过渡。

过渡有中间点怎么办

  1. 使用2次transform
  • .a === transform ===> .b
  • .b === transform ===> .c
  • 使用setTimeout或者监听transitionend事件知道到中间点
  1. 使用animation
  • 声明关键帧
  • 添加动画

animation

  1. 一种是from, to
  2. 一种是百分比
@keyframes XXX{
    from {
        transform: translateX( 0% );
    }

    to {
        transform: translateX( 100% );
    }
}

@keyframes XXX{
    0% {
        top:0;
        left:0;
    }
    30% {
        top:50px;
    }
    68%, 80%{
        left:50px;
    }
    100% {
        top:100px;
        left:100%;
    }

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

时长: 1s或者1000ms
过渡方式: 同transition取值
次数: 3 | 4.2 | infinite
方向:reverse | alternate | alternate-reverse
填充模式: none | forwards | backwards | both
是否暂停: paused | running
以上都可以单独设置,具体查看文档
  • 如何让动画停止在最后一帧
    答: animation加forward
  • 跳动的心重做
    demo
    重点
#heart{
  margin:100px;
  position:relative;
 /*  border:1px solid black; */
  display:inline-block;
 animation:heart 1s infinite alternate 800ms;
}

@keyframes heart{
  0%{
    transform:scale(1.0);
  }
   100%{
    transform:scale(1.2);
  }
  
}