• JavaScript的运动原理1


    运动基础

    1. 在JavaScript中,如何让一个页面元素动起来?
      首先,我们需要了解的是,在JavaScript中如何让一个页面元素动起来。

    我们先来实现一个简单的功能,当我们点击按钮之后,让一个元素动起来。并且到达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);  
            };

    总结:在上面的代码中,是我们一般让一个元素运动起来的基本流程。下面进行一个简单的总结:

    1. 首先是存在的问题:处于匀速运动的元素没有办法进行在不整除的情况下在临界点停止。
    2. 在上面的代码中,可以将整个过程大致分为三个步骤:
      • 清除定时器,保证只有一个定时器在执行
      • 开启定时器
      • 开始运动(需要同时加入一个判断,以便在需要的时候或者满足某个要求时停止运动)

    简单运动的封装

    为了让我们上面的代码可以具备更高的复用性,下面我们把上面的代码进行一个简单的封装。

    示例:

    <!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 = ()=>{    
                startMove(); 
                // 将运动相关的内容全部放到startMove这个函数中,然后调用既可以让元素进行运动
                function startMove() {
                    clearInterval(iTimer);
                    iTimer = setInterval(()=>{
                        if (oDiv.offsetLeft === 500) {
                            // 清除定时器  
                            clearInterval(iTimer);
                        }else { // 没有到达边界才能继续运动
                            oDiv.style.left = oDiv.offsetLeft + 10 + 'px';  // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动
                        }
                    },30);
                }
            };
        </script>
    </html>
    

    在上面的代码中,我们将运动相关的内容放到了一个函数startMove中,并且调用了这个函数,下面来根据这个函数进行案例的开发。

    案例1:分享到功能

    首先,先来实现基本的功能:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
            <style>
                #div1 {
                     100px;
                    height: 200px;
                    background:red;
                    position: absolute;
                    left: -100px;
                    top: 200px;
                }
                #div2 {
                     30px;
                    height: 70px;
                    background: black;
                    position:absolute;
                    right:-30px;
                    top: 70px;;
                    color:#fff;
                    text-align: center;
                }
            </style>
        </head>
        <body>
            <div id="div1">
                <div id="div2">分享到</div>
            </div>
        </body>
        <script>
            // 1. 首先获取两个元素
            let oDiv1 = document.getElementById('div1');
            let oDiv2 = document.getElementById('div2');
            let iTimer = null;  
            
            // 给为父级的div绑定mouseover 和 mouseout事件 
            oDiv1.onmouseover = function() {
                this.style.left = 0 + 'px'; // 鼠标移入,让div元素出现
            };
            
            oDiv1.onmouseout = function() {
                this.style.left = -100 + 'px'; // 鼠标移出,让div隐藏
            }; 
            
        </script>
    </html>
    

    上面的代码中,我们鼠标移入,元素出现。鼠标移出,元素消失。
    下面我们来使用我们的startMove函数,给元素出现和消失加上一个过渡的效果。

    我们的startMove函数如下:

    function startMove() {
        clearInterval(iTimer);
        iTimer = setInterval(()=>{
            if (oDiv.offsetLeft === 500) {
                // 清除定时器  
                clearInterval(iTimer);
            }else { // 没有到达边界才能继续运动
                oDiv.style.left = oDiv.offsetLeft + 10 + 'px';  // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动
            }
        },30);
    }

    我们想要在分享到功能里使用这个函数,我们需要对我们的函数根据分享到的需求进行一定程度的更改。
    首先是,将我们函数中的oDvi更改为oDiv1

    其次是我们分享到案例的需求在鼠标移入时需要将元素逐渐的显示,而鼠标移出时,需要将元素逐渐的隐藏。所以我们需要将startMove函数创建两个
    ,并且当鼠标移出时,速度应该将函数中的+10变为-10

    当然,也别忘了去更该元素边界的值。当移出时,边界为0,移入时,边界为-100.

    如下:

    鼠标移入时调用的startMove1函数:

    function startMove1() {
        clearInterval(iTimer);
        iTimer = setInterval(()=>{
            if (oDiv1.offsetLeft === 0) {
                // 清除定时器  
                clearInterval(iTimer);
            }else { // 没有到达边界才能继续运动
                oDiv1.style.left = oDiv.offsetLeft + 10 + 'px';  // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动
            }
        },30);
    }

    鼠标移出时调用的startMove2函数:

    function startMove() {
        clearInterval(iTimer);
        iTimer = setInterval(()=>{
            if (oDiv1.offsetLeft === -100) {
                // 清除定时器  
                clearInterval(iTimer);
            }else { // 没有到达边界才能继续运动
                oDiv1.style.left = oDiv.offsetLeft - 10 + 'px';  // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动
            }
        },30);
    }

    我们先来将这两个函数放在代码中,进行测试。

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
            <style>
                #div1 {
                     100px;
                    height: 200px;
                    background:red;
                    position: absolute;
                    left: -100px;
                    top: 200px;
                }
                #div2 {
                     30px;
                    height: 70px;
                    background: black;
                    position:absolute;
                    right:-30px;
                    top: 70px;;
                    color:#fff;
                    text-align: center;
                }
            </style>
        </head>
        <body>
            <div id="div1">
                <div id="div2">分享到</div>
            </div>
        </body>
        <script>
            // 1. 首先获取两个元素
            let oDiv1 = document.getElementById('div1');
            let oDiv2 = document.getElementById('div2');
            let iTimer = null;  
            
            // 给为父级的div绑定mouseover 和 mouseout事件 
            oDiv1.onmouseover = function() {
                // this.style.left = 0 + 'px'; // 鼠标移入,让div元素出现
                startMove1();
            };
            
            oDiv1.onmouseout = function() {
                // this.style.left = -100 + 'px'; // 鼠标移出,让div隐藏
                startMove2();
            }; 
            
            function startMove1() {
                clearInterval(iTimer);
                iTimer = setInterval(()=>{
                    if (oDiv1.offsetLeft === 0) {
                        // 清除定时器  
                        clearInterval(iTimer);
                    }else { // 没有到达边界才能继续运动
                        oDiv1.style.left = oDiv1.offsetLeft + 10 + 'px';  // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动
                    }
                },30);
            }
            function startMove2() {
                clearInterval(iTimer);
                iTimer = setInterval(()=>{
                    if (oDiv1.offsetLeft === -100) {
                        // 清除定时器  
                        clearInterval(iTimer);
                    }else { // 没有到达边界才能继续运动
                        oDiv1.style.left = oDiv1.offsetLeft - 10 + 'px';  // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动
                    }
                },30);
            }
        </script>
    </html>
    

    上面的代码中,我们通过创建两个startMove函数,并且对相应的参数进行修改,从而实现了给我们的分享到功能添加了过渡效果。

    进一步升级:
    当然,我们上面的代码中使用的函数其实是非常不灵活的,所以我们下面要做到事就是对之前的函数进行升级,从而让我们的函数具备更强的实用性。

    首先我们再回过头来看下我们刚才写的两个函数,你会发现,大部分的代码其实都是相同的,只有个别的值是不同的,例如元素移动的边界,例如元素
    单位时间内移动的距离。

    我们将上面的两个函数合并成一个函数,只需要将不一样的值提取出来当做参数即可。

    下面是合并之后的函数:

    function startMove(iTarget,iSpeed) {
        clearInterval(iTimer);
        iTimer = setInterval(()=>{
            if (oDiv1.offsetLeft === iTarget) {
                // 清除定时器  
                clearInterval(iTimer);
            }else { // 没有到达边界才能继续运动
                oDiv1.style.left = oDiv1.offsetLeft +  iSpeed + 'px';  
            }
        },30);
    }

    上面的函数升级完成之后,我们在重新的将这个函数应用到我们的分享到功能的代码当中去。

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
            <style>
                #div1 {
                     100px;
                    height: 200px;
                    background:red;
                    position: absolute;
                    left: -100px;
                    top: 200px;
                }
                #div2 {
                     30px;
                    height: 70px;
                    background: black;
                    position:absolute;
                    right:-30px;
                    top: 70px;;
                    color:#fff;
                    text-align: center;
                }
            </style>
        </head>
        <body>
            <div id="div1">
                <div id="div2">分享到</div>
            </div>
        </body>
        <script>
            // 1. 首先获取两个元素
            let oDiv1 = document.getElementById('div1');
            let oDiv2 = document.getElementById('div2');
            let iTimer = null;  
            
            // 给为父级的div绑定mouseover 和 mouseout事件 
            oDiv1.onmouseover = function() {
                // this.style.left = 0 + 'px'; // 鼠标移入,让div元素出现
                startMove(0,10);
            };
            
            oDiv1.onmouseout = function() {
                // this.style.left = -100 + 'px'; // 鼠标移出,让div隐藏
                startMove(-100,-10);
            }; 
            
            function startMove(iTarget,iSpeed) {
                clearInterval(iTimer);
                iTimer = setInterval(()=>{
                    if (oDiv1.offsetLeft === iTarget) {
                        // 清除定时器  
                        clearInterval(iTimer);
                    }else { // 没有到达边界才能继续运动
                        oDiv1.style.left = oDiv1.offsetLeft +  iSpeed + 'px';  
                    }
                },30);
            }
        </script>
    </html>

    上面的代码中,我们顺利的通过我们的startMove函数给分享到功能添加了过渡的效果。

    图片的淡入淡出效果:

    下面我们再来看另外的一个效果,图片的淡入淡出,还是通过我们上面定义好的startMove函数来实现效果。

    首先,我们上面的函数当中,只是针对oDiv1,为了让我们的函数可以处理任意的元素,我们将oDiv1替换成函数的形参。

    例如:

    function startMove(oDom,iTarget,iSpeed) {
        clearInterval(iTimer);
        iTimer = setInterval(()=>{
            if (oDom.offsetLeft === iTarget) {
                // 清除定时器  
                clearInterval(iTimer);
            }else { // 没有到达边界才能继续运动
                oDom.style.left = oDom.offsetLeft +  iSpeed + 'px';  
            }
        },30);
    }

    上面的代码当中,我们将函数操作的元素提取出来,变成了函数的形参,这样做之后,我们就可以让我们的函数针对任意的元素。

  • 相关阅读:
    stl_heap.h
    stl_tree.h
    stl_set.h
    stl_multiset.h
    ant:如何用ant将web project打包成war包
    将java project打包成jar包,web project 打包成war包的几种演示
    windows的各种扩展名详解
    图解教你如何使用ANT打包java程序
    使用apache mail发送邮件错误解决办法
    java虚拟机的运行原理
  • 原文地址:https://www.cnblogs.com/jhflyfish/p/11488850.html
Copyright © 2020-2023  润新知