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 相关文章推荐
Javascript中的数学函数
Apr 04 Javascript
ext监听事件方法[初级篇]
Apr 27 Javascript
WEB页子窗口(showModalDialog和showModelessDialog)使用说明
Oct 25 Javascript
JS添加删除一组文本框并对输入信息加以验证判断其正确性
Apr 11 Javascript
JavaScript中的Math.atan2()方法使用详解
Jun 15 Javascript
简单谈谈Javascript函数中的arguments
Feb 09 Javascript
Angular4学习笔记之新建项目的方法
Jul 18 Javascript
elementUI table表格动态合并的示例代码
May 15 Javascript
微信小程序(订阅消息)功能
Oct 25 Javascript
angular异步验证防抖踩坑实录
Dec 01 Javascript
继承行为在 ES5 与 ES6 中的区别详解
Dec 24 Javascript
js HTML DOM EventListener功能与用法实例分析
Apr 27 Javascript
基于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
利用 window_onload 实现select默认选择
2006/10/09 PHP
用PHP实现弹出消息提示框的两种方法
2013/12/17 PHP
WordPress迁移时一些常见问题的解决方法整理
2015/11/24 PHP
PHP+MYSQL实现读写分离简单实战
2017/03/13 PHP
50个优秀经典PHP算法大集合 附源码
2020/08/26 PHP
MacOS下PHP7.1升级到PHP7.4.15的方法
2021/02/22 PHP
JavaScript中的Document文档对象
2008/01/16 Javascript
JQuery 浮动导航栏实现代码
2009/08/27 Javascript
JavaScript中的全局对象介绍
2015/01/01 Javascript
使用Sticker.js实现贴纸效果
2015/01/28 Javascript
Javascript中的getUTCDay()方法使用详解
2015/06/10 Javascript
JavaScript中的Math.LN2属性用法详解
2015/06/12 Javascript
JS使用Prim算法和Kruskal算法实现最小生成树
2019/01/17 Javascript
vue 中Virtual Dom被创建的方法
2019/04/15 Javascript
vue 引用自定义ttf、otf、在线字体的方法
2019/05/09 Javascript
JS实现从对象获取对象中单个键值的方法示例
2019/06/05 Javascript
JavaScript面向对象中接口实现方法详解
2019/07/24 Javascript
微信小程序错误this.setData报错及解决过程
2019/09/18 Javascript
PyQt5每天必学之带有标签的复选框
2018/04/19 Python
python判断列表的连续数字范围并分块的方法
2018/11/16 Python
对Python定时任务的启动和停止方法详解
2019/02/19 Python
pandas条件组合筛选和按范围筛选的示例代码
2019/08/26 Python
布隆过滤器的概述及Python实现方法
2019/12/08 Python
在Pytorch中计算自己模型的FLOPs方式
2019/12/30 Python
Pytorch maxpool的ceil_mode用法
2020/02/18 Python
Python3 ID3决策树判断申请贷款是否成功的实现代码
2020/05/21 Python
简单介绍HTML5中audio标签的使用
2015/09/24 HTML / CSS
欧尚俄罗斯网上超市:Auchan俄罗斯
2018/05/03 全球购物
国培计划培训感言
2014/03/11 职场文书
学习礼仪心得体会
2014/09/01 职场文书
党员“四风”方面存在问题及整改措施
2014/09/24 职场文书
年会主持人开场白台词
2015/05/29 职场文书
2019年入党思想汇报格式与要求
2019/06/25 职场文书
人生一定要学会的三样东西:放下、忘记、珍惜
2019/08/21 职场文书
PyQt5 QThread倒计时功能的实现代码
2021/04/02 Python
解决Navicat for Mysql连接报错1251的问题(连接失败)
2021/05/27 MySQL