JavaScript基础12——运动

运动原理

运动的原理: 
    让某件物品沿着某种方向随着时间的变化改变位置
    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 {
                width: 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 {
                width: 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{width: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 {width: 1000px;height: 600px;border: 1px solid #000;box-sizing: border-box;position: relative;}
            div div {width: 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{width: 800px;height: 500px;position: relative;border: 1px solid #000;}
            #ball{width: 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 {width: 50px;height: 50px;border-radius: 50%;background-color: darkorange;position: absolute;top: 0;}
            .wall {width: 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>

 

 
posted @ 2019-12-21 15:40  优冠的味道  阅读(167)  评论(0编辑  收藏  举报