前端动画基础

317 阅读5分钟

一、css3动画

首先了解一下css图层的概念 浏览器在渲染一个页面时,会将页面分为很多个图层,在渲染DOM的时候:

1、获取DOM后分割为多个图层

2、对每个图层进行节点进行样式计算

3、为每个节点生成图形和位置(回流)

4、将每个节点绘制填充到图层位图中(绘制)

5、图层作为纹理上传GPU

6、多个图层重组形成页面视图

Chrome中满足以下任意情况就会创建图层:

  • 3D或透视变换(perspective transform)CSS属性
  • 使用加速视频解码的<video>节点
  • 拥有3D(WebGL)上下文或加速的2D上下文的<canvas>节点
  • 混合插件(如Flash)
  • 对自己的opacity做CSS动画或使用一个动画webkit变换的元素
  • 拥有加速CSS过滤器的元素
  • 元素有一个包含复合层的后代节点(一个元素拥有一个子元素,该子元素在自己的层里)
  • 元素有一个z-index较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)

需要注意的是,如果图层中某个元素需要重绘,那么整个图层都需要重绘。每一帧动画浏览器可能会让浏览器重复第2到第6点的操作。

现代浏览器在使用CSS3动画时,以下四种情形绘制的效率较高,分别是:

  • 改变位置(transform)
  • 改变大小
  • 旋转
  • 改变透明度(opacity)

1、animation属性

animation 属性是一个简写属性,用于设置六个动画属性:

描述
animation-name规定需要绑定到选择器的 keyframe 名称。。
animation-duration规定完成动画所花费的时间,以秒或毫秒计。
animation-timing-function规定动画的速度曲线。
animation-delay规定在动画开始之前的延迟。
animation-iteration-count规定动画应该播放的次数。
animation-direction规定是否应该轮流反向播放动画。

注释: 请始终规定 animation-duration 属性,否则时长为 0,就不会播放动画了。

常用几个属性的值:

animation-timing-function 规定动画的速度曲线。

描述
linear动画从头到尾的速度是相同的。
ease默认。动画以低速开始,然后加快,在结束前变慢。
ease-in动画以低速开始。
ease-out动画以低速结束。
ease-in-out动画以低速开始和结束。

animation-direction 规定是否应该轮流反向播放动画。

normal默认值。动画应该正常播放。
alternate动画应该轮流反向播放。

案例:幽灵小猫


<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>动画transform:translate()性能最佳</title>
  <style>
   .move{
    position: absolute;
    top: 0;
    left: 100px;
    width:300px;
    height:300px; 
    animation: demo1 10s linear infinite alternate;//10s完成 速度一致 无数次 反向播放
    text-align: center;
    line-height: 300px;
    color:white;
    font-size: 2em;

   }
   @keyframes demo1{
      from{
        transform: translateX(0);
      }
      to{
        transform: translateX(900px);
      }
     0%{background-color: yellow;}
     50%{background-color: green;}
     100%{background-color:orange;}
    }
  </style>
    
 </head>
 <body>
    <div class="move">我是幽灵小猫菜小彬</div>
 </body>
</html>

2、transtion属性

transition 属性是一个简写属性,用于设置四个过渡属性:

默认:all 0 ease 0

描述
transition-property规定设置过渡效果的 CSS 属性的名称。
transition-duration规定完成过渡效果需要多少秒或毫秒。
transition-timing-function规定速度效果的速度曲线。
transition-delay定义过渡效果何时开始。

transition-timing-function的值可以参考animation

案例:鼠标触碰移动,移开回收

<!DOCTYPE html>
<html>
<head>
<style> 
div
{
	width:100px;
	height:100px;
	background:blue;	
	transition:width 2s;
	-moz-transition:width 2s; /* Firefox 4 */
	-webkit-transition:width 2s; /* Safari and Chrome */
	-o-transition:width 2s; /* Opera */
}

div:hover
{
	width:300px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
//这种写法是针对单个属性,下面介绍习惯写法,针对所有属性,选择哪种取决于需求
div
{
	width:100px;
	height:100px;
	background:blue;	
	transition:all 2s;
}
div:hover{
	transform:scal(1.1,.1);
}

二、javascript动画

1、相对位置偏移量

一个元素在页面中实现移动,即在一段时间内持续改变自己相对页面的位置便能显示动画的效果

关于偏移量

  • 该元素要设置position属性
  • top,left属性可以设置偏移量
  • offsetLeft,offsetTop属性可以设置偏移量
2、obj.offsetwidth与obj.style.width的区别
  • obj.offsetwidth只读属性,不可赋值,结果为一个纯数字
  • obj.style.width使用的前提是元素标签内联有的style样式且width属性存在的情况,可读可以赋值
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
	<title>Document</title>
</head>
<style>
	*{
		padding: 0;
		margin: 0;
	}
	div{
		width: 400px;
		height: 400px;
		padding: 10px;
		border: 10px solid #ccc;
		margin: 20px;
		background-color: yellow;
	}
</style>
<body>
	<div ></div>
	<script>
		var  box=document.querySelector("div");
		box.offsetWidth=300;//不能赋值
		console.log(box.offsetWidth);//440,一个纯数字不带单位
		
		console.log(box.style.width);//没有内联style且width属性不存在,无法读取
		var a=500
		box.style.width=a+"px";//可以赋值,注意赋值的形式
//		box.style.width=600+"px";//可以赋值,注意赋值的形式
//		box.style.width="700px";//可以赋值,注意赋值的形式
		console.log(box.style.width);//赋值成功,可以读取,结果500px

	</script>
</body>
</html>
3、定时器setIntervel()
var tag=setInterval(function(){ alert("Hello"); }, 3000);//每3000毫秒执行一次函数
console.log(tag);//1,返回一个 ID(数字),可以将这个ID传递给clearInterval(),clearTimeout() 以取消执行。

注意:

  • 定时器函数在vue代码里,function(){}匿名函数要用()=>{}函数来代替,否则this并不会指向vue对象
  • 定时器函数是一个异步函数,在使用时要解决一个问题就是,每次触发定时器还可能存在上一个定时器在排队执行任务,这就会导致动画效果越来越快,所以每次触发定时器时,必须先清除之前已经存在的定时器,再从新开始

案例:点击开始按钮,盒子向右移动400px

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        *{
            padding: 0;margin: 0;
        }
        #dv{
            width: 200px;
            height: 200px;
            background-color: pink;
            position: relative;
        } 
    </style>
</head>

<body>
    <input type="button" value="开始" id="btn">
    <div id="dv"></div>
    <script>
        var btn=document.getElementById("btn");
        var dv=document.getElementById("dv");

        btn.onclick=function(){
        	
        	if(btn.timeId){//自定义属性,十分高妙,如果存在结果为1,否则在对象btn中加入该属性
                clearInterval(btn.timeId);
            }
        	
        	btn.timeId=setInterval(function(){
        		var target=400;
        		step=17;//每次走增加的距离
        		var back=Math.abs(dv.offsetLeft-target);//若最后的左边的距离超出目标值,需要返回的距离
        		
				//console.log(dv.offsetLeft);//打印当前距离左边的距离
				//console.log(Math.abs(dv.offsetLeft-target));//判断是超过目标值还是没有超过
        		if(dv.offsetLeft<target){
        			dv.style.left= dv.offsetLeft+step+"px";//这里不使用dv.style.left运算是因为返回值带有单位需要转化
        			console.log(dv.style.left);
        		}else{
        			clearInterval(btn.timeId);
        			dv.style.left= dv.offsetLeft-back+"px";//或者直接:dv.style.left= target+"px";
        			//console.log(dv.style.left);
        		}
        	},30)//时间设小点,否则连续点击会有视觉残留
        }
    </script>
</body>

</html>

三、JS动画和CSS3动画的比较

JS动画

缺点:JavaScript在浏览器的主线程中运行,而其中还有很多其他需要运行的JavaScript、样式计算、布局、绘制等对其干扰。这也就导致了线程可能出现阻塞,从而造成丢帧的情况。

优点:JavaScript的动画与CSS预先定义好的动画不同,可以在其动画过程中对其进行控制:开始、暂停、回放、中止、取消都是可以做到的。而且一些动画效果,比如视差滚动效果,只有JavaScript能够完成

CSS动画

缺点:缺乏强大的控制能力。而且很难以有意义的方式结合到一起,使得动画变得复杂且易于出问题。
优点:浏览器可以对动画进行优化。它必要时可以创建图层,然后在主线程之外运行。

参考资料: W3C css3 动画属性