一、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 动画属性