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 相关文章推荐
2010年最佳jQuery插件整理
Dec 06 Javascript
Express.JS使用详解
Jul 17 Javascript
Javascript基础知识(二)事件
Sep 29 Javascript
javascript 数组操作详解
Jan 29 Javascript
WordPress中利用AJAX技术进行评论提交的实现示例
Jan 12 Javascript
微信小程序 教程之wxapp 视图容器 view
Oct 19 Javascript
javascript实现非常简单的小数取整功能示例
Jun 13 Javascript
VueRouter导航守卫用法详解
Dec 25 Javascript
webpack vue项目开发环境局域网访问方法
Mar 20 Javascript
vue实现表单录入小案例
Sep 27 Javascript
Element-ui Layout布局(Row和Col组件)的实现
Dec 06 Vue.js
VUE中的v-if与v-show区别介绍
Mar 13 Vue.js
基于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 curl模拟浏览器采集阿里巴巴的实现代码
2011/04/20 PHP
简单的php缓存类分享     php缓存机制
2014/01/22 PHP
IIS下PHP的三种配置方式对比
2014/11/20 PHP
PHP session 会话处理函数
2016/06/06 PHP
php设计模式之职责链模式实例分析【星际争霸游戏案例】
2020/03/27 PHP
JavaScript 异步调用框架 (Part 3 - 代码实现)
2009/08/04 Javascript
js查错流程归纳
2012/05/04 Javascript
jquery插件制作 提示框插件实现代码
2012/08/17 Javascript
JavaScript实现生成GUID(全局统一标识符)
2014/09/05 Javascript
js函数与php函数的区别实例浅析
2015/01/12 Javascript
JS如何设置iOS中微信浏览器的title
2016/11/22 Javascript
Nodejs 搭建简单的Web服务器详解及实例
2016/11/30 NodeJs
基于JavaScript实现焦点图轮播效果
2017/03/27 Javascript
使用canvas实现一个vue弹幕组件功能
2018/11/30 Javascript
JavaScript基于遍历操作实现对象深拷贝功能示例
2019/03/05 Javascript
微信小程序 组件的外部样式externalClasses使用详解
2019/09/06 Javascript
js 判断当前时间是否处于某个一个时间段内
2019/09/19 Javascript
《javascript设计模式》学习笔记三:Javascript面向对象程序设计单例模式原理与实现方法分析
2020/04/07 Javascript
谈谈JavaScript中的垃圾回收机制
2020/09/17 Javascript
Vue-Ant Design Vue-普通及自定义校验实例
2020/10/24 Javascript
python搜索指定目录的方法
2015/04/29 Python
Python使用pyautocad+openpyxl处理cad文件示例
2019/07/11 Python
python使用pygame实现笑脸乒乓球弹珠球游戏
2019/11/25 Python
python3爬取torrent种子链接实例
2020/01/16 Python
深度学习入门之Pytorch 数据增强的实现
2020/02/26 Python
Keras官方中文文档:性能评估Metrices详解
2020/06/15 Python
详解HTML5中的标签
2015/06/19 HTML / CSS
html5 Canvas画图教程(9)—canvas中画出矩形和圆形
2013/01/09 HTML / CSS
Sneaker Studio波兰:购买运动鞋
2018/04/28 全球购物
俄罗斯首家面向中国消费者的一站式购物网站:Wruru
2020/05/08 全球购物
文件中有一组整数,要求排序后输出到另一个文件中
2012/01/04 面试题
企业文明单位申报材料
2014/05/16 职场文书
扶贫办主任查摆“四风”问题个人对照检查材料思想汇报
2014/10/02 职场文书
机关干部四风问题自查报告及整改措施
2014/10/26 职场文书
结婚通知短信大全
2015/04/17 职场文书
麦田里的守望者读书笔记
2015/06/30 职场文书