Home » Code » 简易图片轮播(二)-改进动画

简易图片轮播(二)-改进动画

接着原简易图片轮播继续完善之。原文中不考虑切换方式,已经比较完美了,要说有瑕疵可能就是切换动画了,匀速运行可能比较简单了点。有一种速度跟距离成一定比例的缓冲运动,放上去可能高大上一点儿。不用变动太多,只需把速度改为离终点的距离除以某一常数即可。将animate函数修改为:

function animate(offset){
	var newLeft = parseInt(list.style.left) + offset;	
	function go(){
		speed = (newLeft - parseInt(list.style.left))/10;
		speed = speed > 0?Math.ceil(speed): Math.floor(speed);
		if((speed > 0 && newLeft > parseInt(list.style.left) - speed) 
			|| (speed < 0 && newLeft < parseInt(list.style.left) - speed)){
			animated = false;
			list.style.left = parseInt(list.style.left) + speed + 'px';
			setTimeout(go, 30);//反复执行
		}else{
			list.style.left = newLeft + 'px';
			...

修改后,切换开始时候速度最大,随着离终点距离越来越小,速度越来越慢。

这样就完美了吗?显示不是,单就切换效果来说,只是速度上的变化,还是比较简单且单一。有时候还想要透明度上的变化淡入淡出。为方便的对元素进行各种运动,应该封装起来,这方面妙味课堂的运动框架课程在网上比较火,看着跟做了一下。这里的运动公式基于Tween,这个来自flash的东西,里面深奥的数学理论不做探讨,只要知道给定t(time,从0到持续时间的中间时间值)、b(begin,开始位置)、c(change,起点至终点要改变的值,也即路程)、d(duration,完成整个行程所需的时间),即返回在该时间点应该在的位置,即由时间得到已走路程。

function startMove(obj, json, time, easing, fn){
	var startTime = now();
	var currentTime;//已运行时间
	var current = {};//起始值
	for(var attr in json){
		current[attr] = getStyle(obj, attr);
	}

	clearInterval(obj.timer);

	obj.timer = setInterval(function(){
		//var animated = true;//通过Tween计算的值肯定能达到目标值
		for(var attr in json){//attr即为具体属性名了
			var nowTime = now();
			currentTime = Math.min(nowTime - startTime, time);
			//t,b,c,d,当前时间(从0到持续时间中间的值),开始位置,变化量,持续时间
			var value = Tween[easing](currentTime, current[attr], json[attr] - current[attr], time);
			setStyle(obj, attr, value);

		}
		if(currentTime == time){
			clearInterval(obj.timer);
			if(fn){
				fn();
			}
		}

	},13);

}

function getStyle(obj, attr){
	if(obj.currentStyle){
		if(attr == 'opacity'){
			return Math.round(parseFloat(obj.currentStyle[attr])*100);
		}else{
			return parseInt(obj.currentStyle[attr]);
		}

	}else{
		if(attr == 'opacity'){
			return Math.round(parseFloat(getComputedStyle(obj, null)[attr])*100);
		}else{
			return parseInt(getComputedStyle(obj, null)[attr]);
		}
	}
}

function setStyle(obj, attr, value){
	if(attr == 'opacity'){
		obj.style.opacity = 'alpha(opacity:'+value+')';
		obj.style.opacity = value/100;
	}else{
		//这里不能用obj.style.attr ?点后面不能是变量?
		obj.style[attr] = value + 'px';
	}
}

function now(){
	return (new Date()).getTime();
}

以上,以自己的理解记录下startMove函数的实现过程,写得比较初级。其中应用Tween时要获得当前已运行时间t,原老师讲得比较繁琐个人感觉,直接相减应该就可以了,当运行时间大于给定总时间时就取总时间,并清除定时器,应该就可以了。至于Tween的具体内容,整理自网络,后面补上。

这里封装的startMove函数,其实基本就是jquery里面的animate,参数1要运动的dom对象,参数2目标样式属性及其值的集合,参数3运行时间,参数4回调。

有了这个startMove,用javascript写与运动有关的效果就比较方便了。下一篇,就用这个函数在动画和切换方式上再完善一下这个轮播。

附:Tween运动公式

var Tween = {
    Linear: function(t,b,c,d){ return c*t/d + b; },

    QuadeaseIn: function(t,b,c,d){
        return c*(t/=d)*t + b;
    },
    QuadeaseOut: function(t,b,c,d){
        return -c *(t/=d)*(t-2) + b;
    },
    QuadeaseInOut: function(t,b,c,d){
        if ((t/=d/2) < 1) return c/2*t*t + b;
        return -c/2 * ((--t)*(t-2) - 1) + b;
    },

    CubiceaseIn: function(t,b,c,d){
        return c*(t/=d)*t*t + b;
    },
    CubiceaseOut: function(t,b,c,d){
        return c*((t=t/d-1)*t*t + 1) + b;
    },
    CubiceaseInOut: 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;
    },

    QuarteaseIn: function(t,b,c,d){
        return c*(t/=d)*t*t*t + b;
    },
    QuarteaseOut: function(t,b,c,d){
        return -c * ((t=t/d-1)*t*t*t - 1) + b;
    },
    QuarteaseInOut: 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;
    },

    QuinteaseIn: function(t,b,c,d){
        return c*(t/=d)*t*t*t*t + b;
    },
    QuinteaseOut: function(t,b,c,d){
        return c*((t=t/d-1)*t*t*t*t + 1) + b;
    },
    QuinteaseInOut: 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;
    },

    SineeaseIn: function(t,b,c,d){
        return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
    },
    SineeaseOut: function(t,b,c,d){
        return c * Math.sin(t/d * (Math.PI/2)) + b;
    },
    SineeaseInOut: function(t,b,c,d){
        return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
    },

    ExpoeaseIn: function(t,b,c,d){
        return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
    },
    ExpoeaseOut: function(t,b,c,d){
        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
    },
    ExpoeaseInOut: 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;
    },

    CirceaseIn: function(t,b,c,d){
        return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
    },
    CirceaseOut: function(t,b,c,d){
        return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
    },
    CirceaseInOut: 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;
    },

    ElasticeaseIn: function(t,b,c,d,a,p){
        if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
        if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
        else var 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;
    },
    ElasticeaseOut: function(t,b,c,d,a,p){
        if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
        if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
        else var 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);
    },
    ElasticeaseInOut: 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);
        if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
        else var 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;
    },

    BackeaseIn: function(t,b,c,d,s){
        if (s == undefined) s = 1.70158;
        return c*(t/=d)*t*((s+1)*t - s) + b;
    },
    BackeaseOut: 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;
    },
    BackeaseInOut: 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;
    },

    BounceeaseIn: function(t,b,c,d){
        return c - Tween.Bounce.easeOut(d-t, 0, c, d) + b;
    },
    BounceeaseOut: 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;
        }
    },
    BounceeaseInOut: function(t,b,c,d){
        if (t < d/2) return Tween.Bounce.easeIn(t*2, 0, c, d) * .5 + b;
        else return Tween.Bounce.easeOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
    },

};

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Time limit is exhausted. Please reload CAPTCHA.