js运动 1.匀速运动
<style type="text/css"> div { width: 100px; height: 100px; background: orange; position: absolute; left: 0px; top: 0px; } button { margin-top: 150px; } span { position: absolute; left: 300px; top: 0px; width: 1px; height: 100px; background: black; } </style> </head> <body> <div></div> <span></span> <button id="btn">run</button> <script> var oDiv = document.getElementsByTagName('div')[0]; var oBtn = document.getElementById('btn'); var timer = null; oBtn.onclick = function () { // s = vt t s startMove(oDiv , 300);//让谁运动,运动到哪里 } function startMove (dom, target) { clearInterval(timer); var iSpeed = target - dom.offsetLeft> 0 ? 7 : -7; timer = setInterval(function () { if (Math.abs(target-dom.offsetLeft) < Math.abs(iSpeed)) { clearInterval(timer); dom.style.left = target+'px'; }else { dom.style.left = dom.offsetLeft + iSpeed + 'px'; } }, 30); } </script>2.缓冲运动
<style type="text/css"> div { width: 100px; height: 100px; background: orange; position: absolute; left: 0px; top: 0px; } button { margin-top: 150px; } span { position: absolute; left: 300px; top: 0px; width: 1px; height: 100px; background: black; } </style> </head> <body> <div></div> <span></span> <button id="btn">run</button> <script> var oDiv = document.getElementsByTagName('div')[0]; var oBtn = document.getElementById('btn'); var timer = null; oBtn.onclick = function () { // s = vt t s startMove(oDiv , 300);//让谁运动,运动到哪里 } // 物体的速度 距离目标点越近 就越小 当到达目标点时 速度减小为0 function startMove (dom, target) { clearInterval(timer); var iSpeed = null; timer = setInterval(function () { iSpeed = (target - oDiv.offsetLeft) / 7; iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);//像素原因 if(oDiv.offsetLeft == target){ clearInterval(timer); }else { oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px'; } }, 30); } </script>类似电脑清楚缓存球的动态
<style type="text/css"> .wrapper { width: 400px; height: 80px; background: orange; position: absolute; left: -400px; top: 200px; } .wrapper span { width: 50px; height: 80px; background: red; position: absolute; right: -50px; top: 0px; } </style> </head> <body> <div class="wrapper"> <span></span> </div> <script> var oDiv = document.getElementsByClassName('wrapper')[0]; timer=null; oDiv.onmouseenter = function () { startMove(this, 0); } oDiv.onmouseleave = function () { startMove(this, -400); } function startMove (dom, target) { clearInterval(timer); var iSpeed = null; timer = setInterval(function () { iSpeed = (target - oDiv.offsetLeft) / 7; iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);//像素原因 if(oDiv.offsetLeft == target){ clearInterval(timer); }else { oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px'; } }, 30); } </script> 透明度渐变缓存 <style type="text/css"> div { width: 100px; height: 100px; background: red; opacity: 1; } </style> </head> <body> <div> </div> <script> var timer = null; var oDiv=document.getElementsByTagName('div')[0]; //获取样式精准的值 oDiv.onclick=function (){ startMove(this , 0.5); } function getStyle (dom, attr) { if (window.getComputedStyle) { return window.getComputedStyle(dom, null)[attr]; }else { return dom.currentStyle[attr]; } } function startMove (dom, target) { clearInterval(dom.timer); var iSpeed = null, iCur = null; dom.timer = setInterval(function () { iCur = parseFloat( getStyle(dom, 'opacity') ) * 100; iSpeed = ( target - iCur ) / 7; // .... iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (iCur == target) { clearInterval(dom.timer); }else { dom.style.opacity = (iCur + iSpeed)/100; } }, 30); } </script>3.多物体运动
<style type="text/css"> div { width: 100px; height: 100px; background: red; margin-bottom: 100px; } </style> </head> <body> <div></div> <div></div> <div></div> <div></div> <script> var timer = null; var oDivArray = document.getElementsByTagName('div'); for (var i = 0; i < oDivArray.length; i++) { oDivArray[i].onmouseenter = function () { startMove(this, 400); } oDivArray[i].onmouseleave = function () { startMove(this, 100); } } //获取样式精准的值 // oDiv.οnclick=function (){ // startMove(this , 0.5); // } function getStyle (dom, attr) { if (window.getComputedStyle) { return window.getComputedStyle(dom, null)[attr]; }else { return dom.currentStyle[attr]; } } function startMove (dom, target) { clearInterval(dom.timer); var iSpeed = null, iCur = null; dom.timer = setInterval(function () { iCur = parseFloat( getStyle(dom, 'width') ) ; iSpeed = ( target - iCur ) / 7; // .... iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (iCur == target) { clearInterval(dom.timer); }else { dom.style.width = iCur + iSpeed + 'px'; } }, 30); } </script>物体不同运动
<style type="text/css"> div { width: 100px; height: 100px; background: red; margin-bottom: 100px; border: 5px solid black; } </style> </head> <body> <div></div> <div></div> <div></div> <div></div> <script> var timer = null; var oDivArray = document.getElementsByTagName('div'); oDivArray[0].onclick = function () { startMove(this, 'width', 400); } oDivArray[1].onclick = function () { startMove(this, 'height', 400); } oDivArray[2].onclick = function () { startMove(this, 'borderWidth', 20); } oDivArray[3].onclick = function () { startMove(this, 'opacity', 50); } function getStyle (dom, attr) { if (window.getComputedStyle) { return window.getComputedStyle(dom, null)[attr]; }else { return dom.currentStyle[attr]; } } function startMove (dom, attr, target) { clearInterval(dom.timer); var iSpeed = null, iCur = null; dom.timer = setInterval(function () { if (attr == 'opacity') { iCur = parseFloat( getStyle(dom, attr) ) * 100; }else { iCur = parseInt( getStyle(dom, attr) ); } iSpeed = (target - iCur) / 7; iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (iCur == target) { clearInterval(dom.timer); } if (attr == 'opacity') { dom.style.opacity = ( iCur + iSpeed ) / 100; }else { dom.style[attr] = iCur + iSpeed + 'px'; } }, 30) } </script>多物体不同值运动
<style type="text/css"> div { position: absolute; left: 0px; width: 100px; height: 100px; background: red; opacity: 1; } #topDiv { top: 200px; } #bottomDiv { top: 400px; } </style> </head> <body> <div id="topDiv"></div> <div id="bottomDiv"></div> <script> var timer = null; // width -> 100 400 height 100 400 left 0 200 top 200 300 opacity 1 0.5 // {width: 400, height: 400, left: 200, top: 300, opacity: 50} var oTopDiv = document.getElementById('topDiv'); var oBottomDiv = document.getElementById('bottomDiv'); oTopDiv.onclick = function () { // 当一次性传多值时,且不知道传几个,用对象 startMove(this, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () { }) } function getStyle (dom, attr) { if (window.getComputedStyle) { return window.getComputedStyle(dom, null)[attr]; }else { return dom.currentStyle[attr]; } } function startMove (dom, attrObj) { clearInterval(dom.timer); var iSpeed = null, iCur = null; dom.timer = setInterval(function () { var bStop = true; //通过循环来改变是属性 for (var attr in attrObj) { // 'width' 'height' if (attr == 'opacity') { iCur = parseFloat( getStyle(dom, attr) ) * 100; }else { iCur = parseInt( getStyle(dom, attr) ); } iSpeed = (attrObj[attr] - iCur) / 7; iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (attr == 'opacity') { dom.style.opacity = (iCur + iSpeed) / 100; }else { dom.style[attr] = iCur + iSpeed + 'px'; } if (iCur != attrObj[attr]) { bStop = false; } } if (bStop) { clearInterval(dom.timer); alert("over"); } }, 30); } </script> 多物体多值运动+回调机制 <style type="text/css"> div { position: absolute; left: 0px; width: 100px; height: 100px; background: red; opacity: 1; } #topDiv { top: 200px; } #bottomDiv { top: 400px; } </style> </head> <body> <div id="topDiv"></div> <div id="bottomDiv"></div> <script> var timer = null; // width -> 100 400 height 100 400 left 0 200 top 200 300 opacity 1 0.5 // {width: 400, height: 400, left: 200, top: 300, opacity: 50} var oTopDiv = document.getElementById('topDiv'); var oBottomDiv = document.getElementById('bottomDiv'); oTopDiv.onclick = function () { // 当一次性传多值时,且不知道传几个,用对象 startMove(this, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () { startMove(oBottomDiv, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () { alert('over'); }) }) } function getStyle (dom, attr) { if (window.getComputedStyle) { return window.getComputedStyle(dom, null)[attr]; }else { return dom.currentStyle[attr]; } } function startMove (dom, attrObj, callback) { clearInterval(dom.timer); var iSpeed = null, iCur = null; dom.timer = setInterval(function () { var bStop = true; //通过循环来改变是属性 for (var attr in attrObj) { // 'width' 'height' if (attr == 'opacity') { iCur = parseFloat( getStyle(dom, attr) ) * 100; }else { iCur = parseInt( getStyle(dom, attr) ); } iSpeed = (attrObj[attr] - iCur) / 7; iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (attr == 'opacity') { dom.style.opacity = (iCur + iSpeed) / 100; }else { dom.style[attr] = iCur + iSpeed + 'px'; } if (iCur != attrObj[attr]) { bStop = false; } } if (bStop) { clearInterval(dom.timer); typeof callback == 'function' && callback(); } }, 30); } </script>加速度运动
<style type="text/css"> div { position: absolute; left: 0px; top: 0px; width: 100px; height: 100px; background: orange; } </style> </head> <body> <div ></div> <script> var timer = null; // v = v + at; var oDiv = document.getElementsByTagName('div')[0]; var timer = null; oDiv.onclick = function () { startMove(this); } // 加速度不变的加速运动 运动方向是向右 // 加速度不变的减速运动 加速不变的加速运动 向左 function startMove (dom) { clearInterval(timer); var a = 2; var iSpeed = 20; timer = setInterval(function () { iSpeed = iSpeed + a; oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px'; }, 30); }; </script>弹性运动
<style type="text/css"> div { position: absolute; left: 0px; top: 0px; width: 100px; height: 100px; background: orange; } span { position: absolute; left: 300px; top: 0px; background: black; width: 2px; height: 100px; } </style> </head> <body> <div></div> <span></span> <script> var oDiv = document.getElementsByTagName('div')[0]; var timer = null; oDiv.onclick = function (){ startMove(this , 300); } function startMove ( dom , target){ clearInterval(timer); var a =3; var ispeed = 0 ; //实际损耗 mv var u = 0.5 ; timer = setInterval(function(){ a = (target - dom.offsetLeft) / 10 ; ispeed += a; //默认摩擦力 ispeed *=0.8; //在浏览器中运动的物体没有真正的停止,所以近似把绝对值为小于1 看成速度为0 if ( Math.abs(ispeed) < 1 && Math.abs(target -dom.offsetLeft) <1){ clearInterval(timer); dom.style.left = target + 'px'; }else{ dom.style.left = dom.offsetLeft + ispeed +'px'; } dom.style.left = dom.offsetLeft + ispeed + 'px' ; },30) } </script>弹性运动案例
<style> * { padding: 0px; margin: 0px; list-style: none; } ul { position: relative; margin: 100px auto; width: 800px; height: 100px; } .ele { float: left; width: 198px; border: 1px solid black; height: 98px; line-height: 98px; text-align: center; background: aqua; } .bg { position: absolute; left: 0px; top: 0px; width: 200px; height: 100px; opacity: 0.5; background: deeppink; } </style> </head> <body> <ul> <li class="ele">CS</li> <li class="ele">CG</li> <li class="ele">LD</li> <li class="ele">DCG</li> <li class="bg"></li> </ul> <script> var oLiArray = document.getElementsByTagName('li'); var oBg = oLiArray[oLiArray.length - 1]; var timer = null; for (var i =0; i < oLiArray.length - 1; i++) { oLiArray[i].onmouseenter = function () { console.log(this.offsetLeft); startMove(oBg, this.offsetLeft); } } function startMove (dom, target) { clearInterval(timer); var iSpeed = 0; var a = 1; var u = 0.8; timer = setInterval(function () { a = (target - dom.offsetLeft) / 5; iSpeed += a; iSpeed *= u; console.log(iSpeed, target - dom.offsetLeft); if ( Math.abs(iSpeed) < 1 && Math.abs(target - dom.offsetLeft) < 1) { clearInterval(timer); dom.style.left = target + 'px'; }else { dom.style.left = dom.offsetLeft + iSpeed + 'px'; } }, 30); } </script>模拟重力场 多方向运动+碰撞检测+重力加速度+能量损失 问题1:碰撞边界后反弹的处理
解决:首先要判定边界,在小球向下运动的反弹条件是小球的下边线碰到窗口的下边线,由于存在小球的下边线没有刚好处在窗口下边线的情况,则反弹的判定条件是,让小球的offsetTop(小球上边线与窗口的上边线的距离)大于等于窗口可视区的高度减去小球的直径(高度),此时为了防止反弹点不在窗口底边线,则设置小球的offsetTop等于窗口可视区的高度减去小球的直径。反弹后垂直方向上的速度方向改变,可设置speed = -speed;小球在向上运动时反弹的点在上边线上,此时的处理与下边线类似;左右碰撞原理与上下碰撞原理类似,不做赘述。
问题2:碰撞后的动能损耗
解决:动能损耗直观上来讲,就是速度降低,这里拟损耗后的速度为损耗前的0.8倍
问题3:清理定时器的条件
解决:现实中小球停止时,水平和垂直方向的速度均为零,且落在地面上。而模拟的过程发现小球的速度不能为零,但是数值太小不足以引起位置变化,故当水平和垂直方向上的速度均小于1,且小球下边线在窗口下边线(小球的offsetTop等于窗口可视区的高度减去小球的直径)时,设置速度为零并清理定时器。
<style> div { width: 100px; height: 100px; background: orange; position: absolute; top: 0; left: 0; } </style> </head> <body> <div id="demo"></div> <script> var oDiv = document.getElementById('demo'); oDiv.onclick = function () { startMove(this); } function startMove (dom) { clearInterval(dom.timer); var iSpeedX = 6; var iSpeedY = 8; var g = 3;//重力加速度 dom.timer = setInterval(function () { iSpeedY += g; var newTop = dom.offsetTop + iSpeedY; var newLeft = dom.offsetLeft + iSpeedX; if (newTop >= document.documentElement.clientHeight - dom.clientHeight) { iSpeedY *= -1; //能量损失 iSpeedY *= 0.8; iSpeedX *= 0.8; newTop = document.documentElement.clientHeight - dom.clientHeight; } if (newTop <= 0) { iSpeedY *= -1; //能量损失 iSpeedY *= 0.8; iSpeedX *= 0.8; newTop = 0; } if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) { iSpeedX *= -1; //能量损失 iSpeedY *= 0.8; iSpeedX *= 0.8; newLeft = document.documentElement.clientWidth - dom.clientWidth; } if (newLeft <= 0) { iSpeedX *= -1; //能量损失 iSpeedY *= 0.8; iSpeedX *= 0.8; newLeft = 0; } //做停止的判断 if (Math.abs(iSpeedX) < 1) { iSpeedX = 0; } if (Math.abs(iSpeedY) < 1) { iSpeedY = 0; } if (iSpeedX == 0 && iSpeedY == 0 && newTop == document.documentElement.clientHeight - dom.clientHeight) { clearInterval(dom.timer); console.log('over') }else { dom.style.top = newTop + 'px'; dom.style.left = newLeft + 'px'; } }, 30); } </script>拖拽实例
<style> div { width: 100px; height: 100px; background: orange; position: absolute; top: 0; left: 0; } </style> </head> <body> <div id="demo"></div> <script> var oDiv = document.getElementById('demo'); var lastX = 0; var lastY = 0; var iSpeedX = 0; var iSpeedY = 0; oDiv.onmousedown = function (e) { clearInterval(this.timer); var event = event || e; //鼠标距离左侧的位置 鼠标指针相对于浏览器页面(或客户区)的水平坐标。 距离边界的位置 var disX = event.clientX - this.offsetLeft; var disY = event.clientY - this.offsetTop; var self = this; document.onmousemove = function (e) { var event = event || e; var newLeft = event.clientX - disX; var newTop = event.clientY - disY; //计算松手时的速度 iSpeedX = newLeft - lastX; iSpeedY = newTop - lastY; //更新最后松手前的位置 lastX = newLeft; lastY = newTop; // //拖拽时留下的痕迹 // var oSpan = document.createElement('span'); // oSpan.style.position = 'absolute'; // oSpan.style.left = newLeft + 'px'; // oSpan.style.top = newTop + 'px'; // oSpan.style.width = '5px'; // oSpan.style.height = '5px'; // oSpan.style.backgroundColor = 'black'; // document.body.appendChild(oSpan); self.style.left = newLeft + 'px'; self.style.top = newTop + 'px'; } document.onmouseup = function () { document.onmouseup = null; document.onmousemove = null; startMove(self, iSpeedX, iSpeedY); } } function startMove(dom, iSpeedX, iSpeedY) { clearInterval(dom.timer); var g = 3; //重力加速度 dom.timer = setInterval(function () { iSpeedY += g; var newTop = dom.offsetTop + iSpeedY; var newLeft = dom.offsetLeft + iSpeedX; if (newTop >= document.documentElement.clientHeight - dom.clientHeight) { iSpeedY *= -1; //能量损失 iSpeedY *= 0.8; iSpeedX *= 0.8; newTop = document.documentElement.clientHeight - dom.clientHeight; } if (newTop <= 0) { iSpeedY *= -1; //能量损失 iSpeedY *= 0.8; iSpeedX *= 0.8; newTop = 0; } if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) { iSpeedX *= -1; //能量损失 iSpeedY *= 0.8; iSpeedX *= 0.8; newLeft = document.documentElement.clientWidth - dom.clientWidth; } if (newLeft <= 0) { iSpeedX *= -1; //能量损失 iSpeedY *= 0.8; iSpeedX *= 0.8; newLeft = 0; } //做停止的判断 if (Math.abs(iSpeedX) < 1) { iSpeedX = 0; } if (Math.abs(iSpeedY) < 1) { iSpeedY = 0; } if (iSpeedX == 0 && iSpeedY == 0 && newTop == document.documentElement.clientHeight - dom .clientHeight) { clearInterval(dom.timer); console.log('over') } else { dom.style.top = newTop + 'px'; dom.style.left = newLeft + 'px'; } }, 30); } </script>