• 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 {
                     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>
     
  • 相关阅读:
    在vue.js中mixin和页面执行顺序问题
    【转载】Node.js 教程(菜鸟教程系列)
    【转载】一致性hash算法释义
    多线程还是多进程的选择及区别
    腾讯
    gdb命令与调试方法
    面试题56:链表中环的入口节点
    面试题52:缺少i的乘积数组
    UML类图
    面试题51:数组中重复的数字
  • 原文地址:https://www.cnblogs.com/wuziqiang/p/12077098.html
Copyright © 2020-2023  润新知