js实现商品抛物线加入购物车特效


Posted in Javascript onNovember 18, 2020

本文实例为大家分享了js实现商品抛物线加入购物车动画代码,供大家参考,具体内容如下

 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(); 
  });
 });
}

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
返回对象在当前级别中是第几个元素的实现代码
Jan 20 Javascript
jQuery验证Checkbox是否选中的代码 推荐
Sep 04 Javascript
js图片向右一张张滚动效果实例代码
Nov 23 Javascript
jQuery实现时尚漂亮的弹出式对话框实例
Aug 07 Javascript
jquery判断输入密码两次是否相等
Apr 22 Javascript
jQuery图片左右滚动代码 有左右按钮实例
Jun 20 Javascript
使用JavaScript为一张图片设置备选路径的方法
Jan 04 Javascript
利用Node.js+Koa框架实现前后端交互的方法
Feb 27 Javascript
微信小程序实现分享到朋友圈功能
Jul 19 Javascript
微信小程序中插入激励视频广告并获取收益(实例代码)
Dec 06 Javascript
如何在vue中使用jointjs过程解析
May 29 Javascript
javascript canvas实现雨滴效果
Jun 09 Javascript
js类式继承与原型式继承详解
Apr 07 #Javascript
javascript原型继承工作原理和实例详解
Apr 07 #Javascript
浅析JS原型继承与类的继承
Apr 07 #Javascript
AngularJs 弹出模态框(model)
Apr 07 #Javascript
详解AngularJS 模态对话框
Apr 07 #Javascript
分离与继承的思想实现图片上传后的预览功能:ImageUploadView
Apr 07 #Javascript
jQuery动态添加
Apr 07 #Javascript
You might like
dedecms中常见问题修改方法总结
2007/03/21 PHP
thinkphp实现多语言功能(语言包)
2014/03/04 PHP
ThinkPHP模板替换与系统常量及应用实例教程
2014/08/22 PHP
Laravel框架中VerifyCsrfToken报错问题的解决
2017/08/30 PHP
sina的lightbox效果。
2007/01/09 Javascript
jquery 分页控件实现代码
2009/11/30 Javascript
jQuery-serialize()输出序列化form表单值的方法
2012/12/26 Javascript
JS和jquery获取各种屏幕的宽度和高度的代码
2013/08/02 Javascript
jQuery多级弹出菜单插件ZoneMenu
2014/12/18 Javascript
JS面向对象(3)之Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
2016/02/25 Javascript
webpack中引用jquery的简单实现
2016/06/08 Javascript
快速解决js中window.location.href不工作的问题
2016/11/02 Javascript
JS日程管理插件FullCalendar简单实例
2017/02/07 Javascript
Vue用v-for给循环标签自身属性添加属性值的方法
2018/10/18 Javascript
如何用JavaScript实现功能齐全的单链表详解
2019/02/11 Javascript
[03:08]Ti4观战指南上
2014/07/07 DOTA
Python isinstance判断对象类型
2008/09/06 Python
Python专用方法与迭代机制实例分析
2014/09/15 Python
Python之PyUnit单元测试实例
2014/10/11 Python
Python实现提取文章摘要的方法
2015/04/21 Python
将python文件打包exe独立运行程序方法详解
2020/02/12 Python
Python小白学习爬虫常用请求报头
2020/06/03 Python
使paramiko库执行命令时在给定的时间强制退出功能的实现
2021/03/03 Python
CSS3田字格列表的样式编写方法
2018/11/22 HTML / CSS
英国在线滑雪板和冲浪商店:The Board Basement
2020/01/11 全球购物
应聘教师自荐信
2013/10/12 职场文书
总经理办公室主任岗位职责
2013/11/12 职场文书
财务人员个人求职信范文
2013/12/04 职场文书
小学生评语集锦
2014/04/18 职场文书
省文明单位申报材料
2014/05/08 职场文书
车辆工程专业求职信
2014/06/14 职场文书
关于读书的演讲稿600字
2014/08/27 职场文书
学生乘坐校车安全责任书
2015/05/11 职场文书
图书馆义工感想
2015/08/07 职场文书
校园安全教育心得体会
2016/01/15 职场文书
SQL Server表分区删除详情
2021/10/16 SQL Server