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 相关文章推荐
CSDN轮换广告图片轮换效果
Mar 27 Javascript
jquery中的$(document).ready()使用小结
Feb 14 Javascript
一个JavaScript的求爱小特效
May 09 Javascript
javascript格式化日期时间方法汇总
Jun 19 Javascript
jQuery事件委托之Safari
Jul 05 Javascript
jQuery自定义图片上传插件实例代码
Apr 04 jQuery
基于Bootstrap实现城市三级联动
Nov 23 Javascript
JavaScript设计模式之工厂模式简单实例教程
Jul 03 Javascript
js中的reduce()函数讲解
Jan 18 Javascript
vue实现路由切换改变title功能
May 28 Javascript
Node.js学习教程之Module模块
Sep 03 Javascript
Layer.js实现表格溢出内容省略号显示,悬停显示全部的方法
Sep 16 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下连接mssql2005的代码
2011/01/17 PHP
解析php中获取系统信息的方法
2013/06/25 PHP
分享一个php 的异常处理程序
2014/06/22 PHP
根据一段代码浅谈Javascript闭包
2010/12/14 Javascript
ListBox实现上移,下移,左移,右移的简单实例
2014/02/13 Javascript
AngularJs Modules详解及示例代码
2016/09/01 Javascript
js自定义Tab选项卡效果
2017/06/05 Javascript
JavaScript 判断iPhone X Series机型的方法
2019/01/28 Javascript
D3.js(v3)+react 实现带坐标与比例尺的散点图 (V3版本)
2019/05/09 Javascript
微信小程序如何使用canvas二维码保存至手机相册
2019/07/15 Javascript
vue+mock.js实现前后端分离
2019/07/24 Javascript
超简单的微信小程序轮播图
2019/11/22 Javascript
快速了解Vue父子组件传值以及父调子方法、子调父方法
2020/07/15 Javascript
利用Vue的v-for和v-bind实现列表颜色切换
2020/07/17 Javascript
python清除字符串里非数字字符的方法
2015/07/02 Python
详解Python中pandas的安装操作说明(傻瓜版)
2019/04/08 Python
对django的User模型和四种扩展/重写方法小结
2019/08/17 Python
Python动态导入模块和反射机制详解
2020/02/18 Python
python爬虫开发之urllib模块详细使用方法与实例全解
2020/03/09 Python
python中numpy数组与list相互转换实例方法
2021/01/29 Python
HTML5拖放效果的实现代码
2016/11/17 HTML / CSS
Skyscanner加拿大:全球旅行搜索平台
2018/11/19 全球购物
美国摩托车头盔、零件、齿轮及配件商店:Cycle Gear
2019/06/12 全球购物
德国的各种媒体在线商店:Thalia.de(书籍、电子书、玩具等)
2020/10/08 全球购物
利用promise及参数解构封装ajax请求的方法
2021/03/24 Javascript
财务部岗位职责
2013/11/19 职场文书
医学检验专业个人求职信范文
2013/12/04 职场文书
校园餐饮创业计划书
2014/01/10 职场文书
会计专业大学生求职信范文
2014/01/28 职场文书
新闻人物通讯稿
2014/10/09 职场文书
再婚婚前财产协议书范本
2014/10/19 职场文书
2015年度对口支援工作总结
2015/07/22 职场文书
女方家长婚礼答谢词
2015/09/29 职场文书
护士自荐信范文(2016推荐篇)
2016/01/28 职场文书
Java使用httpRequest+Jsoup爬取红蓝球号码
2021/07/02 Java/Android
MySQL中rank() over、dense_rank() over、row_number() over用法介绍
2022/03/23 MySQL