视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
js实现商品抛物线加入购物车特效
2020-11-27 20:25:52 责编:小OO
文档
 本文实例为大家分享了js实现商品抛物线加入购物车动画代码,供大家参考,具体内容如下

parapola.js

/*!
 * by zhangxinxu(.com) 2012-12-27
 * you can visit http://www.zhangxinxu.com/wordpress/?p=3855 to get more infomation
 * under MIT license
*/
var funParabola = function(element, target, options) {
 /*
 * 网页模拟现实需要一个比例尺
 * 如果按照1像素就是1米来算,显然不合适,因为页面动不动就几百像素
 * 页面上,我们放两个物体,200~800像素之间,我们可以映射为现实世界的2米到8米,也就是100:1
 * 不过,本方法没有对此有所体现,因此不必在意
 */
 
 var defaults = {
 speed: 166.67, // 每帧移动的像素大小,每帧(对于大部分显示屏)大约16~17毫秒
 curvature: 0.001, // 实际指焦点到准线的距离,你可以抽象成曲率,这里模拟扔物体的抛物线,因此是开口向下的
 progress: function() {},
 complete: function() {}
 };
 
 var params = {}; options = options || {};
 
 for (var key in defaults) {
 params[key] = options[key] || defaults[key];
 }
 
 var exports = {
 mark: function() { return this; },
 position: function() { return this; },
 move: function() { return this; },
 init: function() { return this; }
 };
 
 /* 确定移动的方式 
 * IE6-IE8 是margin位移
 * IE9+使用transform
 */
 var moveStyle = "margin", testDiv = document.createElement("div");
 if ("oninput" in testDiv) {
 ["", "ms", "webkit"].forEach(function(prefix) {
 var transform = prefix + (prefix? "T": "t") + "ransform";
 if (transform in testDiv.style) {
 moveStyle = transform;
 }
 }); 
 }
 
 // 根据两点坐标以及曲率确定运动曲线函数(也就是确定a, b的值)
 /* 公式: y = a*x*x + b*x + c;
 */
 var a = params.curvature, b = 0, c = 0;
 
 // 是否执行运动的标志量
 var flagMove = true;
 
 if (element && target && element.nodeType == 1 && target.nodeType == 1) {
 var rectElement = {}, rectTarget = {};
 
 // 移动元素的中心点位置,目标元素的中心点位置
 var centerElement = {}, centerTarget = {};
 
 // 目标元素的坐标位置
 var coordElement = {}, coordTarget = {};
 
 // 标注当前元素的坐标
 exports.mark = function() {
 if (flagMove == false) return this;
 if (typeof coordElement.x == "undefined") this.position();
 element.setAttribute("data-center", [coordElement.x, coordElement.y].join());
 target.setAttribute("data-center", [coordTarget.x, coordTarget.y].join());
 return this;
 }
 
 exports.position = function() {
 if (flagMove == false) return this;
 
 var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft,
 scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
 
 // 初始位置
 if (moveStyle == "margin") {
 element.style.marginLeft = element.style.marginTop = "0px";
 } else {
 element.style[moveStyle] = "translate(0, 0)";
 }
 
 // 四边缘的坐标
 rectElement = element.getBoundingClientRect();
 rectTarget = target.getBoundingClientRect();
 
 // 移动元素的中心点坐标
 centerElement = {
 x: rectElement.left + (rectElement.right - rectElement.left) / 2 + scrollLeft,
 y: rectElement.top + (rectElement.bottom - rectElement.top) / 2 + scrollTop
 };
 
 // 目标元素的中心点位置
 centerTarget = {
 x: rectTarget.left + (rectTarget.right - rectTarget.left) / 2 + scrollLeft,
 y: rectTarget.top + (rectTarget.bottom - rectTarget.top) / 2 + scrollTop 
 };
 
 // 转换成相对坐标位置
 coordElement = {
 x: 0,
 y: 0 
 };
 coordTarget = {
 x: -1 * (centerElement.x - centerTarget.x),
 y: -1 * (centerElement.y - centerTarget.y) 
 };
 
 /*
 * 因为经过(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
 */
 // 于是
 b = (coordTarget.y - a * coordTarget.x * coordTarget.x) / coordTarget.x; 
 
 return this;
 }; 
 
 // 按照这个曲线运动
 exports.move = function() {
 // 如果曲线运动还没有结束,不再执行新的运动
 if (flagMove == false) return this;
 
 var startx = 0, rate = coordTarget.x > 0? 1: -1;
 
 var step = function() {
 // 切线 y'=2ax+b
 var tangent = 2 * a * startx + b; // = y / x
 // y*y + x*x = speed
 // (tangent * x)^2 + x*x = speed
 // x = Math.sqr(speed / (tangent * tangent + 1));
 startx = startx + rate * Math.sqrt(params.speed / (tangent * tangent + 1));
 
 // 防止过界
 if ((rate == 1 && startx > coordTarget.x) || (rate == -1 && startx < coordTarget.x)) {
 startx = coordTarget.x;
 }
 var x = startx, y = a * x * x + b * x;
 
 // 标记当前位置,这里有测试使用的嫌疑,实际使用可以将这一行注释
 element.setAttribute("data-center", [Math.round(x), Math.round(y)].join());
 
 // x, y目前是坐标,需要转换成定位的像素值
 if (moveStyle == "margin") {
 element.style.marginLeft = x + "px";
 element.style.marginTop = y + "px";
 } else {
 element.style[moveStyle] = "translate("+ [x + "px", y + "px"].join() +")";
 }
 
 if (startx !== coordTarget.x) {
 params.progress(x, y);
 window.requestAnimationFrame(step); 
 } else {
 // 运动结束,回调执行
 params.complete();
 flagMove = true; 
 }
 };
 window.requestAnimationFrame(step);
 flagMove = false;
 
 return this;
 };
 
 // 初始化方法
 exports.init = function() {
 this.position().mark().move();
 };
 }
 
 return exports;
};
 
/*! requestAnimationFrame.js
 * by zhangxinxu 2013-09-30
*/
(function() {
 var lastTime = 0;
 var vendors = ['webkit', 'moz'];
 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
 window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
 window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || // name has changed in Webkit
 window[vendors[x] + 'CancelRequestAnimationFrame'];
 }
 
 if (!window.requestAnimationFrame) {
 window.requestAnimationFrame = function(callback, element) {
 var currTime = new Date().getTime();
 var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
 var id = window.setTimeout(function() {
 callback(currTime + timeToCall);
 }, timeToCall);
 lastTime = currTime + timeToCall;
 return id;
 };
 }
 if (!window.cancelAnimationFrame) {
 window.cancelAnimationFrame = function(id) {
 clearTimeout(id);
 };
 }
}());

使用:

/* 元素 */
var element = document.getElementById("element"), 
 target = document.getElementById("target");
// 抛物线元素的的位置标记
var parabola = funParabola(element, target).mark();
// 抛物线运动的触发
document.body.onclick = function() {
 element.style.marginLeft = "0px";
 element.style.marginTop = "0px";
 parabola.init();
};

加入购物车实战:

/* 本demo演示脚本基于ieBetter.js, 项目地址:https://github.com/zhangxinxu/ieBetter.js */
 
// 元素以及其他一些变量
var eleFlyElement = document.querySelector("#flyItem"), eleShopCart = document.querySelector("#shopCart");
var numberItem = 0;
// 抛物线运动
var myParabola = funParabola(eleFlyElement, eleShopCart, {
 speed: 400,
 curvature: 0.002, 
 complete: function() {
 eleFlyElement.style.visibility = "hidden";
 eleShopCart.querySelector("span").innerHTML = ++numberItem;
 }
});
// 绑定点击事件
if (eleFlyElement && eleShopCart) {
 [].slice.call(document.getElementsByClassName("btnCart")).forEach(function(button) {
 button.addEventListener("click", function() {
 // 滚动大小
 var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft || 0,
 scrollTop = document.documentElement.scrollTop || document.body.scrollTop || 0;
 
 eleFlyElement.style.left = event.clientX + scrollLeft + "px";
 eleFlyElement.style.top = event.clientY + scrollTop + "px";
 eleFlyElement.style.visibility = "visible";
 
 // 需要重定位
 myParabola.position().move(); 
 });
 });
}

下载本文
显示全文
专题