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 相关文章推荐
JS 巧妙获取剪贴板数据 Excel数据的粘贴
Jul 09 Javascript
关于include标签导致js路径找不到的问题分析及解决
Jul 09 Javascript
用jquery方法操作radio使其默认选项是否
Sep 10 Javascript
通过AJAX的JS、JQuery两种方式解析XML示例介绍
Sep 23 Javascript
使用jQuery Ajax 请求webservice来实现更简练的Ajax
Aug 04 Javascript
数组Array的排序sort方法
Feb 17 Javascript
原生js jquery ajax请求以及jsonp的调用方法
Aug 04 jQuery
JavaScript实现计数器基础方法
Oct 10 Javascript
angularjs中判断ng-repeat是否迭代完的实例
Sep 12 Javascript
layui数据表格实现重载数据表格功能(搜索功能)
Jul 27 Javascript
使用PreloadJS加载图片资源的基础方法详解
Feb 03 Javascript
jQuery zTree如何改变指定节点文本样式
Oct 16 jQuery
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
PHP编程网上资源导航
2006/10/09 PHP
在项目中寻找代码的坏命名
2012/07/14 PHP
PHP中数据库单例模式的实现代码分享
2014/08/21 PHP
PHP编程实现多维数组按照某个键值排序的方法小结【2种方法】
2017/04/27 PHP
PHP7中I/O模型内核剖析详解
2019/04/14 PHP
Laravel使用原生sql语句并调用的方法
2019/10/09 PHP
根据分辨率不同,调用不同的css文件
2006/08/25 Javascript
JavaScript中判断页面关闭、页面刷新的实现代码
2014/08/27 Javascript
jQuery焦点图插件SaySlide
2015/12/21 Javascript
js对象浅拷贝和深拷贝详解
2016/09/05 Javascript
JS中SetTimeout和SetInterval使用初探
2017/03/23 Javascript
bootstrap选项卡扩展功能详解
2017/06/14 Javascript
利用jquery去掉时光轴头尾部线条的方法实例
2017/06/16 jQuery
基于layui数据表格以及传数据的方式
2018/08/19 Javascript
Vue-router 切换组件页面时进入进出动画方法
2018/09/01 Javascript
微信小程序使用map组件实现检索(定位位置)周边的POI功能示例
2019/01/23 Javascript
微信小程序实现点击图片放大预览
2019/10/21 Javascript
JavaScript实现简单进度条效果
2020/03/25 Javascript
AutoJs实现刷宝短视频的思路详解
2020/05/22 Javascript
[50:24]VGJ.S vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
python爬取m3u8连接的视频
2018/02/28 Python
python实现飞机大战微信小游戏
2020/03/21 Python
详解python 爬取12306验证码
2019/05/10 Python
Django之创建引擎索引报错及解决详解
2019/07/17 Python
python 默认参数相关知识详解
2019/09/18 Python
英国最大的百货公司:Harrods
2016/08/18 全球购物
阿玛尼化妆品美国官网:Giorgio Armani Beauty
2017/02/02 全球购物
Notino罗马尼亚网站:购买香水和化妆品
2019/07/20 全球购物
自动化专业毕业生自荐信
2013/11/01 职场文书
中专生职业生涯规划书范文
2013/12/29 职场文书
投标单位介绍信
2014/01/09 职场文书
房屋继承公证书
2014/04/10 职场文书
爱与责任演讲稿
2014/05/20 职场文书
限期整改通知书
2015/04/22 职场文书
部门主管竞聘书
2015/09/15 职场文书
MySQL高速缓存启动方法及参数详解(query_cache_size)
2021/07/01 MySQL