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 相关文章推荐
JavaScript 编程引入命名空间的方法
Jun 29 Javascript
一段利用WSH获取登录时间的jscript代码
May 11 Javascript
toString()一个会自动调用的方法
Feb 08 Javascript
js解析与序列化json数据(二)序列化探讨
Feb 01 Javascript
jcrop基本参数一览
Jul 16 Javascript
javascript为下拉列表动态添加数据项
May 23 Javascript
基于jquery实现一个滚动的分步注册向导-附源码
Aug 26 Javascript
详解JavaScript中的4种类型识别方法
Sep 14 Javascript
Bootstrap每天必学之js插件
Nov 30 Javascript
xmlplus组件设计系列之网格(DataGrid)(10)
May 05 Javascript
vue中使用百度脑图kityminder-core二次开发的实现
Sep 26 Javascript
JavaScript Window浏览器对象模型原理解析
May 30 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生成不同颜色、不同大小的tag标签函数
2013/09/23 PHP
php中文验证码实现方法
2015/06/18 PHP
php获取从百度、谷歌等搜索引擎进入网站关键词的方法
2015/07/08 PHP
php实现替换手机号中间数字为*号及隐藏IP最后几位的方法
2016/11/16 PHP
ThinkPHP5+Layui实现图片上传加预览功能
2018/08/17 PHP
Jsonp 跨域的原理以及Jquery的解决方案
2010/05/18 Javascript
Jquery动态进行图片缩略的原理及实现
2013/08/13 Javascript
JQuery的$和其它JS发生冲突的快速解决方法
2014/01/24 Javascript
javascript的动态加载、缓存、更新以及复用(一)
2014/06/09 Javascript
html的DOM中document对象images集合用法实例
2015/01/21 Javascript
原生js实现放大镜
2017/02/20 Javascript
JavaScript 字符串数字左补位,右补位,取固定长度,截位扩展函数代码
2017/03/25 Javascript
xmlplus组件设计系列之图标(ICON)(1)
2017/05/05 Javascript
使用JQuery实现图片轮播效果的实例(推荐)
2017/10/24 jQuery
vue+node+webpack环境搭建教程
2017/11/05 Javascript
在小程序中集成redux/immutable/thunk第三方库的方法
2018/08/12 Javascript
详解js实时获取并显示当前时间的方法
2019/05/10 Javascript
基于Cesium绘制抛物弧线
2020/11/18 Javascript
使用setup.py安装python包和卸载python包的方法
2013/11/27 Python
Python读取mp3中ID3信息的方法
2015/03/05 Python
详解Python3的TFTP文件传输
2018/06/26 Python
From CSV to SQLite3 by python 导入csv到sqlite实例
2020/02/14 Python
在Anaconda3下使用清华镜像源安装TensorFlow(CPU版)
2020/04/19 Python
python mysql自增字段AUTO_INCREMENT值的修改方式
2020/05/18 Python
python和php哪个容易学
2020/06/19 Python
CSS3中的display:grid,网格布局介绍
2019/10/30 HTML / CSS
canvas离屏技术与放大镜实现代码示例
2018/08/31 HTML / CSS
美国糖果店:Sugarfina
2019/02/21 全球购物
大学总结自我鉴定
2014/01/18 职场文书
幼儿园秋游活动方案
2014/01/21 职场文书
2014年机关党建工作总结
2014/11/11 职场文书
2014年污水处理厂工作总结
2014/12/19 职场文书
暖春观后感
2015/06/08 职场文书
法人代表资格证明书
2015/06/18 职场文书
2019年教师节祝福语精选,给老师送上真诚的祝福
2019/09/09 职场文书
Python中的 Set 与 dict
2022/03/13 Python