js弹性势能动画之抛物线运动实例详解


Posted in Javascript onJuly 27, 2017

抛物线运动就是:当拖拽结束的时候,我们让当前的元素同时水平运动+垂直运动

在同样的移动距离下,我们鼠标移动的速度快,move方法触发的次数少,相反移动的速度慢,move方法触发的次数就多->浏览器对于每一次的move行为的触发都是由一个最小时间的。

通过观察,我们发现一个事情:水平方向我们盒子在结束拖拽的时候移动的速度和移动的距离没有必然的联系,和开始拖拽的速度也没有必然的联系,只和最后一次即将松开的那一瞬间鼠标的速度是有关系的,最后瞬间鼠标如果移动的快,我们水平运动的距离和速度也是比较大的。->获取鼠标最后一次即将松开时候的速度。

在JS盒子模型中,offsetLeft是获取当前元素的左偏移,获取到的值永远不会出现小数,  他会把真实的left值按照小数点的四舍五入进行计算

具体代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <style>
  *{
   margin:0;
   padding:0;
  }
  html,body{
   width:100%;
   height:100%;
  }
  #box{
   position:absolute;
   top:50%;
   left:50%;
   width:200px;
   height:200px;
   background:#ff6600;
   margin:-100px 0 0 -100px;
   cursor:move;
   /*
    不知道宽高的情况下的居中
   position:absolute;
   top:0;
   left:0;
   right:0;
   bottom:0;
   margin:auto;
   */ 
  }
 </style>
</head>
<body>
 <div id='box'>
  
 </div>
 <script>
  //JS实现让当前的元素在屏幕居中的位置
  var box = document.getElementById('box');
  // box.style.top = ((document.documentElement.clientHeight || document.body.clientHeight)-box.offsetHeight)/2 + "px";

  // box.style.left = ((document.documentElement.clientWidth || document.body.clientWidth)-box.offsetWidth)/2 + "px";
  //拖拽的原理
  /*
   当鼠标在盒子上按下的时候,我们开始拖拽(给盒子绑定onmousemove和onmouseup),当鼠标移动的时候,我们计算盒子的最新位置
   当鼠标抬起的时候说明拖拽结束了,我们的move和up就没用了,我们再把这两个方法移除
  */
  box.onmousedown = down;
  function down(e){
   e = e || window.event;
   //记录开始位置的信息
   this["strX"] = e.clientX;
   this["strY"] = e.clientY;
   this["strL"] = parseFloat(this.style.left);
   this["strT"] = parseFloat(this.style.top);
   //给元素绑定移动和抬起的事件
   if(this.setCapture){
    this.setCapture()//把当前的鼠标和this绑定在一起
    this.onmousemove = move;
    this.onmouseup= up;
   }else{
    var _this = this;
    document.onmousemove = function(e){
     // move(e)//这个里面的this是window
     move.call(_this,e);
    }
     ;
    document.onmouseup= function(e){
     up.call(_this,e);
    };
   }
   //当盒子运动中我们想要执行下一次拖拽,我们按下鼠标,但是由于盒子还是运动着呢,导致鼠标抓不住盒子->在按下的同时我们应该停止盒子的运动
   window.clearInterval(this.flyTimer);
   window.clearInterval(this.dropTimer);
   
  }
  function move(e){
   e = e || window.event;
   var curL = (e.clientX-this["strX"])+this["strL"];
   var curT = (e.clientY-this["strY"])+this["strT"];
   //边界判断
   var minL = 0,minT = 0,maxL = (document.documentElement.clientWidth || document.body.clientWidth) - this.offsetWidth,maxT = (document.documentElement.clientHeight || document.body.clientHeight) - this.offsetHeight;
   curL = curL < minL ? minL :(curL > maxL ? maxL : curL);
   curT = curT < minT ? minT :(curT > maxT ? maxT : curT)
   this.style.left = curL + "px";
   this.style.top = curT + "px";

   //计算我们水平方向移动的速度
   /*
    在浏览器最小反应时间内触发一次move,我们都记录一下当前盒子的位置,让当前的位置-上一次记录的位置=当前最后一次的偏移
   */
   if(!this.pre){
    this.pre = this.offsetLeft;
   }else{
    this.speedFly = this.offsetLeft - this.pre;
    this.pre = this.offsetLeft;
   }
  }
  function up(e){
   if(this.releaseCapture){
    this.releaseCapture();//把当前的鼠标和盒子解除绑定
    this.onmousemove = null;
    this.onmouseup= null;
   }else{
    document.onmousemove = null;
    document.onmouseup= null;
    //这样绑定的话,move和up绑定的this都是document
   }
   //当鼠标离开结束拖拽的时候,我们开始进行水平方向的动画运动
   fly.call(this);
   //当鼠标离开结束拖拽的时候,我们开始进行垂直方向的动画运动
   drop.call(this);
   
  }
  //当鼠标移动过快的时候,我们的鼠标会脱离盒子,导致盒子的mousemove和mouseup事件都移除不到->"鼠标焦点丢失"
  //在IE和火狐浏览器中,我们用一个方法把盒子和鼠标绑定在一起即可。
  //鼠标再快也跑不出去文档:我们把mousemove和mouseup绑定给document
  
  
  function fly(){
   //this->当前要操作的盒子
   var _this = this;
   _this.flyTimer = window.setInterval(function(){
    //我们运动的速度是一直在减慢的,一直到停止("指数衰减运动")
    //this->window
    //盒子停止运动,清除定时器:利用offsetLeft获取的值不会出现小数,对小数部分进行了四舍五入,所以我们加上或者减去一个小于0.5的速度值,其实对于盒子本身的位置并没有发生实质的改变,我们认为此阶段的盒子就停止运动了。

    if(Math.abs(_this.speedFly)<0.5){
     window.clearInterval(_this.flyTimer);
     return;
    }
    _this.speedFly*=0.98;
    var curL = _this.offsetLeft + _this.speedFly;
    var minL = 0,maxL = (document.documentElement.clientWidth || document.body.clientWidth) - _this.offsetWidth;
    if(curL>=maxL){
     _this.style.left = maxL + "px";
     _this.speedFly*=-1;
    }else if(curL<=minL){
     _this.style.left = minL + "px";
     _this.speedFly*=-1;
    }else{
     _this.style.left = curL;
    }
   },10)
   

  }

  function drop(){
   var _this = this;
   _this.dragFlag = 0;
   _this.dropTimer = window.setInterval(function(){
    if(_this.dragFlag>1){//到底的时候dragFlag就大于1了
     window.clearInterval(_this.dropTimer);
     return;
    }
    _this.dropSpeed = !_this.dropSpeed ? 9.8 : _this.dropSpeed + 9.8;
    //衰减
    _this.dropSpeed*=0.98;
    var curT = _this.offsetTop + _this.dropSpeed;
    var maxT = (document.documentElement.clientHeight || document.body.clientHeight) - _this.offsetHeight;
    if(curT >= maxT){// 到底了
     _this.style.top = maxT + "px";
     _this.dropSpeed*=-1;
     _this.dragFlag++;
    }else{
     _this.style.top = curT + "px";
     _this.dragFlag = 0;
    }
   })
   
  }
 </script>
</body>
</html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript 调试利器 Firebug使用详解六
Jul 05 Javascript
用jquery实现下拉菜单效果的代码
Jul 25 Javascript
javascript使用数组的push方法完成快速排序
Sep 15 Javascript
jQuery控制DIV层实现由大到小,由远及近动画变化效果
Oct 09 Javascript
一款简单的jQuery图片标注效果附源码下载
Mar 22 Javascript
js 实现数值的千分位及保存小数方法(推荐)
Aug 01 Javascript
Centos7 中安装 Node.js v4.4.4
Nov 03 Javascript
Node.js readline 逐行读取、写入文件内容的示例
Mar 01 Javascript
解析vue路由异步组件和懒加载案例
Jun 08 Javascript
微信小程序在地图选择地址并返回经纬度简单示例
Dec 03 Javascript
优雅地使用loading(推荐)
Apr 20 Javascript
React 条件渲染最佳实践小结(7种)
Sep 27 Javascript
js学习总结之dom2级事件基础知识详解
Jul 27 #Javascript
Angular指令之restict匹配模式的详解
Jul 27 #Javascript
Angularjs的$http异步删除数据详解及实例
Jul 27 #Javascript
js学习总结之DOM2兼容处理this问题的解决方法
Jul 27 #Javascript
Angularjs的键盘事件的绑定
Jul 27 #Javascript
Angularjs 事件指令详细整理
Jul 27 #Javascript
Bootstrap + AngularJS 实现简单的数据过滤字符查找功能
Jul 27 #Javascript
You might like
通过PHP的内置函数,通过DES算法对数据加密和解密
2012/06/21 PHP
PHP 输出缓冲控制(Output Control)详解
2016/08/25 PHP
PHP基于面向对象封装的分页类示例
2019/03/15 PHP
判断iframe是否加载完成的完美方法
2010/01/07 Javascript
理解Javascript_12_执行模型浅析
2010/10/18 Javascript
FusionCharts图表显示双Y轴双(多)曲线
2012/11/22 Javascript
js限制文本框输入长度两种限制方式(长度、字节数)
2012/12/19 Javascript
jquery利用ajax调用后台方法实例
2013/08/23 Javascript
判断文档离浏览器顶部的距离的方法
2014/01/08 Javascript
JavaScript面向对象的实现方法小结
2015/04/14 Javascript
javascript针对不确定函数的执行方法
2015/12/16 Javascript
详解JavaScript中的事件流和事件处理程序
2016/05/20 Javascript
使用jquery/js获取iframe父子级、同级获取元素的方法
2016/08/05 Javascript
js放到head中失效的原因与解决方法
2017/03/07 Javascript
如何在 Vue.js 中使用第三方js库
2017/04/25 Javascript
使用webpack构建应用的方法步骤
2019/03/04 Javascript
Vue实现固定定位图标滑动隐藏效果
2019/05/30 Javascript
js模拟实现百度搜索
2020/06/28 Javascript
微信小程序以7天为周期连续签到7天功能效果的示例代码
2020/08/20 Javascript
在vue中使用cookie记住用户上次选择的实例(本次例子中为下拉框)
2020/09/11 Javascript
vue项目中使用rem,在入口文件添加内容操作
2020/11/11 Javascript
PyMongo安装使用笔记
2015/04/27 Python
python3实现绘制二维点图
2019/12/04 Python
python异常处理、自定义异常、断言原理与用法分析
2020/03/23 Python
Python实现手绘图效果实例分享
2020/07/22 Python
python 如何上传包到pypi
2020/12/24 Python
使用CSS3代码绘制可爱的Hello Kitty猫
2016/08/03 HTML / CSS
HTML5实现可缩放时钟代码
2017/08/28 HTML / CSS
英国排名第一的最新设计师品牌手表独立零售商:TIC Watches
2016/09/24 全球购物
受外贸欢迎的美国主机:BlueHost
2017/05/16 全球购物
凯特王妃父母建立的派对用品网站:Party Pieces
2017/05/28 全球购物
加薪申请报告范本
2015/05/15 职场文书
2015年庆祝国庆节66周年演讲稿
2015/07/30 职场文书
2016年优秀班主任先进事迹材料
2016/02/26 职场文书
SQL Server 忘记密码以及重新添加新账号
2022/04/26 SQL Server
阿里云服务器(windows)手动部署FTP站点详细教程
2022/08/05 Servers