上次做图片滑动展示效果时做了减速效果,就想做一个加速效果。结合起来就想到了下面这个东西,当然只是类似弹簧,而不是真正的弹簧。

先看效果:
固定范围反弹:

范围渐变反弹:

自定范围反弹:

范围:


程序说明:
虽然说的是弹簧效果,但实际上要实现的是定点坐标之间的加速和减速移动。
点到点的移动应该都知道怎么做,这里是通过设置滑动对象的left来实现的。
而减速效果,一般的做法是通过用目标值减当前值除以一个系数(一般为正整数),得到一个步长。
然后当前值加上这个步长作为新的当前值,然后反复取值直到当前值等于目标值。
由于这样得到的步长是越来越小的,而步长就是移动的值,所以就做成减速效果。
那如何做加速效果呢?
由于取不到能对应减速步长的加速的步长(或者有方法我想不到),所以我想了个方法,
一开始先把所有减速的步长算出来,放到一个数组中,作为减速时的步长,那加速的步长就是这个数组的反转了(即倒过来)。
这个部分主要在SetStep()函数中,可参照代码。
其他部分在代码中都有说明。

程序代码:
 (id) {
    return "string" == typeof id ? document.getElementById(id) : id;
};


function addEventHandler(oTarget, sEventType, fnHandler) {
    
if (oTarget.addEventListener) {
        oTarget.addEventListener(sEventType, fnHandler, 
false);
    } 
else if (oTarget.attachEvent) {
        oTarget.attachEvent(
"on" + sEventType, fnHandler);
    } 
else {
        oTarget[
"on" + sEventType] = fnHandler;
    }
};

var Class = {
  create: 
function() {
    
return function() {
      
this.initialize.apply(this, arguments);
    }
  }
}

Object.extend 
= function(destination, source) {
    
for (var property in source) {
        destination[property] 
= source[property];
    }
    
return destination;
}


var Bounce = Class.create();
Bounce.prototype 
= {
  
//容器对象,滑动对象,原始位置,移动范围
  initialize: function(container, obj, iOrigin, iRange, options) {
    
    
this._obj = $(obj);//滑动对象
    this._xo = parseInt(iOrigin);//中轴坐标(即原来坐标)
    this._xt = 0;//目标坐标
    this._xs = [];//目标坐标集合
    this._steps = [];//步长集合
    this._fast = true;//是否加速
    
    
this.Range = iRange || 0;//滑动范围(宽度)
    
    
this.SetOptions(options);
    
    
this.Step = parseInt(this.options.Step);
    
this.Time = parseInt(this.options.Time);
    
this.Zoom = parseInt(this.options.Zoom);
    
this.Reduce = !!this.options.Reduce;
    
this.Min = parseInt(this.options.Min);
    
this.Max = parseInt(this.options.Max);
    
this.onMin = this.options.onMin;
    
this.onMax = this.options.onMax;
    
this.onSide = this.options.onSide;
    
    
//样式设置
    $(container).style.position = "relative";    
    
this._obj.style.position = "absolute";
    
this._obj.style.left = this._xo + "px";
    
    
if(this.Range > 0this.Start();
  },
  
//设置默认属性
  SetOptions: function(options) {
    
this.options = {//默认值
        Step:        10,//滑动变化率
        Time:        10,//滑动延时
        Zoom:        0,//缩放变化率
        Reduce:        true,//是否缩小
        Min:        0,//最小范围
        Max:        0,//最大范围
        onMin:        function(){},//到达最小时执行
        onMax:        function(){},//到达最大时执行
        onSide:        function(){}//到达边界时执行
    };
    Object.extend(
this.options, options || {});
  },
  
//从轴点开始
  Start: function(iRange) {
    clearTimeout(
this._timer);
    
//iRange有值的话重新设置滑动范围
    if(iRange) this.Range = iRange;
    
//是否到了最小点
    if(this.Reduce && (this.Range <= 0 || this.Range <= this.Min)) { this.onMin(); return; }
    
//是否到了最大点
    if(!this.Reduce && (this.Max > 0 && this.Range >= this.Max)) { this.onMax(); return; }
    
//重置位置
    this._obj.style.left = this._xo + "px";
    
//设置目标坐标集合(iRange可能会变化所以每次都要设置)
    this._xs = [this._xo + this.Range, this._xo, this._xo - this.Range, this._xo];
    
//设置为加速状态
    this._fast = false;
    
//开始分段移动
    this.Set();
  },
  
//从分段开始
  Set: function() {
    
//目标坐标都到达后返回
    if(this._xs.length <= 0){
        
//缩放变化率有值的话重新设置范围
        if(this.Zoom > 0) { this.Range += (this.Reduce ? -1 : 1* this.Zoom; }
        
this.Start(); return;
    }
    
//取得目标坐标
    this._xt = this._xs.shift();
    
//目标坐标是中轴点说明现在是在边界上
    if(this._xt == this._xo) this.onSide();    
    
//设置步长
    this.SetStep();
    
//开始移动
    this.Move();
  },
  
//移动
  Move: function() {
    clearTimeout(
this._timer);
    
//步长走完即到达目标坐标就返回
    if (this._steps.length <= 0) { this.Set(); return; }
    
//执行移动
    this._obj.style.left = (parseInt(this._obj.style.left) + this._steps.shift()) + "px";
    
//循环移动
    var oThis = thisthis._timer = setTimeout(function(){ oThis.Move(); }, this.Time);
  },
  
//设置步长
  SetStep: function() {
    
var iTemp = parseInt(this._obj.style.left);
    
    
//注意是从大到小排的
    this._steps = [];
    
    
if(this.Step >= 1){
        
var i = 0;
        
do{
            i 
= (this._xt - iTemp) / this.Step;
            
//步长不能包含0
            if (i == 0) { break; } else if (Math.abs(i) < 1) { i = i > 0 ? 1 : -1; }
            
this._steps.push(i = parseInt(i));
            iTemp 
+= i;
        } 
while (true);
        
//如果是加速的话反转步长集合
        if(this._fast) this._steps.reverse();
    }
    
//加速减速是交替进行的所以每次都要取反
    this._fast = !this._fast;
  }
};

测试html:

.container{border:1px solid #000000;height:50px; width:500px;}
.bounce
{width:10px; height:10px; background:#000000;top:20px;}
</style>
固定范围反弹:
<div id="idContainer" class="container">
  
<div id="idBounce" class="bounce"> </div>
</div>
<br />
范围渐变反弹:
<div id="idContainer1" class="container">
  
<div id="idBounce1" class="bounce"> </div>
</div>
<br />
自定范围反弹:
<div id="idContainer2" class="container">
  
<div id="idBounce2" class="bounce"> </div>
</div>
<br />
范围:
<input id="aa" name="" type="text" value="200" size="8" />
<input id="bb" name="" type="button" value=" 开始 " />
<input id="idFast" name="" type="button" value=" 加速 + " />
<input id="idSlow" name="" type="button" value=" 减速 - " />
<input id="idZoom" name="" type="button" value=" 渐 小 " />

测试代码:
);
    
    var o = new Bounce("idContainer1""idBounce1"250200, {
        Zoom: 
20, Max: 200,
        onMax: 
function(){ o.Reduce = true; o.Start(200); },
        onMin: 
function(){ o.Reduce = false; o.Start(0); }
    });

    
var o2 = new Bounce("idContainer2""idBounce2"250);
    $(
"bb").onclick = function(){ o2.Start(parseInt($("aa").value) || 200); }
    $(
"idFast").onclick = function(){ if(--o2.Step<2){o2.Step=2} }
    $(
"idSlow").onclick = function(){ if(++o2.Step>20){o2.Step=20} }
    $(
"idZoom").onclick = function(){ o2.Zoom=50; }

下载完整测试代码

分类:

技术点:

相关文章: