js绘制购物车抛物线动画


Posted in Javascript onNovember 18, 2020

天猫将商品加入购物车会有一个抛物线动画,告诉用户操作成功以及购物车的位置,业务中需要用到类似的效果,记录一下实现过程备忘,先上demo

js绘制购物车抛物线动画 

一开始没有想到用抛物线函数去做,也已经忘记还有这么个函数了,想着抛物线本质上就是向右和向上方向各有一个速度(就上面的demo而言),向右的速度匀速,向上的速度递减,减到0后再反方向递增,元素的left和top值随时间递增而改变,元素运动轨迹就是抛物线,这个思路不具备通用性,实现也比较复杂,放弃了。

js绘制购物车抛物线动画 

之后参考了张鑫旭用抛物线函数的实现方式和愚人码头的改进,豁然开朗。

思路我再捋一捋,抛物线函数y = a*x*x + b*x + c ,其中a不等于0,a、b、c为常数。x、y为抛物线经过的坐标;a决定抛物线的开口方向,a>0开口向上,a<0开口向下。很明显天猫的抛物线开口向下,a还决定开口的大小,值越小开口越大,抛物线越平顺,反之抛物线越陡。所以a的值可以自定义,等于是已知两个坐标(起点和终点坐,即元素left、top值),求两个未知数,初中的数学就学过,二元二次方程。

y1 = a*x1*x1 + b*x1 + c
y2 = a*x2*x2 + b*x2 + c 

a已知,代入两个已知坐标[x1, y1][x2, y2]可以得出b、c的值,x和y的对应关系有了。

不管抛物线开口向上还是向下,元素在水平方向上移动的速度不变,即left值匀速改变,可以设定抛物线运动时间t,元素在水平方向上的速度为speedx =(x2 - x1)/t,设置一个定时器,每30ms执行一次,left值在每次定时器执行后的值为当前的x = speedx * 定时器已执行时长,再代入函数y = a*x*x + b*x + c得到top值,由于这一切的计算都建立在起点坐标平移到原点(终点也随之平移)的基础上,所以最终设置运动元素的left/top值的时候必须将起点元素的初始left/top值加上。具体请F12查看demo代码。

主要代码:

/**
 * js抛物线动画
 * @param {[object]} origin [起点元素]
 * @param {[object]} target [目标点元素]
 * @param {[object]} element [要运动的元素]
 * @param {[number]} a [抛物线弧度]
 * @param {[number]} time [动画执行时间]
 * @param {[function]} callback [抛物线执行完成后回调]
 */
 var parabola = function(config){
 var b = 0,
  INTERVAL = 15,
  timer = null,
  x1,y1,x2,y2,originx,originy,diffx,diffy;

 this.config = config || {};
 // 起点
 this.origin = $(this.config.origin)||null;
 // 终点
 this.target = $(this.config.target)||null;
 // 运动的元素
 this.element = $(this.config.element)||null;
 // 曲线弧度
 this.a = this.config.a || 0.004;
 // 运动时间(ms)
 this.time = this.config.time || 1000;

 this.init = function(){
  x1 = this.origin.offset().left;
  y1 = this.origin.offset().top;
  x2 = this.target.offset().left;
  y2 = this.target.offset().top;
  originx = x1;
  originy = y1;
  diffx = x2-x1;
  diffy = y2-y1,
  speedx = diffx/this.time;

  // 已知a, 根据抛物线函数 y = a*x*x + b*x + c 将抛物线起点平移到坐标原点[0, 0],终点随之平移,那么抛物线经过原点[0, 0] 得出c = 0;
  // 终点平移后得出:y2-y1 = a*(x2 - x1)*(x2 - x1) + b*(x2 - x1)
  // 即 diffy = a*diffx*diffx + b*diffx;
  // 可求出常数b的值
  b = (diffy - this.a*diffx*diffx)/diffx;
  this.element.css({
  left: x1,
  top: y1
  })
  return this;
 }

 // 确定动画方式
 this.moveStyle = function(){
  var moveStyle = 'position',
  testDiv = document.createElement('div');
  if('placeholder' in testDiv){
  ['','ms','moz','webkit'].forEach(function(pre){
   var transform = pre + (pre ? 'T' : 't') + 'ransform';
   if(transform in testDiv.style){
   moveStyle = transform;
   }
  })
  }
  return moveStyle;
 }

 this.move = function(){
  var start = new Date().getTime(),
  moveStyle = this.moveStyle(),
  _this = this;
  timer = setInterval(function(){
  if(new Date().getTime() - start > _this.time){
   clearInterval(timer);
   _this.element.css({
   left: x2,
   top: y2
   })
   typeof _this.config.callback === 'function' && _this.config.callback(_this.element);
   return;
  }
  x = speedx * (new Date().getTime() - start);
  y = _this.a*x*x + b*x;
  if(moveStyle === 'position'){
   _this.element.css({
   left: x+originx,
   top: y+originy
   })
  }else{
   if(window.requestAnimationFrame){
   window.requestAnimationFrame(_this.element[0].style[moveStyle] = 'translate('+x+'px,'+y+'px)');
   }else{
   _this.element[0].style[moveStyle] = 'translate('+x+'px,'+y+'px)';
   }
  }
  },INTERVAL)
  return this;
 }

 this.init();
 }

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

Javascript 相关文章推荐
从零开始学习jQuery (八) 插播:jQuery实施方案
Feb 23 Javascript
javascript简单事件处理和with用法介绍
Sep 16 Javascript
jquery的each方法使用示例分享
Mar 25 Javascript
jQuery新的事件绑定机制on()示例应用
Jul 18 Javascript
纯javascript制作日历控件
Jul 17 Javascript
jquery+CSS实现的水平布局多级网页菜单效果
Aug 24 Javascript
详解Node.js如何开发命令行工具
Aug 14 Javascript
微信小程序(应用号)简单实例应用及实例详解
Sep 26 Javascript
JavaScript实现简单随机点名器
Nov 21 Javascript
ES6的循环与可迭代对象示例详解
Jan 31 Javascript
基于JavaScript实现省市联动效果
Jun 22 Javascript
vue 实现弹窗关闭后刷新效果
Apr 08 Vue.js
基于jQuery实现发送短信验证码后的倒计时功能(无视页面关闭)
Sep 02 #Javascript
基于JS实现发送短信验证码后的倒计时功能(无视页面刷新,页面关闭不进行倒计时功能)
Sep 02 #Javascript
node.js中module.exports与exports用法上的区别
Sep 02 #Javascript
AngularJs Scope详解及示例代码
Sep 01 #Javascript
AngularJs Modules详解及示例代码
Sep 01 #Javascript
AngularJs IE Compatibility 兼容老版本IE
Sep 01 #Javascript
AngularJs 国际化(I18n/L10n)详解
Sep 01 #Javascript
You might like
在PHP模板引擎smarty生成随机数的方法和math函数详解
2014/04/24 PHP
php获取四位字母和数字的随机数的实现方法
2015/01/09 PHP
基于Laravel 5.2 regex验证的正确写法
2019/09/29 PHP
用js+xml自动生成表格的东西
2006/12/21 Javascript
JavaScript中链式调用之研习
2011/04/07 Javascript
javascript 学习笔记(八)javascript对象
2011/04/12 Javascript
JavaScript高级程序设计 阅读笔记(七) ECMAScript中的语句
2012/02/27 Javascript
将文本输入框内容加入表中的js代码
2013/08/18 Javascript
jQuery实现的简单折叠菜单(折叠面板)效果代码
2015/09/16 Javascript
基于JavaScript代码实现随机漂浮图片广告
2016/01/05 Javascript
JS解决移动web开发手机输入框弹出的问题
2017/03/31 Javascript
了解VUE的render函数的使用
2017/06/08 Javascript
Vue2.0 组件传值通讯的示例代码
2017/08/01 Javascript
js提取中文拼音首字母的封装工具类
2018/03/12 Javascript
实例解析Vue.js下载方式及基本概念
2018/05/11 Javascript
实例详解Vue项目使用eslint + prettier规范代码风格
2018/08/20 Javascript
通过实例解析js简易模块加载器
2019/06/17 Javascript
详解微信小程序动画Animation执行过程
2020/09/23 Javascript
新手该如何学python怎么学好python?
2008/10/07 Python
Python3.x和Python2.x的区别介绍
2013/02/12 Python
你真的了解Python的random模块吗?
2017/12/12 Python
python判断数字是否是超级素数幂
2018/09/27 Python
python将数组n等分的实例
2019/12/02 Python
Python 识别12306图片验证码物品的实现示例
2020/01/20 Python
Python try except异常捕获机制原理解析
2020/04/18 Python
解决Jupyter Notebook使用parser.parse_args出现错误问题
2020/04/20 Python
使用HTML5技术开发一个属于自己的超酷颜色选择器
2013/09/22 HTML / CSS
canvas中普通动效与粒子动效的实现代码示例
2019/01/03 HTML / CSS
办理生育手续介绍信
2014/01/14 职场文书
校园文化艺术节宣传标语
2014/10/09 职场文书
个人债务授权委托书
2014/10/17 职场文书
2015年机关党建工作总结
2015/05/22 职场文书
机械生产实习心得体会
2016/01/22 职场文书
六年级作文之关于梦
2019/10/22 职场文书
MySQL修炼之联结与集合浅析
2021/10/05 MySQL
SQL使用复合索引实现数据库查询的优化
2022/05/25 SQL Server