视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
JavaScript中弹性势能动画之关于抛物线运动的代码案例
2020-11-27 20:15:00 责编:小采
文档

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

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

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

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

具体代码如下:

<!DOCTYPE html>
<html>
<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>
下载本文
显示全文
专题