做的一个抖动效果,兼容IE6/7/8/FF/OPERA/SAFARI,先看效果:
抖动效果的原理主要是:将需要抖动的元素按上右下左移动。利用Math.sin和Math.cos计算x轴以及y轴的偏移,稍后会提到。
在这里,我首先定义了2个参数,也是在创建实例是可以修改的2个参数
this .options = { z: 3 , // 抖动半径 maxa: 1080 // 总计抖动角度 1080/360圈 } 然后是实例调用的3个方法,这3个方法分别是3种抖动的方式(上下,左右,上下左右),这里需要在调用时给函数传个抖动元素的ID。
PS:mode是抖动方式 "h"左右抖动;"v"上下抖动;"c"上下左右抖动。
h: function (objID){ // 左右抖动 this .oID = objID; this .mode = " h " ; this ._start(); }, v: function (objID){ // 上下抖动 this .oID = objID; this .mode = " v " ; this ._start(); }, c: function (objID){ // 上右下左抖动 this .oID = objID; this .mode = " c " ; this ._start(); } 定义好抖动元素ID和mode之后,我们就执行抖动操作。
_start: function (){ this ._end(); if ( this ._init()){ this .i = setInterval( this ._exe(), 30 ); } } _end()是用来停止上个抖动操作,并还原上个抖动元素的位置。_init()是用来初始化抖动参数。我们把角度还原到0,然后获取对象的left和top。
_init: function (){ this .obj = document.getElementById( this .oID); if ( this .obj){ this .a = 0 ; // 角度 this .os = this .obj.style; this .oleft = this .os.left == " auto " ? 0 : ~~ this .os.left; this .otop = this .os.top == " auto " ? 0 : ~~ this .os.top; return true ; } else { return false ; } } 初始化参数之后,我们就可以使用setInterval来移动我们的元素。我们都知道setInterval里的函数以及内部的this都是指向window的,为了解决这个问题,我这里用了闭包。
_exe: function (){ var object = this ; return function (){ var r = object.a * Math.PI / 180 , x = Math.sin(r) * object.z , y = Math.cos(r) * object.z; if (object.mode == ' c ' || object.mode == ' h ' ){ object.os.left = object.oleft + y + " px " ; } if (object.mode == ' c ' || object.mode == ' v ' ){ object.os.top = object.otop + x + " px " ; } if ( (object.a += 90 ) > object.maxa ){ object._end(); } } } 上面我们已经谈到了,抖动的原理就是将元素上下左右画圆的偏移,如果只是需要将其偏移幅度设定为直角,那我们可以直接oleft+z otop+z来进行处理,但当我们将幅度设定为30° 45°的时候,显然就行不通了,这个时候我们就根据半径z来计算x和y了,我们的三角函数cos/sin就派上用场了(还记得这两个函数吗(^。^)y-~~)。通过sin计算x轴,通过cos计算y轴,这里需要注意的是,在javascript里,sin和cos里的参数不再是角度,而是弧度,将角度乘以 0.017453293 (2PI/360)即可转换为弧度。当我们的偏移角度超过我们设定的最大角度,我们即可停止抖动。
PS:参考
js基本原理就是这样,另外需要提醒的是,由于我的偏移使用的是left和top,所以抖动的元素必须增加position:relative||absolute||fixed,使用left而不是使用margin-left,个人感觉在做偏移上left效率更高,下面是完整代码:
View Code <! 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=utf-8" /> < title > 无标题文档 </ title > < script > var extendJson = function (target,src){ for ( var json in src){ target[json] = src[json]; } return target;} var $class = function (constructor,prototype) { var c = constructor || function (){}; var p = prototype || {}; return function () { for ( var atr in p) { arguments.callee.prototype[atr] = p[atr]; } c.apply( this ,arguments); }} var Shake = function (options){ options = options || {}; this .options = { z: 3 , // 抖动半径 maxa: 1080 // 总计抖动角度 1080/360圈 } extendJson( this .options,options); this .z = this .options.z; this .maxa = this .options.maxa; this .mode = " c " ; // 抖动的模式 "h"左右抖动;"v"上下抖动;"c"上下左右抖动; } var proto = { _setZ: function (z){ this .z = z;}, _getZ: function (){ return this .z;}, _setMaxa: function (maxa){ this .maxa = maxa;}, _getMaxa: function (){ return this .maxa;}, _init: function (){ this .obj = document.getElementById( this .oID); if ( this .obj){ this .a = 0 ; // 角度 this .os = this .obj.style; this .oleft = this .os.left == " auto " ? 0 : ~~ this .os.left; this .otop = this .os.top == " auto " ? 0 : ~~ this .os.top; return true ; } else { return false ; } }, _end: function (){ if ( this .os){ clearInterval( this .i); this .os.left = this .oleft + " px " ; this .os.top = this .otop + " px " ; } }, _exe: function (){ var object = this ; return function (){ var r = object.a * Math.PI / 180 , x = Math.sin(r) * object.z , y = Math.cos(r) * object.z; if (object.mode == ' c ' || object.mode == ' h ' ){ object.os.left = object.oleft + y + " px " ; } if (object.mode == ' c ' || object.mode == ' v ' ){ object.os.top = object.otop + x + " px " ; } if ( (object.a += 90 ) > object.maxa ){ object._end(); } } }, _start: function (){ this ._end(); if ( this ._init()){ this .i = setInterval( this ._exe(), 30 ); } }, h: function (objID){ // 左右抖动 this .oID = objID; this .mode = " h " ; this ._start(); }, v: function (objID){ // 上下抖动 this .oID = objID; this .mode = " v " ; this ._start(); }, c: function (objID){ // 上右下左抖动 this .oID = objID; this .mode = " c " ; this ._start(); }} var Shk = $class(Shake,proto); var shk = new Shk({z: 10 }); </ script > </ head > < body > < button onclick ="shk.v('shakeBox1');return false;" > 抖抖更建康 </ button > < div id ="shakeBox1" style ="position:relative;" > < input type ="text" /> </ div > < button onclick ="shk.h('shakeBox2');return false;" > 喝前抖一抖 </ button > < div id ="shakeBox2" style ="position:relative;" > < input type ="text" /> </ div > < button onclick ="shk.c('shakeBox3');return false;" > 左抖右抖上抖下抖 </ button > < div id ="shakeBox3" style ="position:relative;" > < input type ="text" /> </ div > </ body > </ html >
demo下载: