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打印大全(打印页面设置/打印预览代码)
Mar 29 Javascript
jquery 多行文本框(textarea)高度变化
Jul 03 Javascript
jQuery CSS()方法改变现有的CSS样式
Aug 20 Javascript
JS实现兼容性好,自动置顶的淘宝悬浮工具栏效果
Sep 18 Javascript
JS实现的N多简单无缝滚动代码(包含图文效果)
Nov 06 Javascript
JavaScript简单实现弹出拖拽窗口(一)
Jun 17 Javascript
微信小程序图片选择区域裁剪实现方法
Dec 02 Javascript
微信小程序实现日历功能
Nov 27 Javascript
在vue使用clipboard.js进行一键复制文本的实现示例
Jan 15 Javascript
jquery实现动态改变css样式的方法分析
May 27 jQuery
Vue+ElementUI项目使用webpack输出MPA的方法
Aug 27 Javascript
element ui分页多选,翻页记忆的实例
Sep 03 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
2019年漫画销量排行榜:鬼灭登顶 海贼单卷制霸 尾田盛赞鬼灭
2020/03/08 日漫
图形数字验证代码
2006/10/09 PHP
PHP 解决utf-8和gb2312编码转换问题
2010/03/18 PHP
为PHP初学者的8点有效建议
2010/11/20 PHP
PHP删除非空目录的函数代码小结
2013/02/28 PHP
php读取mysql的简单实例
2014/01/15 PHP
php对象和数组相互转换的方法
2015/05/12 PHP
Laravel框架基于ajax实现二级联动功能示例
2019/01/17 PHP
js表格分页实现代码
2009/09/18 Javascript
javascript 实现map集合
2015/04/03 Javascript
js实现卡片式项目管理界面UI设计效果
2015/12/08 Javascript
实例详解Nodejs 保存 payload 发送过来的文件
2016/01/14 NodeJs
VUE利用vuex模拟实现新闻点赞功能实例
2017/06/28 Javascript
vue+vuex+axios实现登录、注册页权限拦截
2018/03/09 Javascript
JS实现中英文混合文字溢出友好截取功能
2018/08/06 Javascript
angularJs利用$scope处理升降序的方法
2018/10/08 Javascript
JS自定义对象创建与简单使用方法示例
2020/01/15 Javascript
TypeScript 运行时类型检查补充工具
2020/09/28 Javascript
分析python服务器拒绝服务攻击代码
2014/01/16 Python
整理Python最基本的操作字典的方法
2015/04/24 Python
Python作用域用法实例详解
2016/03/15 Python
PyQt5实现下载进度条效果
2018/04/19 Python
python3使用SMTP发送HTML格式邮件
2018/06/19 Python
Python中 CSV格式清洗与转换的实例代码
2019/08/29 Python
在python shell中运行python文件的实现
2019/12/21 Python
Python3.9.0 a1安装pygame出错解决全过程(小结)
2021/02/02 Python
HTML中meta标签及Keywords
2020/04/15 HTML / CSS
财务专业大学生职业生涯规划范文
2013/12/30 职场文书
网上签名寄语活动留言
2014/01/18 职场文书
心理健康课教学反思
2014/02/13 职场文书
酒店管理失职检讨书
2014/09/16 职场文书
教师党员个人总结
2015/02/10 职场文书
《植物妈妈有办法》教学反思
2016/02/23 职场文书
南阳市白酒市场的调查报告
2019/11/08 职场文书
【海涛dota解说】海涛小满开黑4v5被破两路翻盘潮汐第一视角解说
2022/04/01 DOTA
vue里使用create, mounted调用方法
2022/04/26 Vue.js