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 相关文章推荐
prototype 的说明 js类
Sep 07 Javascript
ajax 同步请求和异步请求的差异分析
Jul 04 Javascript
简介JavaScript中的setHours()方法的使用
Jun 11 Javascript
使用ngView配合AngularJS应用实现动画效果的方法
Jun 19 Javascript
jQuery validate插件实现ajax验证重复的2种方法
Jan 22 Javascript
JavaScript tab选项卡插件实例代码
Feb 23 Javascript
详解JavaScript设计模式开发中的桥接模式使用
May 18 Javascript
JavaScript中push(),join() 函数 实例详解
Sep 06 Javascript
详解JS中的柯里化(currying)
Aug 17 Javascript
不得不看之JavaScript构造函数及new运算符
Aug 21 Javascript
小程序实现列表多个批量倒计时
Jan 29 Javascript
ES5新增数组的实现方法
May 12 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 的 __FILE__ 常量
2007/01/15 PHP
在PHP上显示JFreechart画的统计图方法
2013/11/03 PHP
php使用ereg验证文件上传的方法
2014/12/16 PHP
php启用sphinx全文搜索的实现方法
2014/12/24 PHP
Firefox 无法获取cssRules 的解决办法
2006/10/11 Javascript
jQuery对象数据缓存Cache原理及jQuery.data方法区别介绍
2013/04/07 Javascript
js如何判断不同系统的浏览器类型
2013/10/28 Javascript
JavaScript数组对象赋值用法实例
2015/08/04 Javascript
浅谈JS继承_借用构造函数 &amp; 组合式继承
2016/08/16 Javascript
微信小程序 页面跳转和数据传递实例详解
2017/01/19 Javascript
jquery Ajax实现Select动态添加数据
2017/06/08 jQuery
jQuery完成表单验证的实例代码(纯代码)
2017/09/30 jQuery
基于JS实现一个随机生成验证码功能
2019/05/29 Javascript
微信小程序版本自动更新的方法
2019/06/14 Javascript
layui插件表单验证提交触发提交的例子
2019/09/09 Javascript
JS对象属性的检测与获取操作实例分析
2020/03/17 Javascript
JavaScript forEach中return失效问题解决方案
2020/06/01 Javascript
JS数据类型分类及常用判断方法
2020/11/19 Javascript
Python中使用Inotify监控文件实例
2015/02/14 Python
在Python下尝试多线程编程
2015/04/28 Python
Python操作mongodb的9个步骤
2018/06/04 Python
浅谈利用numpy对矩阵进行归一化处理的方法
2018/07/11 Python
python实现定时发送qq消息
2019/01/18 Python
python判断文件夹内是否存在指定后缀文件的实例
2019/06/10 Python
python数据爬下来保存的位置
2020/02/17 Python
python GUI库图形界面开发之PyQt5信号与槽机制、自定义信号基础介绍
2020/02/25 Python
css3针对移动端卡顿问题的解决(动画性能优化)
2020/02/14 HTML / CSS
网页中的电话号码如何实现一键直呼效果_附示例
2016/03/15 HTML / CSS
英语文学专业学生的自我评价
2013/10/31 职场文书
求职简历中的自我评价分享
2013/12/08 职场文书
评析教师个人的自我评价
2014/02/19 职场文书
《北京的春节》教学反思
2014/04/07 职场文书
对照检查剖析材料
2014/09/30 职场文书
永不妥协观后感
2015/06/10 职场文书
如何使用SQL Server语句创建表
2022/04/12 SQL Server
python+pyhyper实现识别图片中的车牌号思路详解
2022/12/24 Python