您的位置:首页 > Web前端

一个前端博客(10)——动画

2015-11-03 15:02 323 查看
最简单的运动

var box = document.getElementById("box");
setInterval(function(){
box.style.left = box.offsetLeft + 1 + ‘px’;
},50);


创建Tar的运动效果方法animate:

Tar.prototype.animate = function(obj){
for(var i = 0; i < this.elements.length; i++) {

}
return this;
}


首先我们说一下参数obj。

参数obj是一个对象

{
"attr"  : "",//动画的属性,参数:x,y,w,h。x == left, y == top, w ==width, h == height,默认为left
"start" : "",//运动的开始位置,默认为当前的位置
"t"     : "",//运动的时间,默认为30
"step"  : "",//速度,默认为10
"target": "",//目标位置,*px
"alter" : "",//增量,*px
"speed" : "",//缓冲值,默认为6
"type"  : ""//是否缓冲,1为缓冲,0为不缓冲。默认为缓冲
}


对应这些参数我们需要创建相应的变量。通过三元操作符,来赋予各个变量的值。

比如第一个参数attr:

var attr = obj['attr'] == 'x' ? 'left' : obj['attr'] == 'y' ? 'top' : obj['attr'] == 'w' ? 'width' :
obj['attr'] == 'h' ? 'height' : 'left';


类似的:

var start = obj['start'] != undefined ? obj['start'] : getStyle(element, attr);
var t     = obj['t'] != undefined ? obj['t'] : 30;
var step  = obj['step'] != undefined ? obj['step'] : 10;


不过这里:

var target = obj['target'];
var alter  = obj['alter'];


由于他们不能同时存在,也不能同时不存在。当增量alter存在的时候,通过 "起始量" + "增量" 就可以得到 "目标量".而有了目标量,增量就可以不用管了。于是有了下面的代码:

if(alter != undefined && target == undefined) {
target = alter + start;
}else if(alert == undefined && target == undefined) {
throw new Error('alter增量或者target目标量必须传递一个!');
}


最后两个参数:

var speed = obj['speed'] != undefined ? obj['speed'] : 6;
var type = obj['type'] == 0 ? 'constant' : obj['type'] == 1 ? 'buffer' : 'buffer';


参数问题解决了,下面要解决的是关于step的问题。如果目标比开始的位置要大,那么step应该为正的,如果目标比开始的位置小,那么step应该为负值。然而我们传递的参数一直都是正值。所以这里我们需要判断一下,来决定step的值为正还是负。

if(target < start) step = -step;


然后我们开始第一步运动,就是让元素从start的位置开始,并且我们要清除全局的timer定时器,因为我们后面就是通过timer来实现运动的,这个看前面的运动基本原理就知道了,清除它是为了方式产生多个定时器而造成我们不想要的效果。

elment.style = start + 'px';
clearInterval(window.timer);


接下来我们开始定时器的部分:

timer = setInterval(functtion(){}, t);


运动的核心就是element.style[attr] = getStyle(element,attr) + step + "px";

运动停止的条件是:

如果step>0,那么当当前的位置大于目标的时候停止。不过这会出现奇怪的现象:比如向右移动会在最后向左运动一下。原因很简单,走过头了。所以这里我们不采用这种方式来判断。而是这样:

如果step>0,那么当当前位置与目标位置的差距的绝对值 小于等于step的时候,元素直接到达目标位置,并且停止运动。因为最后一步是正好到达。所以不会有奇怪的效果出现。同理,如果step<0,那么当当前位置与目标位置的差距小于等于step的绝对值的时候(PS:此时step为负值),元素直接到达目标位置,并且停止运动。

这里还有一个问题,step可不可能为0呢?这个我们稍后再说。

停止运动,就是将元素设置为目标位置后清除定时器。我们可以把它封装起来,当做一个函数。

function setTarget() {
element.style[attr] = target + 'px';
clearInterval(timer);
}


那么定时器里的代码如下:

if(step > 0 && Math.abs(getStyle(element, attr) - target) <= step) {
setTarget();
}else if(step < 0 && (getStyle(element, attr) - target) <= Math.abs(step)) {
setTarget();
}else {
element.style[attr] = getStyle(element,attr) + step + "px";
}


下面我们来说一下step==0的问题。这里我们一直没有用到缓冲变量。我们先讲一下缓冲的实现:

这里我们默认缓冲为由快到慢,一般来说这个速率是通过每次运动后, temp = 目标位置 和 当前位置 的差距 除以缓冲值speed 得到的。又由于step有正值和负值,所以通过判断step的正负,分别使用Math.ceil向上取整和Math.floor向下取整。正值的时候使用Math.ceil,小数部分进一位。负数的时候使用Math.floor,小数部分进一位。这样就不会导致结束运动的时候不流畅突兀的感觉。

所以代码如下:

if(type == 'buffer') {
var temp = (getStyle(element, attr) - target) / speed;
step = step > 0 ? Math.ceil(temp) : Math.floor(temp);
}


由于缓冲的原因,step的值是改变的,会有某个时刻,step的值为0。这个时候,就直接调用setTarget()就可以了。

最后代码如下:

Tar.prototype.animate = function() {
for(var i = 0; i < this.elements.length; i++) {
var element = this.elements[i];
var attr = obj['attr'] == 'x' ? 'left' : obj['attr'] == 'y' ? 'top' : obj['attr'] == 'w' ? 'width' :
obj['attr'] == 'h' ? 'height' : 'left';
var start = obj['start'] != undefined ? obj['start'] : getStyle(element, attr); var t = obj['t'] != undefined ? obj['t'] : 30; var step = obj['step'] != undefined ? obj['step'] : 10;
var target= obj['target'];
var alter = obj['alter'];
if(alter != undefined && target == undefined) { target = alter + start; }else if(alert == undefined && target == undefined) { throw new Error('alter增量或者target目标量必须传递一个!'); }
var speed = obj['speed'] != undefined ? obj['speed'] : 6; var type = obj['type'] == 0 ? 'constant' : obj['type'] == 1 ? 'buffer' : 'buffer';

if(target < start) step = -step;
this.elements[i].style = start + 'px';
clearInterval(window.timer);
timer = setInterval(function() {
if(type == 'buffer') { var temp = (getStyle(element, attr) - target) / speed; step = step > 0 ? Math.ceil(temp) : Math.floor(temp); }
if(step == 0){
setTarget();
}
else if(step > 0 && Math.abs(getStyle(element, attr) - target) <= step) { setTarget(); }else if(step < 0 && (getStyle(element, attr) - target) <= Math.abs(step)) { setTarget(); }else { element.style[attr] = getStyle(element,attr) + step + "px"; }
}, t);
function setTarget() { element.style[attr] = target + 'px'; clearInterval(timer); }
}
return this;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: