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 void(0)的妙用
Oct 21 Javascript
jQuery 表格插件整理
Apr 27 Javascript
JavaScript中的noscript元素属性位置及作用介绍
Apr 11 Javascript
使用ImageMagick进行图片缩放、合成与裁剪(js+python)
Sep 16 Javascript
js charAt的使用示例
Feb 18 Javascript
jQuery基础知识小结
Dec 22 Javascript
javascript实现带节日和农历的日历特效
Feb 01 Javascript
JavaScript控制输入框中只能输入中文、数字和英文的方法【基于正则实现】
Mar 03 Javascript
js获取指定时间的前几秒
Apr 05 Javascript
node.js中TCP Socket多进程间的消息推送示例详解
Jul 10 Javascript
vue实现在线翻译功能
Sep 27 Javascript
JavaScript对象属性操作实例解析
Feb 04 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
PHP+MySQL5.0中文乱码解决方法
2006/11/20 PHP
php 使用array函数实现分页
2015/02/13 PHP
php对文件进行hash运算的方法
2015/04/03 PHP
PHP 类与构造函数解析
2017/02/06 PHP
Ubuntu上安装yaf扩展的方法
2018/01/29 PHP
PHP实现生成推广海报的方法详解
2018/03/14 PHP
js删除所有的cookie的代码
2010/11/25 Javascript
javascript实现日历控件(年月日关闭按钮)
2012/12/12 Javascript
简单介绍jsonp 使用小结
2016/01/27 Javascript
jQuery实现可展开折叠的导航效果示例
2016/09/12 Javascript
微信小程序开发一键登录 获取session_key和openid实例
2016/11/23 Javascript
关于Javascript中document.cookie的使用
2017/03/08 Javascript
jQuery插件FusionCharts实现的MSBar2D图效果示例【附demo源码】
2017/03/24 jQuery
借助node实战JSONP跨域实例
2017/03/30 Javascript
node.js 利用流实现读写同步,边读边写的方法
2017/09/11 Javascript
vue多种弹框的弹出形式的示例代码
2017/09/18 Javascript
微信小程序中时间戳和日期的相互转换问题
2018/07/09 Javascript
详解多页应用 Webpack4 配置优化与踩坑记录
2018/10/16 Javascript
p5.js实现简单货车运动动画
2019/10/23 Javascript
JS变量提升及函数提升实例解析
2020/09/03 Javascript
javascript前端实现多视频上传
2020/12/13 Javascript
Python拼接微信好友头像大图的实现方法
2018/08/01 Python
Python 支付整合开发包的实现
2019/01/23 Python
python Tkinter版学生管理系统
2019/02/20 Python
使用python socket分发大文件的实现方法
2019/07/08 Python
Python实现TCP探测目标服务路由轨迹的原理与方法详解
2019/09/04 Python
Python操作Excel工作簿的示例代码(\*.xlsx)
2020/03/23 Python
东方红海科技面试题软件测试方面
2012/02/08 面试题
AJAX应用和传统Web应用有什么不同
2013/08/24 面试题
仲裁协议书
2014/09/26 职场文书
校园安全主题班会
2015/08/12 职场文书
宪法宣传标语100条
2019/10/15 职场文书
python函数指定默认值的实例讲解
2021/03/29 Python
详解Python flask的前后端交互
2022/03/31 Python
USB TYPE-C 或将成为所有智能手机充电标准
2022/04/21 数码科技
Zabbix对Kafka topic积压数据监控的解决方案
2022/07/07 Servers