您的位置:首页 > Web前端 > JavaScript

javascript仿天猫加入购物车动画效果

2015-09-12 11:21 961 查看
javascript仿天猫加入购物车动画效果

注意:首先需要声明的是:代码原思路不是我写的,是在网上找的这种效果,自己使用代码封装了下而已;代码中都有注释,我们最主要的是理解抛物线的思路及在工作中完成这样的任务,最近需要做类似于天猫加入购物车动画效果,所以就在网上搜索了下,就看到类似的效果,就把代码截下来自己封装了下~~

如果想要了解抛物线的细节,我建议大家先 看下 张鑫旭 讲解的抛物线的文章,再来看如下JS代码,可能理解更深点~~

http://www.zhangxinxu.com/wordpress/2013/12/javascript-js-%E5%85%83%E7%B4%A0-%E6%8A%9B%E7%89%A9%E7%BA%BF-%E8%BF%90%E5%8A%A8-%E5%8A%A8%E7%94%BB/

首先我们来理解的是: 既然是抛物运动,那么 运动的元素肯定需要 "绝对定位";配置的参数有如下:(依赖于Jquery或者zepto.js

配置项含义
el需要运动的元素 {object | string} 默认为null
offset运动的元素在 X轴,Y轴的偏移位置
targetEl终点目标元素 这时就会自动获取该元素的left、top值,来表示移动元素在X,Y轴的偏移位置;设置了这个参数,offset将失效
duration运动时间,默认为500毫秒
curvature抛物线曲率,就是弯曲的程度,越接近于0越像直线,默认0.001
callback运动完成后执行的回调函数
autostart是否自动开始运动,默认为false
stepCallback运动过程中执行的回调函数,this指向该对象,接受x,y参数,分别表示X,Y轴的偏移位置。
JSFiddler效果如下:

JS抛物线运动效果

下面是所有的JS代码:

/*
* 实现抛物线函数 Parabola
* 切记既然是抛物线运动,那么运动的元素需要绝对定位
* 具体了解抛物线 可以看张鑫旭的文章
* http://www.zhangxinxu.com/wordpress/2013/12/javascript-js-%E5%85%83%E7%B4%A0-%E6%8A%9B%E7%89%A9%E7%BA%BF-%E8%BF%90%E5%8A%A8-%E5%8A%A8%E7%94%BB/ */
var Parabola = function(opts){
this.init(opts);
};
Parabola.prototype = {
constructor: Parabola,
/*
* @fileoverview 页面初始化
* @param opts {Object} 配置参数
*/
init: function(opts){
this.opts =  $.extend(defaultConfig, opts || {});
// 如果没有运动的元素 直接return
if(!this.opts.el) {
return;
}
// 取元素 及 left top
this.$el = $(this.opts.el);
this.$elLeft = this._toInteger(this.$el.css("left"));
this.$elTop = this._toInteger(this.$el.css("top"));
// 计算x轴,y轴的偏移量
if(this.opts.targetEl) {
this.diffX = this._toInteger($(this.opts.targetEl).css("left")) - this.$elLeft;
this.diffY = this._toInteger($(this.opts.targetEl).css("top")) - this.$elTop;
}else {
this.diffX = this.opts.offset[0];
this.diffY = this.opts.offset[1];
}
// 运动时间
this.duration = this.opts.duration;
// 抛物线曲率
this.curvature = this.opts.curvature;

// 计时器
this.timerId = null;
/*
* 根据两点坐标以及曲率确定运动曲线函数(也就是确定a, b的值)
* 公式: 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.diffY - this.curvature * this.diffX * this.diffX) / this.diffX;

// 是否自动运动
if(this.opts.autostart) {
this.start();
}
},
/*
* @fileoverview 开始
*/
start: function(){
// 开始运动
var self = this;
// 设置起始时间 和 结束时间
this.begin = (new Date()).getTime();
this.end = this.begin + this.duration;

// 如果目标的距离为0的话 就什么不做
if(this.diffX === 0 && this.diffY === 0) {
return;
}
if(!!this.timerId) {
clearInterval(this.timerId);
this.stop();
}
// 每帧(对于大部分显示屏)大约16~17毫秒。默认大小是166.67。也就是默认10px/ms
this.timerId = setInterval(function(){
var t = (new Date()).getTime();
self.step(t);
},16);
return this;
},
/*
* @fileoverview 执行每一步
* @param {string} t 时间
*/
step: function(t){
var opts = this.opts;
var x,
y;
// 如果当前运行的时间大于结束的时间
if(t > this.end) {
// 运行结束
x = this.diffX;
y = this.diffY;
this.move(x,y);
this.stop();
// 结束后 回调
if(typeof opts.callback === 'function') {
opts.callback.call(this);
}
}else {
// 每一步x轴的位置
x = this.diffX * ((t - this.begin) / this.duration);
// 每一步y轴的位置 y = a * x *x + b*x + c; c = 0
y = this.curvature * x * x + this.b * x;
// 移动
this.move(x,y);
if(typeof opts.stepCallback === 'function') {
opts.stepCallback.call(this,x,y);
}
}
return this;
},
/*
* @fileoverview 给元素定位
* @param {x,y} x,y坐标
* @return this
*/
move: function(x,y) {
this.$el.css({
"position":'absolute',
"left": this.$elLeft + x + 'px',
"top": this.$elTop + y + 'px'
});
return this;
},
/*
* 获取配置项
* @param {object} options配置参数
* @return {object} 返回配置参数项
*/
getOptions: function(options){
if(typeof options !== "object") {
options = {};
}
options = $.extend(defaultConfig, options || {});
return options;
},
/*
* 设置options
* @param options
*/
setOptions: function(options) {
this.reset();
if(typeof options !== 'object') {
options = {};
}
options = $.extend(this.opts,options);
this.init(options);
return this;
},
/*
* 重置
*/
reset: function(x,y) {
this.stop();
x = x ? x : 0;
y = y ? y : 0;
this.move(x,y);
return this;
},
/*
* 停止
*/
stop: function(){
if(!!this.timerId){
clearInterval(this.timerId);
}
return this;
},
/*
* 变成整数
* isFinite() 函数用于检查其参数是否是无穷大。
*/
_toInteger: function(text){
text = parseInt(text);
return isFinite(text) ? text : 0;
}
};
var defaultConfig = {
//需要运动的元素 {object | string}
el: null,

// 运动的元素在 X轴,Y轴的偏移位置
offset: [0,0],

// 终点元素
targetEl: null,

// 运动时间,默认为500毫秒
duration: 500,

// 抛物线曲率,就是弯曲的程度,越接近于0越像直线,默认0.001
curvature: 0.01,

// 运动后执行的回调函数
callback: null,

// 是否自动开始运动,默认为false
autostart: false,

// 运动过程中执行的回调函数,this指向该对象,接受x,y参数,分别表示X,Y轴的偏移位置。
stepCallback: null
};


HTML代码如下:

<div class="btns" style="margin-top:20px">
<a href="#" id="reset">重置</a>
<a href="#" id="run">开始运动</a>
<a href="#" id="stop">停止运动</a>
<a href="#" id="setOptions">设置配置参数</a>
</div>
<div id="boll" class="boll"></div>
<div id="target" class="target"></div>


JS初始化如下方式:

var bool = new Parabola({
el: "#boll",
offset: [500, 100],
duration: 500,
curvature: 0.005,
callback:function(){
alert("完成后回调")
},
stepCallback:function(x,y){

$("<div>").appendTo("body").css({
"position": "absolute",
"top": this.$elTop + y + 'px',
"left":this.$elLeft + x + 'px',
"background-color":"#CDCDCD",
"width":"5px",
"height":"5px",
"border-radius": "5px"
});

}
});
$("#reset").click(function (event) {
event.preventDefault();
bool.reset();
});
$("#run").click(function (event) {
event.preventDefault();
bool.start();
});
$("#stop").click(function (event) {
event.preventDefault();
bool.stop();
});
$("#setOptions").click(function (event) {
event.preventDefault();
bool.setOptions({
targetEl: $("#target"),
curvature: 0.001,
duration: 1000
});
});


JS源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: