@15013890200
2018-10-17T15:02:17.000000Z
字数 3413
阅读 515
animation
requestAnimationFrame
setInterval
对前端人员来说,要想做出酷炫的动画效果还是需要下点功夫的,实现的途径也是有很多的,以下介绍和比较实现动画效果的几种途径。
通过控制元素的一个或多个属性再设置相关过渡时间就可以实现较为简单的过渡动画了(需要做兼容)
特点:可以用来做某一过程的动画。
.class{...,transtion width 0.5s;-webkit-transition: width 0.5s;}
使用比transition略复杂,但是功能比transition更多。(需要做兼容)
特点:不仅可以做某一过程的动画还可以做循环动画。还可以定义每一个过程怎样执行。但是很难控制动画的执行与暂停,一般用来做纯展示,不涉及到交互。
.class{...,animation move 0.5s infinite;}
@keyframes move{
from {...}
to {...}
/** 也可以自定义过程细节 */
}
利用定时器不停调用某一动画过程,实现特定动画效果。可以很方便的控制动画的执行
如果是做不断重复动画效果interval的使用要优于timeout
缺点:很耗性能,重复调用某个动画很可能出现丢帧的现象(js单线程的缘故)
web api接口,通过传入回调函数,不断的触发动画执行。相应的取消执行接口为cancelAnimationFrame方法,用法类似于clearTimeout和clearInterval。
特点:性能要优于setTimeout和setInterval。
与#3的区别:
定时器是代码定时告知浏览器执行某一过程,当遇到线程阻塞时,执行时间就会后移,从而产生丢帧现象。web api是浏览器层面的主动行为,优化了动画的执行过程。以下附上animation、setInterval、requestAnimationFrame三者的使用demo
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>requestAnimationFrame API</title>
<style>
.div_rotate{width: 200px;height: 200px;border:1px solid #ddd;display: flex;align-items: center;justify-content: center;border-radius: 5px;background-color: #ddd;position: relative;user-select: none;float: left;}
.div_rotate2{width: 400px;height: 400px;border:1px solid #ddd;display: flex;align-items: center;justify-content: center;border-radius: 50%;background-color: #ddd;margin-left: 100px;user-select: none;float: left;background: url(imgs/award2.png) no-repeat center;background-size: 100% 100%;}
@-webkit-keyframes move{
/*20%{margin-left: 100px;width: 100px;height: 200px;}
50%{height: 300px;width: 100px;}
100%{background-color: #bbb;}*/
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
@keyframes move{
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
</style>
</head>
<body>
<div class="div_rotate">hhh</div>
<div class="div_rotate2"></div>
<script type="text/javascript">
var util = {
addListener: function(ele,type,handle){
if(ele.addEventListener){
ele.addEventListener(type,handle);
}
else if(ele.attachEvent){
ele.attachEvent('on'+type,handle);
}
else{
ele['on'+type] = handle;
}
},
removeListener: function(ele,type,handle){
if(ele.removeListener){
ele.removeListener(type,handle);
}
else if(ele.detachEvent){
ele.detachEvent('on'+type,handle);
}
else{
ele['on'+type] = null;
}
}
}
var div_rotate = document.querySelector('.div_rotate');
util.addListener(div_rotate,'click',rotate);
/** 借助css3实现动画轮转 **/
function rotate(e){
e = e || window.event;
var target = e.target || e.srcElement;
if(target.style.animation){
target.style.animation = '';
target.style['-webkit-animation'] = '';
}
else{
target.style.animation = 'move .1s infinite';
target.style['-webkit-animation'] = 'move .1s infinite';
}
}
var div_rotate2 = document.querySelector('.div_rotate2');
var animationId = null,intervalId = null;
util.addListener(div_rotate2,'click',ctrlRotate)
function rotate2(){
var target = div_rotate2;
var deg = target.style.transform;
if(deg){
deg = deg.match(/rotate\((\d*)deg/)[1];
deg = parseInt(deg)+15;
}
else{
deg = 15;
}
target.style.transform = 'rotate(' + deg + 'deg)';
/** 调用requestAnimationFrame api实现轮转动画,性能更好 **/
if(window.requestAnimationFrame){
if(animationId)window.cancelAnimationFrame(animationId)
animationId = window.requestAnimationFrame(rotate2)
}
}
function ctrlRotate(){
/** 借用interval实现动画轮转 **/
// if(intervalId){
// clearInterval(intervalId);
// intervalId = null;
// }
// else{
// intervalId = setInterval(function(){
// rotate2();
// },16)
// }
/** 借助requestAnimationFrame **/
if(animationId){
window.cancelAnimationFrame(animationId);
animationId = null;
}
else{
rotate2();
}
}
ctrlRotate()
</script>
</body>
</html>