linear(匀速运动的公式)
function linear(t,b,c,d){
return t/d*c+b;//t是走过的时间、d是总时间、c是总路程(灵活的有可能是opacity的变化的值)、b是元素的初始位置
}
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.animate动画的封装</title>
<style>
html,body,div{
margin: 0;
padding: 0;
}
width: 100px;
height: 100px;
background: brown;
border-radius: 50%;
position: absolute;
left: 0;
top: 0;
opacity: 0.4;
}
</style>
</head>
<body>
<div id="box"></div>
<script src="utils.js"></script>
<script>
var oBox=document.getElementById('box');
;(function(){
function linear(t,b,c,d){
return t/d*c+b;
}
function animate(curEle,target,duration,callback){
var begin={};
var distance={};
for(var key in target){//检测当前属性属不属于目标对象
begin[key]=utils.css(curEle,key);
distance[key]=target[key]-begin[key];
console.log(target[key]);
console.log(distance[key])
}
var time=0;
curEle.timer=setInterval(()=>{
time+=17;//走过的时间
if(time>=duration){//如果走过的时间大于等于总时间
utils.css(curEle,target);
clearInterval(curEle.timer);
typeof callback==='function'?callback():null;
return;
}
for(var key in target){
var val=linear(time,begin[key],distance[key],duration );//time是走过的时间,
utils.css(curEle,key,val);
}
},17)
}
function change() {
oBox.style.width=500;
oBox.style.height=700;
oBox.style.background='yellowGreen';
}
animate(oBox,{width:1000,height:1000,opacity:1,left:2500,top:2500},3000,change)
})();
</script>
</body>
</html>
复制代码
utils.js
var utils = (function () {
function offset(curEle) {
var l = curEle.offsetLeft;
var t = curEle.offsetTop;
var p = curEle.offsetParent;
while(p.nodeName !=="BODY"){
l+=p.offsetLeft +p.clientLeft;
t+=p.offsetTop+p.clientTop;
p = p.offsetParent;
}
return {
left:l,top:t
}
};
function getCss(curEle,attr) {
var val;
if("getComputedStyle" in window){
// 先判断是否支持getComputedStyle;
val = getComputedStyle(curEle)[attr];
}else{
val = curEle.currentStyle[attr];
}
// 去单位
var reg = /^(width|height|margin|padding|left|top|right|bottom|fontZise|opacity)$/;
// 校验当前属性是否带有单位
if(reg.test(attr)){
// 判断是否为空;
if(!isNaN(parseFloat(val))){
val = parseFloat(val);
}
}
return val;
}
// setCss : 每执行一次,都会设置元素一个属性样式;
function setCss(curEle,attr,val) {
var reg = /^(width|height|top|left|right|bottom|padding|margin)$/;
if(reg.test(attr)){
if(typeof val==="number"){
val = val + "px";
}
}
curEle.style[attr]=val;// 设置行内样式;
}
function setGroupCss(curEle,obj) {
// 遍历obj;调用封装的setCss,设置元素的单个样式;
for(var key in obj){
setCss(curEle,key,obj[key])
}
}
function css(...arg) {// 在函数定义的括号中,... 是剩余运算符;将所有的实参放入到一个数组中;
//
if(arg.length===3){
// [oBox,"height",300]
setCss(...arg);
}else if(arg.length===2){
if(toString.call(arg[1])==="[object Object]"){
setGroupCss(...arg)
}else{
return getCss(...arg)
}
}
}
function win(attr,val) {
// 如果是两个实参,那么一定是设置;如果是一个实参,是获取;
if(val===undefined){
return document.documentElement[attr] || document.body[attr];
}
document.documentElement[attr] = val;
document.body[attr] = val;
}
return {
offset:offset,
getCss:getCss,
setCss:setCss,
setGroupCss:setGroupCss,
css:css,
win:win
}
})();
// 单例模式
/*
var utils= {
offset:function offset(curEle) {
var l = curEle.offsetLeft;
var t = curEle.offsetTop;
var p = curEle.offsetParent;
while(p.nodeName !=="BODY"){
l+=p.offsetLeft +p.clientLeft;
t+=p.offsetTop+p.clientTop;
p = p.offsetParent;
}
return {
left:l,top:t
}
}
}*/
复制代码
animate.js
(function () {
// 运动方式
var zhufengEffect = {
// 匀速运动公式
Linear: function (t, b, c, d) {
return t/d * c + b;
},
//指数衰减的反弹缓动
Bounce: {
easeIn: function(t, b, c, d) {
return c - zhufengEffect.Bounce.easeOut(d - t, 0, c, d) + b;
},
easeOut: function(t, b, c, d) {
if ((t /= d) < (1 / 2.75)) {
return c * (7.5625 * t * t) + b;
} else if (t < (2 / 2.75)) {
return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
} else if (t < (2.5 / 2.75)) {
return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
} else {
return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
}
},
easeInOut: function(t, b, c, d) {
if (t < d / 2) {
return zhufengEffect.Bounce.easeIn(t * 2, 0, c, d) * .5 + b;
}
return zhufengEffect.Bounce.easeOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
}
},
//二次方的缓动
Quad: {
easeIn: function(t, b, c, d) {
return c * (t /= d) * t + b;
},
easeOut: function(t, b, c, d) {
return -c * (t /= d) * (t - 2) + b;
},
easeInOut: function(t, b, c, d) {
if ((t /= d / 2) < 1) {
return c / 2 * t * t + b;
}
return -c / 2 * ((--t) * (t - 2) - 1) + b;
}
},
//三次方的缓动
Cubic: {
easeIn: function(t, b, c, d) {
return c * (t /= d) * t * t + b;
},
easeOut: function(t, b, c, d) {
return c * ((t = t / d - 1) * t * t + 1) + b;
},
easeInOut: function(t, b, c, d) {
if ((t /= d / 2) < 1) {
return c / 2 * t * t * t + b;
}
return c / 2 * ((t -= 2) * t * t + 2) + b;
}
},
//四次方的缓动
Quart: {
easeIn: function(t, b, c, d) {
return c * (t /= d) * t * t * t + b;
},
easeOut: function(t, b, c, d) {
return -c * ((t = t / d - 1) * t * t * t - 1) + b;
},
easeInOut: function(t, b, c, d) {
if ((t /= d / 2) < 1) {
return c / 2 * t * t * t * t + b;
}
return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
}
},
//五次方的缓动
Quint: {
easeIn: function(t, b, c, d) {
return c * (t /= d) * t * t * t * t + b;
},
easeOut: function(t, b, c, d) {
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
},
easeInOut: function(t, b, c, d) {
if ((t /= d / 2) < 1) {
return c / 2 * t * t * t * t * t + b;
}
return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
}
},
//正弦曲线的缓动
Sine: {
easeIn: function(t, b, c, d) {
return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
},
easeOut: function(t, b, c, d) {
return c * Math.sin(t / d * (Math.PI / 2)) + b;
},
easeInOut: function(t, b, c, d) {
return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
}
},
//指数曲线的缓动
Expo: {
easeIn: function(t, b, c, d) {
return (t == 0)
? b
: c * Math.pow(2, 10 * (t / d - 1)) + b;
},
easeOut: function(t, b, c, d) {
return (t == d)
? b + c
: c * (-Math.pow(2, -10 * t / d) + 1) + b;
},
easeInOut: function(t, b, c, d) {
if (t == 0)
return b;
if (t == d)
return b + c;
if ((t /= d / 2) < 1)
return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
}
},
//圆形曲线的缓动
Circ: {
easeIn: function(t, b, c, d) {
return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
},
easeOut: function(t, b, c, d) {
return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
},
easeInOut: function(t, b, c, d) {
if ((t /= d / 2) < 1) {
return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
}
return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
}
},
//超过范围的三次方缓动
Back: {
easeIn: function(t, b, c, d, s) {
if (s == undefined)
s = 1.70158;
return c * (t /= d) * t * ((s + 1) * t - s) + b;
},
easeOut: function(t, b, c, d, s) {
if (s == undefined)
s = 1.70158;
return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
},
easeInOut: function(t, b, c, d, s) {
if (s == undefined)
s = 1.70158;
if ((t /= d / 2) < 1) {
return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
}
return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
}
},
//指数衰减的正弦曲线缓动
Elastic: {
easeIn: function(t, b, c, d, a, p) {
if (t == 0)
return b;
if ((t /= d) == 1)
return b + c;
if (!p)
p = d * .3;
var s;
!a || a < Math.abs(c)
? (a = c, s = p / 4)
: s = p / (2 * Math.PI) * Math.asin(c / a);
return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
},
easeOut: function(t, b, c, d, a, p) {
if (t == 0)
return b;
if ((t /= d) == 1)
return b + c;
if (!p)
p = d * .3;
var s;
!a || a < Math.abs(c)
? (a = c, s = p / 4)
: s = p / (2 * Math.PI) * Math.asin(c / a);
return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
},
easeInOut: function(t, b, c, d, a, p) {
if (t == 0)
return b;
if ((t /= d / 2) == 2)
return b + c;
if (!p)
p = d * (.3 * 1.5);
var s;
!a || a < Math.abs(c)
? (a = c, s = p / 4)
: s = p / (2 * Math.PI) * Math.asin(c / a);
if (t < 1)
return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
}
}
};
/**
*
* @param curEle 当前执行动画的元素
* @param target 目标值对象 {left:500,top:300}
* @param duration 总过渡时间 2000ms
*/
// effect 指定运动方式 传参
// 传一个数字
// 传一个数组 ['Quad','easeInOut']
function move(curEle, target, duration,effect, callBack) {
// 默认运动方式
var tempEffect = zhufengEffect.Linear;
// 判断effect 如果是个数字
if(typeof effect === "number") {
switch (effect) {
case 0:
tempEffect = zhufengEffect.Linear;
break;
case 1:
tempEffect = zhufengEffect.Quad.easeInOut;
break;
case 2:
tempEffect = zhufengEffect.Bounce.easeIn;
break;
case 3:
tempEffect = zhufengEffect.Cubic.easeInOut;
break;
}
} else if(effect instanceof Array) {
//如果以数组方式指定远动方式 ['Quad','easeInOut']
tempEffect = effect.length === 2? zhufengEffect[effect[0]][effect[1]]:zhufengEffect[effect[0]];
} else if(typeof effect === "function") {
callBack = effect;
}
// 执行本次动画之前 清除上次动画
curEle.zfTimer? clearInterval(curEle.zfTimer) : null;
var begin = {}; // 存储元素执行动画前 相应属性初始状态
var change = {}; // 存储元素执行动画 相应属性状态变化值
for(var key in target) {
// target 对象 目标位置
if(target.hasOwnProperty(key)) {
// begin {'left': 'left初始值'}
begin[key] =Number(utils.css(curEle, key));// 获取属性初始值,在obj新增key属性,初始值赋值给begin的key的属性值
// change {'left': 'left变化值'}
console.log(begin[key]);//获取的透明度的
change[key] =target[key] - begin[key]// key属性要变化的值,并且放在change对象中
console.log(change[key]);
}
}
// console.log(begin);
// console.log(change);
var time = null; // 记录当前时间
curEle.zfTimer = setInterval(function () {
time += 10;
if(time >= duration) { // 结束条件
// target:{left: 500, top: 300}
utils.css(curEle,target); // 确保是目标状态
clearInterval(curEle.zfTimer); //结束动画
typeof callBack ==="function"? callBack.call(curEle) : null;
return;
}
// 计算出当前时间 元素相应属性 的状态
// target 有多少个属性 zfEffect.Linear 执行多少次 并且把相应属性的参数传递进去 计算出 当前状态
// 第一次的时候 key 是left 第二次的时候key 是 top
for(var key in target) {
if(target.hasOwnProperty(key)) {
// 计算出 当前时间time 元素相应属性 所处状态
var curPos = tempEffect(time,begin[key],change[key], duration);
// 将当前元素 相应属性 设置为 当前计算出来的状态curPos
utils.css(curEle, key, curPos);
}
}
}, 10);
}
// 把函数放进全局下的zfAnimate
window.zfAnimate = move;
})();
复制代码