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 相关文章推荐
图片Slider 带左右按钮的js示例
Aug 30 Javascript
JavaScript中的apply和call函数详解
Jul 20 Javascript
JS 排序输出实现table行号自增前端动态生成的tr
Aug 13 Javascript
JavaScript中的Math.sin()方法使用详解
Jun 15 Javascript
javascript实现的左右无缝滚动效果
Sep 19 Javascript
node使用Koa2搭建web项目的方法
Oct 17 Javascript
微信小程序使用toast消息对话框提示用户忘记输入用户名或密码功能【附源码下载】
Dec 09 Javascript
使用layui 渲染table数据表格的实例代码
Aug 19 Javascript
微信小程序登录按钮遮罩浮层效果的实现方法
Dec 16 Javascript
vue组件数据传递、父子组件数据获取,slot,router路由功能示例
Mar 19 Javascript
小程序绑定用户方案优化小结
May 15 Javascript
javascript实现超好看的3D烟花特效
Jan 01 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
用js进行url编码后用php反解以及用php实现js的escape功能函数总结
2010/02/08 PHP
解析PHP可变函数的经典用法
2013/06/20 PHP
PHP类中的魔术方法(Magic Method)简明总结
2014/07/08 PHP
PHP中使用循环实现的金字塔图形
2014/11/08 PHP
PHP将页面中点击数量高的链接进行高亮显示的方法
2016/05/30 PHP
JavaScript 版本自动生成文章摘要
2008/07/23 Javascript
Jquery实战_读书笔记2 选择器
2010/01/22 Javascript
jquery ready()的几种实现方法小结
2010/06/18 Javascript
mailto的使用技巧分享
2012/12/21 Javascript
jquery easyui 对于开始时间小于结束时间的判断示例
2014/03/22 Javascript
JS+DIV+CSS实现仿表单下拉列表效果
2015/08/18 Javascript
AngularJS变量及过滤器Filter用法分析
2016/11/22 Javascript
原生js实现焦点轮播图效果
2017/01/12 Javascript
javascript实现日期三级联动下拉框选择菜单
2020/12/03 Javascript
微信小程序tabBar底部导航中文注解api详解
2017/08/16 Javascript
JS基于贪心算法解决背包问题示例
2017/11/27 Javascript
React Native 自定义下拉刷新上拉加载的列表的示例
2018/03/01 Javascript
浅谈如何通过node.js对数据进行MD5加密
2018/05/16 Javascript
关于自定义Egg.js的请求级别日志详解
2018/12/12 Javascript
微信小程序工具函数封装
2019/10/28 Javascript
24个ES6方法解决JS实际开发问题(小结)
2020/05/31 Javascript
[46:00]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#4EG VS Fnatic第一局
2016/03/03 DOTA
[47:04]LGD vs infamous Supermajor小组赛D组 BO3 第二场 6.3
2018/06/04 DOTA
[00:13]天涯墨客二技能展示
2018/08/25 DOTA
对python append 与浅拷贝的实例讲解
2018/05/04 Python
python实现多张图片拼接成大图
2019/01/15 Python
Python分布式进程中你会遇到的问题解析
2019/05/28 Python
用Python+OpenCV对比图像质量的几种方法
2019/07/15 Python
Python单元测试工具doctest和unittest使用解析
2019/09/02 Python
百思买美国官网:Best Buy
2016/07/28 全球购物
俄罗斯首家面向中国消费者的一站式购物网站:Wruru
2020/05/08 全球购物
单位刻章介绍信范文
2014/01/11 职场文书
大学三年计划书范文
2014/04/30 职场文书
教师年度个人总结
2015/02/11 职场文书
幼儿园综治宣传月活动总结
2015/05/07 职场文书
在前女友婚礼上,用Python破解了现场的WIFI还把名称改成了
2021/05/28 Python