js 弹簧效果代码


虽然说的是弹簧效果,但实际上要实现的是定点坐标之间的加速和减速移动。 点到点的移动应该都知道怎么做,这里是通过设置滑动对象的left来实现的。

  而减速效果,一般的做法是通过用目标值减当前值除以一个系数(一般为正整数),得到一个步长。

  然后当前值加上这个步长作为新的当前值,然后反复取值直到当前值等于目标值。 由于这样得到的步长是越来越小的,而步长就是移动的值,所以就做成减速效果。

  那如何做加速效果呢?

  由于取不到能对应减速步长的加速的步长(或者有方法我想不到),所以我想了个方法, 一开始先把所有减速的步长算出来,放到一个数组中,作为减速时的步长,那加速的步长就是这个数组的反转了(即倒过来)。 这个部分主要在SetStep()函数中,可参照代码。

  其他部分在代码中都有说明。

  程序代码:

var $ = function (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 > 0) this.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 = this; this._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:
<style type="text/css">
.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=" 渐 小 " />

测试代码:

new Bounce("idContainer", "idBounce", 250, 200);
var o = new Bounce("idContainer1", "idBounce1", 250, 200, {
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; }

  运行可以看到效果

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>javascript弹簧效果</title>
<script type="text/javascript">
var $ = function (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 > 0) this.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 = this; this._timer = xywTimeout(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;
}
};
window.xywxff=function(){
  new Bounce("idContainer", "idBounce", 250, 200);
  var o = new Bounce("idContainer1", "idBounce1", 250, 200, {
    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; }
}
</script>
</head>
<body>
<style type="text/css">
.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>

  范围渐变反弹:

<div id="idContainer1" class="container">
<div id="idBounce1" class="bounce"> </div>
</div>

  自定范围反弹:

<div id="idContainer2" class="container">
<div id="idBounce2" class="bounce"> </div>
</div>

  范围:

<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=" 渐 小 " />
</body>
</html>


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3