JavaScript 弹簧效果

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

先看效果:
<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(); //如果是加速的话反转步长集合 if(this._fast) this._steps.reverse(); //加速减速是交替进行的所以每次都要取反 this._fast = !this._fast; //开始移动 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); } } };</script> 固定范围反弹:

范围渐变反弹:

自定范围反弹:

范围:

<script> var b = true; new Bounce("idContainer", "idBounce", 250, 200, { Time: 1, Step: 20, onSide: function(){ $$("idBounce").src = b ? "http://images.cnblogs.com/cnblogs_com/cloudgamer/143727/r_em12.gif" : "http://images.cnblogs.com/cnblogs_com/cloudgamer/143727/r_em11.gif"; b=!b;} }); 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>
程序说明:
虽然说的是弹簧效果,但实际上要实现的是定点坐标之间的加速和减速移动。
点到点的移动应该都知道怎么做,这里是通过设置滑动对象的left来实现的。
而减速效果,一般的做法是通过用目标值减当前值除以一个系数(一般为正整数),得到一个步长。
然后当前值加上这个步长作为新的当前值,然后反复取值直到当前值等于目标值。
由于这样得到的步长是越来越小的,而步长就是移动的值,所以就做成减速效果。
那如何做加速效果呢?
由于取不到能对应减速步长的加速的步长(或者有方法我想不到),所以我想了个方法,
一开始先把所有减速的步长算出来,放到一个数组中,作为减速时的步长,那加速的步长就是这个数组的反转了(即倒过来)。
这个部分主要在 SetStep()函数中,可参照代码。
其他部分在代码中都有说明。

程序代码:
Code

测试html:
Code

测试代码:
Code

下载完整测试代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值