运动原理
运动的原理:
让某件物品沿着某种方向随着时间的变化改变位置
setInterval(function(){ obox.style.left = obox.offsetLeft+10+"px"; },30)
让页面中的obox元素的left值,每30毫秒,在自身left的基础上增加10像素
为什么是30毫秒呢?
因为电影播放每秒24帧,人眼就识别不出卡顿了,但是对于电脑来说,处理速度相对较快,需要每秒30帧以上才会显得流畅
边界处理
当元素的offsetLeft超出一定距离或到达一个边界值后,停止计时器
var timer; timer = setInterval(function(){ if(obox.offsetLeft>=200){ clearInterval(timer); }else{[ obox.style.left = obox.offsetLeft+10+"px"; } },30)
我们先来实现一个简单的功能,当我们点击按钮之后,让一个元素动起来。并且到达500的边界之后立刻停止下来
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> #d1 { 100px; height: 100px; background-color: red; position: absolute; top:100px; left: 200px; } </style> </head> <body> <button id="btn">点击运动</button> <div id="d1"></div> </body> <script> // 点击按钮,让div横向的运动起来 // 1. 获取元素 let oBtn = document.getElementById('btn'); let oDiv = document.getElementById('d1'); let iTimer = null; // 点击按钮,让元素一直运动 ,需要使用到的知识点:定时器 oBtn.onclick = ()=>{ iTimer = setInterval(()=>{ // 点击按钮之后,让div的位置在当前的基础之上每次增加10px的距离 // oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; // 虽然此代码可以让div动起来,但是我们需要div在运动之后到达某个边界就立刻停止,所以需要将此句代码改为一个判断 if (oDiv.offsetLeft === 500) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; } },30); }; </script> </html>
在上面的代码中,我们点击按钮之后,元素已经可以直接进行移动,但是却存在一个问题,什么问题呢?
当我们点击按钮之后,元素始终以10px的匀速进行运动,到达500的临界然后停止。 但是我们的问题是,速度可能会变,例如将速度变为7px,就不能够
准确的到达500的临界值。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> #d1 { 100px; height: 100px; background-color: red; position: absolute; top:100px; left: 200px; } </style> </head> <body> <button id="btn">点击运动</button> <div id="d1"></div> </body> <script> // 点击按钮,让div横向的运动起来 // 1. 获取元素 let oBtn = document.getElementById('btn'); let oDiv = document.getElementById('d1'); let iTimer = null; // 点击按钮,让元素一直运动 ,需要使用到的知识点:定时器 oBtn.onclick = ()=>{ iTimer = setInterval(()=>{ // 点击按钮之后,让div的位置在当前的基础之上每次增加10px的距离 // oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; // 虽然此代码可以让div动起来,但是我们需要div在运动之后到达某个边界就立刻停止,所以需要将此句代码改为一个判断 if (oDiv.offsetLeft === 500) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv.style.left = oDiv.offsetLeft + 7 + 'px'; // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动 } },30); }; </script> </html>
出现这种情况的原因是因为运动的临界值必须能够被运动的速度(也就是oDiv.offsetLeft + 7 + 'px',表示每次执行移动的距离)整除。
上面的代码当中, 因为临界值不能够被速度整除,所以,最终元素始终达到不了临界值,那么元素就没有办法在到达临界值时停止。
同时在上面的代码中的另外一个问题是,当我们每点击一次运动按钮,元素的速度就会变得更快,原因很简单,就是我们设置的定时器发生了累加。
那么该如何解决定时器累加的问题呢?
我们可以在每次开始运动之前先清除一次定时器。
oBtn.onclick = ()=>{ /* * 为了防止定时器累加,在每次开始定时器之前,先清楚掉一个定时器 * */ clearInterval(iTimer); iTimer = setInterval(()=>{ // 点击按钮之后,让div的位置在当前的基础之上每次增加10px的距离 // oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; // 虽然此代码可以让div动起来,但是我们需要div在运动之后到达某个边界就立刻停止,所以需要将此句代码改为一个判断 if (oDiv.offsetLeft === 500) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv.style.left = oDiv.offsetLeft + 7 + 'px'; // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动 } },30); };
圆周运动demo
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .box{20px;height:20px;background: red;position: absolute;lefT:0;top:0;border-radius: 50%;} </style> </head> <body> <!-- <div class="box"></div> --> </body> <script> var obox = document.querySelector(".box"); var t; var speed = 10; var target = 360; var iNow = 0; var r = 200; // 圆周运动 document.onclick = function(){ clearInterval(t); t = setInterval(() => { if(target <= iNow){ clearInterval(t); }else{ iNow += speed; var div = document.createElement("div"); div.className = "box"; document.body.appendChild(div); // 利用三角函数计算left和top div.style.left = Math.cos( Math.PI/180*iNow ) * r + 200 + "px"; div.style.top = Math.sin( Math.PI/180*iNow ) * r + 200 + "px"; } }, 30); } </script> </html>
多元素缓冲运动事件委托demo
<!DOCTYPE html> <html> <head> <meta charset = "utf-8"> <title></title> <style> .cont { 1000px;height: 600px;border: 1px solid #000;box-sizing: border-box;position: relative;} div div { 100px;height: 100px;position: absolute;left: 0;top: 10px;background-color: lightcoral;} </style> </head> <body> <div class="cont"> <div class="box1" >1</div> <div class="box2">2</div> <div class="box3">3</div> <div class="box4">4</div> <div class="box5">5</div> </div> </body> <script> var ocont = document.querySelector(".cont"); var abox = document.querySelectorAll("div div"); document.onclick = eventFn(abox,function(){ var a = this; move(a,{top:490},function(){ // move(a,{left:800},function(){ // move(a,{top:10},function(){ // move(a,{left:0}) // }) // }) move(a,{left:800,top:300},function(){}) }) }) // 多元素运动 function move(ele,obj,fn){ clearInterval(ele.t); ele.t = setInterval(() => { var onoff = true; for(var i in obj){ var pos = parseInt(getComputedStyle(ele,false)[i]); var speed = (obj[i]-pos)/10; speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); if(pos != obj[i]){ onoff = false; } ele.style[i] = pos + speed + "px"; if(onoff == true){ clearInterval(ele.t); fn && fn(); } } }, 30); } // 事件委托: function eventFn(ele,cb){ return function(eve){ var e = eve || window.event; var target = e.target || e.srcElement; for(var j = 0;j <ele.length;j++){ if(target == ele[j]){ cb.bind(target)(); } } } } </script> </html>
抛物线demo
<!DOCTYPE html> <html> <head> <meta charset = "utf-8"> <title></title> <style> html body {margin: 0;padding: 0;} .box{ 800px;height: 500px;position: relative;border: 1px solid #000;} #ball{ 50px;height: 50px;background-color: paleturquoise;border: 1px solid #000;border-radius: 50%;position: absolute;left: 0;top: 0;} </style> </head> <body> <div class="box"> <div id="ball"></div> </div> </body> <script> var obox = document.querySelector(".box"); var oball = document.querySelector("#ball"); var index = 0; var tSpeed = 5; var lSpeed = 20; var t = null; var maxTop = obox.offsetHeight - oball.offsetHeight; var maxLeft = obox.offsetWidth - oball.offsetWidth; var g = 1; onload = function(){ clearInterval(t); t = setInterval(function(){ if(index%5 == 0){ tSpeed += g; } if(maxTop-oball.offsetTop < tSpeed){ oball.style.top = maxTop+"px"; tSpeed = -Math.round(tSpeed*0.7); if(Math.abs(tSpeed) <= 1){ clearInterval(t) } }else{ oball.style.top = oball.offsetTop + tSpeed +"px"; oball.style.left = oball.offsetLeft + lSpeed +"px"; } if(oball.offsetLeft > maxLeft){lSpeed = -lSpeed} if(oball.offsetLeft < 0){lSpeed = -lSpeed} },30) } </script> </html>
重力运动demo
<!DOCTYPE html> <html> <head> <meta charset = "utf-8"> <title></title> <style> .ball { 50px;height: 50px;border-radius: 50%;background-color: darkorange;position: absolute;top: 0;} .wall { 1000px;border: 1px solid #000;position: absolute;top: 300px;} </style> </head> <body> <div class="ball"></div> <div class="wall"></div> </body> <script> onload = function(){ var oball = document.querySelector(".ball"); var owall = document.querySelector(".wall"); var speed = 6; var index = 0; var g = 2; var t = null; var maxTop = owall.offsetTop - oball.offsetHeight; t = setInterval(function(){ index++; if(index%6 == 0){ speed += g; } if(maxTop - oball.offsetTop <= speed){ oball.style.top = maxTop + "px"; speed = -Math.round(speed*0.7); if(Math.abs(speed) <= 1){ clearInterval(t); } }else{ oball.style.top = oball.offsetTop + speed + "px"; } },30) } </script> </html>