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 28 Javascript
Javascript中正则表达式的全局匹配模式分析
Apr 26 Javascript
含有CKEditor的表单如何提交
Jan 09 Javascript
javascript自定义函数参数传递为字符串格式
Jul 29 Javascript
JavaScript插件化开发教程 (二)
Jan 27 Javascript
jquery实现键盘左右翻页特效
Apr 30 Javascript
jquery实现TAB选项卡鼠标经过带延迟效果的方法
Jul 27 Javascript
js实现纯前端的图片预览
Apr 27 Javascript
JS弹出窗口的运用与技巧大全
Nov 01 Javascript
详解如何在微信小程序开发中正确的使用vant ui组件
Sep 13 Javascript
在Chrome DevTools中调试JavaScript的实现
Apr 07 Javascript
vue项目使用$router.go(-1)返回时刷新原来的界面操作
Jul 26 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创建动态图像
2006/10/09 PHP
一个ubbcode的函数,速度很快.
2006/10/09 PHP
20个2014年最优秀的PHP框架回顾
2014/10/22 PHP
微信公众平台接口开发入门示例
2014/12/24 PHP
详解PHP中的状态模式编程
2015/08/11 PHP
基于JQuery的抓取博客园首页RSS的代码
2011/12/01 Javascript
左右悬浮可分组的网站QQ在线客服代码(可谓经典)
2012/12/21 Javascript
高效率JavaScript编写技巧整理
2013/08/23 Javascript
javascript实现点击提交按钮后显示loading的方法
2015/07/03 Javascript
理解JS事件循环
2016/01/07 Javascript
dedecms页面如何获取会员状态的实例代码
2016/03/15 Javascript
Javascript必知必会(四)js类型转换
2016/06/08 Javascript
Bootstrap table两种分页示例
2016/12/23 Javascript
有关JS中的0,null,undefined,[],{},'''''''',false之间的关系
2017/02/14 Javascript
浅析bootstrap原理及优缺点
2017/03/19 Javascript
JavaScript实现简单计算器功能
2019/12/19 Javascript
[01:04:14]OG vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python中比较特别的除法运算和幂运算介绍
2015/04/05 Python
Python实现的朴素贝叶斯算法经典示例【测试可用】
2018/06/13 Python
python3.6利用pyinstall打包py为exe的操作实例
2018/10/31 Python
Python3实现的判断回文链表算法示例
2019/03/08 Python
Python中PyQt5/PySide2的按钮控件使用实例
2019/08/17 Python
浅谈Python3识别判断图片主要颜色并和颜色库进行对比的方法
2019/10/25 Python
基于selenium及python实现下拉选项定位select
2020/07/22 Python
Python抓包并解析json爬虫的完整实例代码
2020/11/03 Python
利用纯CSS3实现tab选项卡切换示例代码
2016/09/21 HTML / CSS
三星美国官网:Samsung美国
2017/02/06 全球购物
人事经理岗位职责范本
2014/08/04 职场文书
学术会议邀请函
2015/01/30 职场文书
唐山大地震的观后感
2015/06/05 职场文书
科技馆观后感
2015/06/08 职场文书
2016优秀班主任个人先进事迹材料
2016/02/26 职场文书
十一月早安语录:把心放轻,人生就是一朵自在的云
2019/11/04 职场文书
拒绝盗图!教你怎么用python给图片加水印
2021/06/04 Python
SQL Server中使用判断语句(IF ELSE/CASE WHEN )案例
2021/07/07 SQL Server
MySQL数据库 任意ip连接方法
2022/05/20 MySQL