parabola.js抛物线与加入购物车效果的示例代码


Posted in Javascript onOctober 25, 2017

在做购物车的时候发现一个很好用抛物线特效parabola.js,可先点击DEMO体验下。下面贴出一些关键代码,具体代码可在GitHub上查看

parabola.js

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

实现

// body
<div class="container">
  ![](dist/01.png)
  <center>点击加入购物车查看效果</center>

  <!--动画图片-->
  <div class="img-element" id="imgElement">
    ![](dist/02.jpg)
  </div>
  <!--购物车-->
  <div class="shop-cart" id="shopCart"></div>

  <span class="shop-cart-num">0</span>
  <div class="add-shop-cart"><!--加入购物车--></div>
</div>
// script
// 起始位置元素
var imgElement = document.querySelector('#imgElement'),
  // 终点位置元素
  shopCartElement = document.querySelector('#shopCart'),
  // 购物车数量
  proNum = 0;

// 初始化抛物线动画
var myParabola = funParabola(imgElement, shopCartElement, {
  speed: 100,// 每帧移动的像素大小
  curvature: 0.005,// 实际指焦点到准线的距离
  complete: function () {
    imgElement.style.visibility = "hidden";
    $('.shop-cart-num').text(++proNum);
  }
});
// 绑定加入购物车事件
$('.add-shop-cart').click(function () {
  // 重置位置
  $('#imgElement').css({ left: '70px', bottom: '25px', visibility: 'visible' });

  myParabola.position().move();
});

效果图

parabola.js抛物线与加入购物车效果的示例代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
MooTools 1.2介绍
Sep 14 Javascript
jQuery JSON的解析方式分享
Apr 05 Javascript
JavaScript高级程序设计阅读笔记(六) ECMAScript中的运算符(二)
Feb 27 Javascript
js自动下载文件到本地的实现代码
Apr 28 Javascript
JQuery在页面中添加和除移DOM示例代码
Jun 24 Javascript
jQuery使用empty()方法删除元素及其所有子元素的方法
Mar 26 Javascript
jQuery三级下拉列表导航菜单代码分享
Apr 15 Javascript
AngularJS基础 ng-if 指令用法
Aug 01 Javascript
Html5 js实现手风琴效果
Apr 17 Javascript
JS实现不用中间变量temp 实现两个变量值得交换方法
Feb 04 Javascript
Node 搭建一个静态资源服务器的实现
May 20 Javascript
vue h5移动端禁止缩放代码
Oct 28 Javascript
通过js控制时间,一秒一秒自己动的实例
Oct 25 #Javascript
js 显示日期时间的实例(时间过一秒加1)
Oct 25 #Javascript
JavaScript编程设计模式之观察者模式(Observer Pattern)实例详解
Oct 25 #Javascript
BootStrap 标题设置跨行无效的解决方法
Oct 25 #Javascript
vue基于mint-ui的城市选择3级联动的示例
Oct 25 #Javascript
浅谈Vue的加载顺序探讨
Oct 25 #Javascript
JavaScript模块模式实例详解
Oct 25 #Javascript
You might like
php cache类代码(php数据缓存类)
2010/04/15 PHP
php中explode与split的区别介绍
2012/10/03 PHP
Mac系统下使用brew搭建PHP(LNMP/LAMP)开发环境
2015/03/03 PHP
2款PHP无限级分类实例代码
2015/11/11 PHP
php+MySQL实现登录时验证登录名和密码是否正确
2016/05/10 PHP
PHP PDOStatement::bindColumn讲解
2019/01/30 PHP
jquery ajax 简单范例(界面+后台)
2013/11/19 Javascript
jQuery实现鼠标划过展示大图的方法
2015/03/09 Javascript
Javascript aop(面向切面编程)之around(环绕)分析
2015/05/01 Javascript
Json解析的方法小结
2016/06/22 Javascript
手机端 HTML5使用photoswipe.js仿微信朋友圈图片放大效果
2016/08/25 Javascript
JavaScript 监控微信浏览器且自带返回按钮时间
2016/11/27 Javascript
js鼠标跟随运动效果
2017/03/11 Javascript
微信小程序表单验证错误提示效果
2017/05/19 Javascript
深入理解ES6中let和闭包
2018/02/22 Javascript
Javascript实现动态时钟效果
2018/11/17 Javascript
在 Vue-CLI 中引入 simple-mock实现简易的 API Mock 接口数据模拟
2018/11/28 Javascript
el-input 标签中密码的显示和隐藏功能的实例代码
2019/07/19 Javascript
vue解决花括号数据绑定不成功的问题
2019/10/30 Javascript
js原生map实现的方法总结
2020/01/19 Javascript
Vue2.4+新增属性.sync、$attrs、$listeners的具体使用
2020/03/08 Javascript
初学python数组的处理代码
2011/01/04 Python
python通过ftplib登录到ftp服务器的方法
2015/05/08 Python
Python浅拷贝与深拷贝用法实例
2015/05/09 Python
tensorflow识别自己手写数字
2018/03/14 Python
实例讲解python中的协程
2018/10/08 Python
Python3使用PySynth制作音乐的方法
2019/09/09 Python
Python基于pygame实现单机版五子棋对战
2019/12/26 Python
python + selenium 刷B站播放量的实例代码
2020/06/12 Python
python根据用户需求输入想爬取的内容及页数爬取图片方法详解
2020/08/03 Python
HTML5实现视频弹幕功能
2019/08/09 HTML / CSS
Weblogic和WebSphere不同特点
2012/05/09 面试题
产品销售员岗位职责
2013/12/18 职场文书
大雁塔英文导游词
2015/02/10 职场文书
2015年上半年信访工作总结
2015/03/30 职场文书
项目中Nginx多级代理是如何获取客户端的真实IP地址
2022/05/30 Servers