以下是 jQuery抛物线运动轨迹动画特效代码 的示例演示效果:
部分效果截图:
HTML代码(index.html):
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>jQuery抛物线运动轨迹动画特效</title>
<style type="text/css">
.btns{text-align:center;}
.btns a{
color:#fff;padding:5px 10px;font-family:Arial;
background-color:#f90;text-decoration:none;
}
.boll {
width: 50px;
height: 50px;
background-color: #ff3333;
position: absolute;
top: 380px;
left: 100px;
-moz-border-radius: 50px;
-webkit-border-radius: 50px;
border-radius: 50px;
}
.target {
width: 50px;
height: 50px;
background-color: #CDCDCD;
position: absolute;
top: 180px;
left: 600px;
-moz-border-radius: 50px;
-webkit-border-radius: 50px;
border-radius: 50px;
}
</style>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/parabola.js"></script>
</head>
<body>
<div class="btns" style="margin-top:20px">
<a href="javascript:;" id="run">run</a>
<a href="javascript:;" id="reset">reset</a>
<a href="javascript:;" id="stop">stop</a>
<a href="javascript:;" id="setOptions">setOptions</a>
</div>
<div id="boll" class="boll"></div>
<div id="target" class="target"></div>
<script type="text/javascript">
var bool = new Parabola({
el: "#boll",
offset: [500, 100],
curvature: 0.005,
duration: 2000,
callback:function(){
alert("完成后回调")
},
stepCallback:function(x,y){
console.log(x,y);
$("<div>").appendTo("body").css({
"position": "absolute",
"top": this.elOriginalTop + y,
"left":this.elOriginalLeft + x,
"background-color":"#CDCDCD",
"width":"5px",
"height":"5px",
"border-radius": "5px"
});
}
});
$("#reset").click(function () {
bool.reset()
});
$("#run").click(function () {
bool.start();
});
$("#stop").click(function () {
bool.stop();
});
$("#setOptions").click(function () {
bool.setOptions({
targetEl: $("#target"),
curvature: 0.001,
duration: 1000
});
});
</script>
</body>
</html>
JS代码(parabola.js):
;
(function (){
var _$ = function (_this){
return _this.constructor == jQuery ? _this:$(_this);
}
;
// 鑾峰彇褰撳墠鏃堕棿 function now(){
return +new Date();
}
// 杞寲涓烘暣鏁? function toInteger(text){
text = parseInt(text);
return isFinite(text) ? text:0;
}
var Parabola = function (options){
this.initialize(options);
}
;
Parabola.prototype ={
constructor:Parabola,/** * 鍒濆鍖? * @classDescription 鍒濆鍖? * @param{
Object}
options 鎻掍欢閰嶇疆 . */
initialize:function (options){
this.options = this.options || this.getOptions(options);
var ops = this.options;
if (!this.options.el){
return;
}
this.$el = _$(ops.el);
this.timerId = null;
this.elOriginalLeft = toInteger(this.$el.css("left"));
this.elOriginalTop = toInteger(this.$el.css("top"));
// this.driftX X杞寸殑鍋忕Щ鎬婚噺 //this.driftY Y杞寸殑鍋忕Щ鎬婚噺 if (ops.targetEl){
this.driftX = toInteger(_$(ops.targetEl).css("left")) - this.elOriginalLeft;
this.driftY = toInteger(_$(ops.targetEl).css("top")) - this.elOriginalTop;
}
else{
this.driftX = ops.offset[0];
this.driftY = ops.offset[1];
}
this.duration = ops.duration;
// 澶勭悊鍏紡甯搁噺 this.curvature = ops.curvature;
// 鏍规嵁涓ょ偣鍧愭爣浠ュ強鏇茬巼纭畾杩愬姩鏇茬嚎鍑芥暟锛堜篃灏辨槸纭畾a,b鐨勫€硷級 //a=this.curvature /* 鍏紡锛?y = a*x*x + b*x + c;
*/
/* * 鍥犱负缁忚繃(0,0),鍥犳c = 0 * 浜庢槸锛? * y = a * x*x + b*x;
* y1 = a * x1*x1 + b*x1;
* y2 = a * x2*x2 + b*x2;
* 鍒╃敤绗簩涓潗鏍囷細 * b = (y2+ a*x2*x2) / x2 */
// 浜庢槸 this.b = ( this.driftY - this.curvature * this.driftX * this.driftX ) / this.driftX;
//鑷姩寮€濮? if (ops.autostart){
this.start();
}
}
,/** * 鍒濆鍖?閰嶇疆鍙傛暟 杩斿洖鍙傛暟MAP * @param{
Object}
options 鎻掍欢閰嶇疆 . * @return{
Object}
閰嶇疆鍙傛暟 */
getOptions:function (options){
if (typeof options !== "object"){
options ={
}
;
}
options = $.extend({
}
,defaultSetting,_$(options.el).data(),(this.options ||{
}
),options);
return options;
}
,/** * 瀹氫綅 * @param{
Number}
x x鍧愭爣 . * @param{
Object}
y y鍧愭爣 . * @return{
Object}
this */
domove:function (x,y){
this.$el.css({
position:"absolute",left:this.elOriginalLeft + x,top:this.elOriginalTop + y}
);
return this;
}
,/** * 姣忎竴姝ユ墽琛? * @param{
Data}
now 褰撳墠鏃堕棿 . * @return{
Object}
this */
step:function (now){
var ops = this.options;
var x,y;
if (now > this.end){
// 杩愯缁撴潫 x = this.driftX;
y = this.driftY;
this.domove(x,y);
this.stop();
if (typeof ops.callback === 'function'){
ops.callback.call(this);
}
}
else{
//x 姣忎竴姝ョ殑X杞寸殑浣嶇疆 x = this.driftX * ((now - this.begin) / this.duration);
//姣忎竴姝ョ殑Y杞寸殑浣嶇疆y = a*x*x + b*x + c;
c==0;
y = this.curvature * x * x + this.b * x;
this.domove(x,y);
if (typeof ops.stepCallback === 'function'){
ops.stepCallback.call(this,x,y);
}
}
return this;
}
,/** * 璁剧疆options * @param{
Object}
options 褰撳墠鏃堕棿 . */
setOptions:function (options){
this.reset();
if (typeof options !== "object"){
options ={
}
;
}
this.options = $.extend(this.options,options);
this.initialize(this.options);
return this;
}
,/** * 寮€濮? */
start:function (){
var self = this;
// 璁剧疆璧锋鏃堕棿 this.begin = now();
this.end = this.begin + this.duration;
if (this.driftX === 0 && this.driftY === 0){
// 鍘熷湴韪忔灏卞埆娴垂鎬ц兘浜? return;
}
/*timers.push(this);
Timer.start();
*/
if (!!this.timerId){
clearInterval(this.timerId);
this.stop();
}
this.timerId = setInterval(function (){
var t = now();
self.step(t);
}
,13);
return this;
}
,/** * 閲嶇疆 */
reset:function (x,y){
this.stop();
x = x ? x:0;
y = y ? y:0;
this.domove(x,y);
return this;
}
,/** * 鍋滄 */
stop:function (){
if (!!this.timerId){
clearInterval(this.timerId);
}
return this;
}
}
;
var defaultSetting ={
el:null,//鍋忕Щ浣嶇疆 offset:[0,0],//缁堢偣鍏冪礌锛岃繖鏃跺氨浼氳嚜鍔ㄨ幏鍙栬鍏冪礌鐨刲eft銆乼op锛岃缃簡杩欎釜鍙傛暟锛宱ffset灏嗗け鏁? targetEl:null,//杩愬姩鐨勬椂闂达紝榛樿500姣 duration:500,//鎶涚墿绾挎洸鐜囷紝灏辨槸寮洸鐨勭▼搴︼紝瓒婃帴杩戜簬0瓒婂儚鐩寸嚎锛岄粯璁?.001 curvature:0.001,//杩愬姩鍚庢墽琛岀殑鍥炶皟鍑芥暟 callback:null,// 鏄惁鑷姩寮€濮嬶紝榛樿涓篺alse autostart:false,//杩愬姩杩囩▼涓墽琛岀殑鍥炶皟鍑芥暟 stepCallback:null}
;
window.Parabola = Parabola;
}
)();