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的时候写的学习笔记
Dec 30 Javascript
使用RequireJS优化JavaScript引用代码的方法
Jul 01 Javascript
Kendo Grid editing 自定义验证报错提示的解决方法
Nov 18 Javascript
JavaScript数组迭代方法
Mar 03 Javascript
EasyUI为Numberbox添加blur事件的方法
Mar 05 Javascript
初探js和简单隐藏效果的实例
Nov 23 Javascript
webstorm添加*.vue文件支持
May 08 Javascript
Vuejs+vue-router打包+Nginx配置的实例
Sep 20 Javascript
jQuery-ui插件sortable实现自由拖动排序
Dec 01 jQuery
JS实现网页烟花动画效果
Mar 10 Javascript
Vue记住滚动条和实现下拉加载的完美方法
Jul 31 Javascript
uniapp实现横向滚动选择日期
Oct 21 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
在Zeus Web Server中安装PHP语言支持
2006/10/09 PHP
PHP生成自适应大小的缩略图类及使用方法分享
2014/05/06 PHP
php运行报错Call to undefined function curl_init()的最新解决方法
2016/11/20 PHP
js实现的网页颜色代码表全集
2007/07/17 Javascript
仿迅雷焦点广告效果(JQuery版)
2008/11/19 Javascript
IE iframe的onload方法分析小结
2010/01/07 Javascript
JS上传图片前的限制包括(jpg jpg gif及大小高宽)等
2012/12/19 Javascript
jQuery滚动加载图片效果的实现
2013/03/06 Javascript
jQuery contains过滤器实现精确匹配使用方法
2013/04/12 Javascript
js判断undefined类型示例代码
2014/02/10 Javascript
JavaScript通过事件代理高亮显示表格行的方法
2015/05/27 Javascript
JS实现间歇滚动的运动效果实例
2016/12/22 Javascript
jQuery实现的简单悬浮层功能完整实例
2017/01/23 Javascript
基于JavaScript实现图片连播和联级菜单实例代码
2017/07/28 Javascript
在Vue.js中使用Mixins的方法
2017/09/12 Javascript
JavaScript设计模式之缓存代理模式原理与简单用法示例
2018/08/07 Javascript
JavaScript设计模式之观察者模式实例详解
2019/01/16 Javascript
webpack实践之DLLPlugin 和 DLLReferencePlugin的使用教程
2019/06/10 Javascript
Vue 技巧之控制父类的 slot
2020/02/24 Javascript
JavaScript异步操作的几种常见处理方法实例总结
2020/05/11 Javascript
[01:07:20]DOTA2-DPC中国联赛 正赛 Dynasty vs XG BO3 第二场 2月2日
2021/03/11 DOTA
[原创]python爬虫(入门教程、视频教程)
2018/01/08 Python
Python实现的简单计算器功能详解
2018/08/25 Python
通过python实现弹窗广告拦截过程详解
2019/07/10 Python
django+tornado实现实时查看远程日志的方法
2019/08/12 Python
pytorch 模型可视化的例子
2019/08/17 Python
pytorch中的自定义反向传播,求导实例
2020/01/06 Python
python:解析requests返回的response(json格式)说明
2020/04/30 Python
Python抖音快手代码舞(字符舞)的实现方法
2021/02/07 Python
有关HTML5中背景音乐的自动播放功能
2017/10/16 HTML / CSS
Gloeilampgoedkoop荷兰:在线购买灯泡
2019/02/16 全球购物
附答案的Java面试题
2012/11/19 面试题
逻辑链路控制协议
2016/10/01 面试题
公务员转正考察材料
2014/02/07 职场文书
党员批评与自我批评范文
2014/09/23 职场文书
经典祝酒词大全
2015/08/12 职场文书