JS拖拽碰壁实现效果
实际情况下,一个物体默认具有重力效果。物体的重力效果是时时刻刻都在发生的,相当于定时器的每次运动,都有向下的匀加速运动
如果投掷速度不同,则运动速度也不相同。在碰壁的情况下,速度会有损耗,并且发生速度方向变化。最终,物体会落到地上
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> #nav{ list-style:none; padding: 0; margin: 0 50px 0; text-align:center; color:white; font-weight:bold; background-color: #25517A; cursor:pointer; overflow:hidden; width: 500px; } .navItem{ line-height: 30px; float:left; width:100px; text-decoration: none; color:inherit; } #navActive{ width: 100px; height: 30px; background-color: rgba(0,0,0,0.3); position:absolute; margin-top: -30px; cursor:pointer; } </style> </head> <body> <body> <div id="test" style="height: 100px;width: 100px;border-radius:50%;background:pink;position:absolute;top:40px;left:0;"></div> <script> //声明元素投掷步长值 var stepX=0,stepY=0; //默认情况下,也存在重力效果 collisionMove({ obj:test, stepX:stepX, stepY:stepY }) function getCSS(obj,style){ if(window.getComputedStyle){ return getComputedStyle(obj)[style]; } return obj.currentStyle[style]; } //碰撞运动函数 function collisionMove(json){ var obj = json.obj; var fn = json.fn; //声明x、y轴的当前值 var curX = parseFloat(getCSS(obj,'left')); var curY = parseFloat(getCSS(obj,'top')); //声明x、y轴的步长值 var stepX = json.stepX; var stepY = json.stepY; //声明元素的重要加速度 var g = json.g || 3; //步长值默认值为10 if(isNaN(Number(stepX))){ stepX = 10; }else{ stepX = Number(stepX); } if(isNaN(Number(stepY))){ stepY = 10; }else{ stepY = Number(stepY); } //声明x、y轴方向 var dirX = json.dirX; var dirY = json.dirY; dirX = stepX > 0 ? '+' : '-'; dirY = stepY > 0 ? '+' : '-'; //声明offset宽高 var offsetWidth = obj.offsetWidth; var offsetHeight = obj.offsetHeight; //声明元素活动区域宽高 var activeWidth = json.activeWidth; var activeHeight = json.activeHeight; //元素获取区域宽高默认值为可视区域宽高 activeWidth = Number(activeWidth) || document.documentElement.clientWidth; activeHeight = Number(activeHeight) || document.documentElement.clientHeight; //声明left、top样式值 var left; var top; //声明减速系数 var k = 0.8; //声明碰撞次数 var i = 0; //清除定时器 if(obj.timer){return;} //开启定时器 obj.timer = setInterval(function(){ //获取x、y轴的当前值 curX = parseFloat(getCSS(obj,'left')); curY = parseFloat(getCSS(obj,'top')); //受到重力影响,更新步长值stepY stepY += g; //更新left、top值 left = curX + stepX; top = curY + stepY; //右侧碰壁前一刻,步长大于剩余距离,且元素向右运动时 if((left > activeWidth - offsetWidth) && (dirX == '+')){ left = activeWidth - offsetWidth; } //左侧碰壁前一刻,步长大于剩余距离,且元素向左运动时 if((Math.abs(stepX) > curX) && (dirX == '-')){ left = curX; } //下侧碰壁前一刻,步长大于剩余距离,且元素向下运动时 if((top > activeHeight - offsetHeight) && (dirY == '+')){ top = activeHeight - offsetHeight; } //上侧碰壁前一刻,步长大于剩余距离,且元素向上运动时 if((Math.abs(stepY) > curY) && (dirY == '-')){ top = curY; } obj.style.left= left + 'px'; obj.style.top = top + 'px'; //左侧或右侧碰撞瞬间 if(left == activeWidth - offsetWidth || left == curX){ //x轴方向速度损耗,并发生方向变化 stepX = -stepX * k; } //上侧或下侧碰撞瞬间 if(top == activeHeight - offsetHeight || top == curY){ //y轴方向速度损耗,并发生方向变化 stepY = -stepY * k; //x轴方向速度损耗 stepX = stepX * k; } //元素与地面碰撞10次后,则停止运动 if(top == activeHeight - offsetHeight){ i++; if(i== 10){ clearInterval(obj.timer) obj.timer = 0; fn && fn.call(obj); } } //更新运动方向 dirX = stepX > 0 ? '+' : '-'; dirY = stepY > 0 ? '+' : '-'; },20); } //初始抛掷 test.onmousedown = function(e){ e = e || event; //声明上一次mousemove事件的坐标位置 var lastX2 = e.clientX; var lastY2 = e.clientY; //获取元素距离定位父级的x轴及y轴距离 var x0 = this.offsetLeft; var y0 = this.offsetTop; //获取此时鼠标距离视口左上角的x轴及y轴距离 var x1 = e.clientX; var y1 = e.clientY; //鼠标按下时,获得此时的页面区域 var L0 = 0; var R0 = document.documentElement.clientWidth; var T0 = 0; var B0 = document.documentElement.clientHeight; //鼠标按下时,获得此时的元素宽高 var EH = this.offsetHeight; var EW = this.offsetWidth; document.onmousemove = function(e){ e = e || event; //获取此时鼠标距离视口左上角的x轴及y轴距离 var x2 = e.clientX; var y2 = e.clientY; stepX = x2 - lastX2; stepY = y2 - lastY2; lastX2 = e.clientX; lastY2 = e.clientY; //计算此时元素应该距离视口左上角的x轴及y轴距离 var X = x0 + (x2 - x1); var Y = y0 + (y2 - y1); /******范围限定*******/ //获取鼠标移动时元素四边的瞬时值 var L = X; var R = X + EW; var T = Y; var B = Y + EH; //在将X和Y赋值给left和top之前,进行范围限定 //只有在范围内时,才进行相应的移动 //如果脱离左侧范围,则left置L0 if(L < L0){X = L0;} //如果脱离右侧范围,则left置为R0 if(R > R0){X = R0 - EW;} //如果脱离上侧范围,则top置T0 if(T < T0){Y = T0;} //如果脱离下侧范围,则top置为B0 if(B > B0){Y = B0 - EH;} //将X和Y的值赋给left和top,使元素移动到相应位置 test.style.left = X + 'px'; test.style.top = Y + 'px'; } document.onmouseup = function(e){ e = e || event; var maxHeight = document.documentElement.clientHeight - test.offsetHeight; var maxWidth = document.documentElement.clientWidth - test.offsetWidth; //以设置的投掷速度来进行碰撞运动 collisionMove({ obj:test, stepX:stepX, stepY:stepY }) //当鼠标抬起时,拖拽结束,则将onmousemove赋值为null即可 document.onmousemove = null; //释放全局捕获 if(test.releaseCapture){ test.releaseCapture(); } } //阻止默认行为 return false; //IE8-浏览器阻止默认行为 if(test.setCapture){ test.setCapture(); } } </script> </body> </html>
具体效果点上面的运行代码来看。静态效果图:
本站声明:网站内容来源于网络,如有侵权,请联系我们https://www.qiquanji.com,我们将及时处理。
微信扫码关注
更新实时通知