1. 时间实现动画效果
var div = document.querySelector("div"); var distance = 1000; //总共的距离 var duration = 2000; //总共的时间 var initLeft = div.offsetLeft; //初始化left值 var startTime = new Date(); //动画开始时间 setTimeout(function fun(){ var p = Math.min(1,(new Date() - startTime) / duration); //获取当前时间所占总共时间的比例 div.style.left = initLeft + distance * p + "px"; //改变left值为 算出来的距离(总距离*占的比例) if(p == 1) return; setTimeout(fun,20); },20)
2. transform属性
原点在最左上角,往右是x的正方向,往下是y的正方向
transform
表示转换 它一定在没有加这个属性之前的基础上开始变换
它的属性值相当于是一个函数调用吧
translate
平移
rotate(30deg)
旋转,值的单位是deg 表示度的意思
默认的旋转的中心是当前元素的中心
可以利用 transform-origin : 100px 0px
改变旋转中心
像素是在自身的左上角为基础,左上角就是0 0
右上角:自身宽度 0px
;
正值表示顺时针旋转,负值表示逆时针转换
var div = document.querySelector("div"); var distance = 1000; //总共的距离 var duration = 2000; //总共的时间 var startTime = new Date(); //动画开始时间 setTimeout(function fun(){ var p = Math.min(1,(new Date() - startTime) / duration); //获取当前时间所占总共时间的比例 div.style.transform = translate(""+distance * p +"px,100px"); if( p == 1) return; setTimeout(fun,20); },20);
如果要进行无限循环,可以将判断条件改为:
if( p == 1) { startTime = new Date(); }
3. 运动算子
-
匀速运动
t
-
匀速反方向运动
1-t
-
匀加速运动
t * t
-
匀减速运动
(2 - t) * t
-
先加速后减速
(t *= 2) < 1 ? .5 * t * t : .5 * (1 - (--t) * (t - 2))
-
4次方加速
t * t * t * t
-
4次方减速
1 - (--t) * t * t * t
-
弹跳
bounce: function (t){ var s = 7.5625, r; if (t < (1 / 2.75)){ r = s * t * t; }else if (t < (2 / 2.75)){ r = s * (t -= (1.5 / 2.75)) * t + .75; }else if (t < (2.5 / 2.75)){ r = s * (t -= (2.25 / 2.75)) * t + .9375; }else{ r = s * (t -= (2.625 / 2.75)) * t + .984375; } return r; }
水平抛物
var div = document.querySelector("div"); var distance = 1000; var duration = 2000; var startTime = Date.now(); requestAnimationFrame(function fun(){ var p = Math.min(1,(Date.now() - startTime) / duration); div.style.transform = "translate("+ distance * p +"px,"+ 500 * p * p +"px)"; requestAnimationFrame(fun); });
正弦运动
var div = document.querySelector("div"); var distance = 300; var duration = 2000; var startTime = Date.now(); requestAnimationFrame(function fun(){ var p = Math.min(1,(Date.now() - startTime) / duration); div.style.transform = "translate("+ distance * p +"px,"+ -distance * Math.sin( 2 * Math.PI * p) +"px)"; requestAnimationFrame(fun); });
4. 动画序列
//实现3个动画,先向右线性运动,再向下弹跳运动,再向左弹跳运动 var div = document.querySelector("div"); var btns = document.querySelectorAll("button"); var distance = 1000; var animator = new Animator( [1000,2000,1000,2000], //表示周期数组 [Easing.bounce,Easing.linear,Easing.bounce,Easing.linear], //运动算子函数 [function (e) { div.style.transform = "translate("+ distance * e +"px,0px)"; },function (e) { div.style.transform = "translate("+ distance + "px,"+ 300 * e +"px)"; },function (e) { div.style.transform = "translate("+ distance * (1 - e) +"px,"+ 300 +"px)"; },function (e) { div.style.transform = "translate(0px,"+ 300 *(1 - e) +"px)"; }] ); btns[0].onclick = function () { animator.start(); }; btns[1].onclick = function () { animator.stop(); };
//js文件 /* 参数一:时间周期 参数二:动画类型,传进来一个函数 参数三:运行代码的函数 */ function Animator(durations, easings, fns) { this.durations = durations; this.easings = easings; this.fns = fns; } //开始运行的方法 写入原型中 利用替换法 Animator.prototype = { constructor: Animator, //参数一: 执行的次数 start: function () { var durations = this.durations, easings = this.easings, fns = this.fns; var that = this; //因为在下面定时器中的fun访问到的是执行fun函数的那个对象 (其实是window) var index = 0; // 运动的数组中的索引 var startTime = new Date(); that.timeId = requestAnimationFrame(function fun() { var p = Math.min(1,(new Date() - startTime) / durations[index]); var e = easings[index](p); fns[index](e); if( p == 1){ index++; if(index < durations.length){ startTime = new Date(); that.timeId = requestAnimationFrame(fun); } }else{ that.timeId = requestAnimationFrame(fun); } }); }, stop: function () { cancelAnimationFrame(this.timeId); } };