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 相关文章推荐
将jQuery应用于login页面的问题及解决
Oct 17 Javascript
非阻塞动态加载javascript广告实现代码
Nov 17 Javascript
Jquery封装tab自动切换效果的具体实现
Jul 13 Javascript
javascript的alert box在java中如何显示多行
May 18 Javascript
javascript原型模式用法实例详解
Jun 04 Javascript
Ext JS框架中日期函数的用法及日期选择控件的实现
May 21 Javascript
在JS中a标签加入单击事件屏蔽href跳转页面
Dec 16 Javascript
jQuery实现页面顶部下拉广告
Dec 30 Javascript
JS实现touch 点击滑动轮播实例代码
Jan 19 Javascript
jQuery实现的事件绑定功能基本示例
Oct 11 jQuery
Vue实现导航栏的显示开关控制
Nov 01 Javascript
解决echarts图表使用v-show控制图表显示不全的问题
Jul 19 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 调试环境(IIS+PHP+MYSQL)
2007/01/10 PHP
php读取csv实现csv文件下载功能
2013/12/18 PHP
zf框架的Filter过滤器使用示例
2014/03/13 PHP
php准确获取文件MIME类型的方法
2015/06/17 PHP
php技术实现加载字体并保存成图片
2015/07/27 PHP
Javascript打印网页部分内容的脚本
2008/11/17 Javascript
DWZ table的原生分页浅谈
2013/03/01 Javascript
使用DNode实现php和nodejs之间通信的简单实例
2015/07/06 NodeJs
jQuery实现带延迟的二级tab切换下拉列表效果
2015/09/01 Javascript
js实现全国省份城市级联下拉菜单效果代码
2015/09/07 Javascript
javascript实现unicode与ASCII相互转换的方法
2015/12/10 Javascript
JavaScript中的Number数字类型学习笔记
2016/05/26 Javascript
浅析Bootstrap验证控件的使用
2016/06/23 Javascript
Google 地图API Map()构造器详解
2016/08/06 Javascript
javascript 中的事件委托详解
2016/10/25 Javascript
jQuery手指滑动轮播效果
2016/12/22 Javascript
基于JS设计12306登录页面
2016/12/28 Javascript
纯JS实现轮播图
2017/02/22 Javascript
详解Vue的computed(计算属性)使用实例之TodoList
2017/08/07 Javascript
jQuery实现的简单动态添加、删除表格功能示例
2017/09/21 jQuery
JS实现的简单表单验证功能完整实例
2017/10/14 Javascript
一个Vue视频媒体多段裁剪组件的实现示例
2018/08/09 Javascript
微信小程序scroll-view点击项自动居中效果的实现
2020/03/25 Javascript
Vue toFixed保留两位小数的3种方式
2020/10/23 Javascript
Python cx_freeze打包工具处理问题思路及解决办法
2016/02/13 Python
Python图像处理之gif动态图的解析与合成操作详解
2018/12/30 Python
Python pandas对excel的操作实现示例
2020/07/21 Python
canvas实现扭蛋机动画效果的示例代码
2018/10/17 HTML / CSS
Merchant 1948澳大利亚:新西兰领先的鞋类和靴子供应商
2018/03/24 全球购物
俄罗斯设计师家具购物网站:The Furnish
2019/12/01 全球购物
营业经理岗位职责
2013/11/10 职场文书
幼儿园教师教学反思
2014/02/06 职场文书
任命书怎么写
2015/03/02 职场文书
初中语文教学随笔
2015/08/15 职场文书
Django使用echarts进行可视化展示的实践
2021/06/10 Python
使用pipenv管理python虚拟环境的全过程
2021/09/25 Python