1. 程式人生 > >第八節 JS運動基礎

第八節 JS運動基礎

運動基礎

  讓Div運動起來

  速度——物體運動的快慢

  運動中的Bug

    不會停止

    速度取某些值會無法停止

    到達位置後再點選還會運動

    重複點選速度加快

勻速運動(速度不變)

運動框架及應用:

  運動框架:

    在開始運動時,關閉已有定時器

    把運動和停止隔開(if/else)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JS運動基礎</
title> <style> #div1{ width: 200px; height: 200px; background: yellow; position: absolute; top: 50px; left: 0px; } </style> <script> var timer=null; //用於儲存定時器 function
startMove() { var oDiv=document.getElementById('div1'); clearInterval(timer); //不管之前有沒有定時器,都先關閉,然後下面開啟定時器,以保證每次點選該事件時只有一個定時器在工作, timer=setInterval(function () { var speed=7; //控制物體運動的快慢 //注意此時,速度為7,而距離300不能整除7,所以當到達294時直接跳過300,而直接到301,所以物體就不會停止,而是繼續向下運動,
// if (oDiv.offsetLeft==300){ //當離左邊的距離為300畫素的時候,關掉定時器,使其停止運動 if (oDiv.offsetLeft>=300){ //解決不會停止的辦法,此時停在的301px的位置,但是問題又來了,如果再次點選按鈕, // 則物體會運動7畫素,再點選一下,有運動7畫素,一直點選,一直運動7的倍數個畫素 //這是因為,每次點選按鈕時,都會重新開一個定時器,所以每次點選就會運動一下,解決辦法如下else中語句 clearInterval(timer); //到達終點以後要做的事情 } else { oDiv.style.left=oDiv.offsetLeft+speed+'px'; //到達終點之前要做的事情 } // oDiv.style.left=oDiv.offsetLeft+speed+'px'; //offsetleft就是取div的位置; speed控制運動速度 }, 30); } </script> </head> <body> <input id="btn1" type="button" value="開始運動" onclick="startMove()"/> <div id="div1"></div> </body> </html>
View Code

 

運動框架例項:

  例1:“分享到”側邊欄(通過目標點,計算速度值)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>側邊隱藏欄</title>
    <style>
        *{margin: 0px;padding: 0px;}
        #div1{
            width: 150px;
            height: 150px;
            background: green;
            position: absolute;
            top: 100px;
            left: -150px;
        }
        #div1 span{
            width: 20px;
            height: 60px;
            line-height: 20px;
            position: absolute;
            background: blue;
            right: -20px;
            top: 20px;
        }
    </style>
    <script>
        window.onload=function () {
            var oDiv=document.getElementById('div1');
            // oDiv.onmouseover=function () {
            //     InOut1(10, 0);   //傳入引數speed, iTarget
            // };
            // oDiv.onmouseout=function () {
            //     InOut1(-10, -150);   //傳入引數speed, iTarget
            // };
            oDiv.onmouseover=function () {
                InOut2(0);   //傳入引數iTarget
            };
            oDiv.onmouseout=function () {
                InOut2(-150);   //傳入引數iTarget
            };
        };

        var timer=null;
        // function Out() {
        //     var oDiv=document.getElementById('div1');
        //     clearInterval(timer);
        //     timer=setInterval(function () {
        //         if (oDiv.offsetLeft == 0) {
        //             clearInterval(timer);
        //         } else {
        //             oDiv.style.left=oDiv.offsetLeft+10+"px";
        //         }
        //     }, 30);
        // }
        //
        // function In() {
        //     var oDiv=document.getElementById('div1');
        //     clearInterval(timer);
        //     timer=setInterval(function () {
        //         if (oDiv.offsetLeft == -150) {
        //             clearInterval(timer);
        //         } else {
        //             oDiv.style.left=oDiv.offsetLeft-10+"px";
        //         }
        //     }, 30);
        // }
        
        //程式碼合併,把要發生變動的“量”定義為引數,呼叫時直接傳入
        // function InOut1(speed, iTarget) {
        //     var oDiv=document.getElementById('div1');
        //     clearInterval(timer);
        //     timer=setInterval(function () {
        //         if (oDiv.offsetLeft == iTarget) {
        //             clearInterval(timer);
        //         } else {
        //             oDiv.style.left=oDiv.offsetLeft+speed+"px";
        //         }
        //     }, 30);
        // }
        
        //程式碼簡化,儘量少傳入引數
        function InOut2(iTarget) {
            var oDiv=document.getElementById('div1');
            clearInterval(timer);
            timer=setInterval(function () {
                var speed=0;
                if (oDiv.offsetLeft>iTarget){
                    speed=-10;      //噹噹前位置大於預設目標位置,向左移動
                } else {
                    speed=10;       //噹噹前位置小於預設目標位置,向右移動
                }
                
                if (oDiv.offsetLeft == iTarget) {
                    clearInterval(timer);
                } else {
                    oDiv.style.left=oDiv.offsetLeft+speed+"px";
                }
            }, 30);
        }
    </script>
</head>
<body>
    <div id="div1">
        <span>分享到</span>
        <a>hhhhhh</a>
    </div>
</body>
</html>
View Code

 

  例2:淡入淡出的圖片(用變數儲存透明度)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>內容淡入淡出-透明度的變換</title>
    <style>
        #div1{
            width: 200px;
            height: 200px;
            background: red;
            filter:alpha(opacity:30);   /*IE透明度*/
            opacity: 0.3;   /*Chrome Firefox透明度*/
        }
    </style>
    <script>
        window.onload = function () {
            var oDiv = document.getElementById('div1');

            oDiv.onmouseover=function () {
                Fade_In_Out(100);   //淡入
            };
            oDiv.onmouseout=function () {
                Fade_In_Out(30);    //淡出
            };
        };

        var alpha = 30;     //因為沒有offsetAlpha該引數,所以我們改變透明度時,需要自定義變數
        var timer = null;
        function Fade_In_Out(iTarget) {
            var oDiv = document.getElementById('div1');
            clearInterval(timer);
            timer = setInterval(function () {
                var speed = 0;      //變化速度
                if (alpha < iTarget){
                    speed = 10;
                } else {
                    speed = -10;
                }

                if (alpha == iTarget){
                    clearInterval(timer);
                } else {
                    alpha += speed;
                    oDiv.style.filter = 'alpha(opacity:'+alpha+')';   //IE改變透明度,其中“:”可以換位“=”
                    oDiv.style.opacity = alpha/100;   //Chrome FireFox
                }
            }, 30);
        }
    </script>
</head>
<body>
    <div id="div1">

    </div>
</body>
</html>
View Code

 

緩衝運動

  逐漸變慢,最後停止

  距離越遠速度越大:速度由距離決定(距離越大,速度越快;距離越小,速度越慢),速度=(目標值-當前值)/縮放係數

  例子:緩衝選單

    Bug:速度調整(所以當用到緩衝運動時,切記一定要用到取整,否則會有誤)    

// alert(Math.ceil(3.01));     //返回值為4,表示向上取整
// alert(Math.floor(3.999));   //返回值為3,表示向下取整   
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>速度調整</title>
    <style>
        #div1{
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
            left: 0px;    /*向右運動*/
            /*left: 600px;    !*向左運動*!*/
            top: 50px;
        }
        #div2{
            width: 1px;
            height: 300px;
            position: absolute;
            background: black;
            left: 300px;
            top: 0px;
        }
    </style>
    <script>
        // alert(Math.ceil(3.01));     //返回值為4,表示向上取整
        // alert(Math.floor(3.999));   //返回值為3,表示向下取整

        function startMove() {
            var oDiv = document.getElementById('div1');
            setInterval(function () {
                //不斷計算left的值,首先是(300-0)/15,之後是(300-x)/15,而x不斷增大,速度也就逐漸變慢
                var speed = (300-oDiv.offsetLeft)/15;

                // speed = Math.ceil(speed);   //當div1向有運動時,速度向上取整
                // speed = Math.floor(speed);     //當div1向左運動時,速度向下取整
                speed = speed>0?Math.ceil(speed):Math.floor(speed);     //上面兩句程式碼的合併

                oDiv.style.left = oDiv.offsetLeft+speed+'px';

                document.title = oDiv.offsetLeft+','+speed;     //把主題title轉換為left和speed的值,方便觀察變化
            }, 30);
        }
    </script>
</head>
<body>
    <button onclick="startMove()">開始運動</button>
    <div id="div1"></div>
    <div id="div2"></div>
</body>
</html>
View Code

 

    跟隨頁面滾動的緩衝側邊欄

      潛在問題:目標值不是整數時;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>右側懸浮框</title>
    <style>
        body{height: 2000px;    /*為了呈現出滾動條*/}
        #div1{
            width: 100px;
            height: 150px;
            background: red;
            position: absolute;
            right: 0px;
            bottom: 318px;
        }
    </style>
    <script>
        //onscroll滾動
        window.onscroll = function(){
            var oDiv = document.getElementById('div1');
            var scrollTop = document.documentElement.scrollTop||document.body.scrollTop;

            // oDiv.style.top = (document.documentElement.clientHeight-oDiv.offsetHeight+scrollTop)/2+'px';
            //此時存在的問題是,在滑動滾動條的時候,div1的變化“有跳動”,跳一下才變換到正確位置,所以我們註釋掉,解決方法為:
            startMove(parseInt((document.documentElement.clientHeight-oDiv.offsetHeight)/2+scrollTop));
            //(可視區的高-div的高)/2 表示把需要懸浮的框,懸浮在靠右中間的位置;
            // 其中parseInt() 表示避免“除以2”時出現0.5的畫素值(螢幕沒有半個畫素的情況),此時懸浮框會出現上下抖動的情況,而用parseInt()取整後就不會出現這種情況了。
        };

        var timer=null;
        function startMove(iTarget) {
            var oDiv = document.getElementById('div1');
            clearInterval(timer);
            timer = setInterval(function(){
                var speed = (iTarget-oDiv.offsetTop)/6;
                speed = speed>0?Math.ceil(speed):Math.floor(speed);     //取整

                if (oDiv.offsetTop==iTarget){
                    clearInterval(timer);
                } else {
                    document.getElementById('txt1').value = oDiv.offsetTop;   //調整懸浮框的位置,以便觀察
                    oDiv.style.top = oDiv.offsetTop+speed+'px';
                }
            }, 30);
        }
    </script>
</head>
<body>
    <input type="txt1" id="txt1" style="position: fixed; right: 0px; top: 0px;"/>
    <div id="div1"></div>
</body>
</html>
View Code

 

勻速運動的停止條件

  運動終止條件:

    勻速運動:距離足夠近

    緩衝運動:兩點重合

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>勻速運動停止條件</title>
    <style>
        #div1{
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
            left: 0px;    /*向右運動*/
            /*left: 600px;    !*向左運動*!*/
            top: 50px;
        }
        #div2{
            width: 1px;
            height: 300px;
            position: absolute;
            background: black;
            left: 300px;
            top: 0px;
        }
        #div3{
            width: 1px;
            height: 300px;
            position: absolute;
            background: black;
            left: 100px;
            top: 0px;
        }
    </style>
    <script>
        // alert(Math.abs(-6));    //返回值為6,abs()表示絕對值

        var timer = null;
        function startMove(iTarget) {
            var oDiv = document.getElementById('div1');

            clearInterval(timer);
            timer = setInterval(function () {
                var speed = 0;
                if (oDiv.offsetLeft<iTarget){
                    speed = 7;  //故意找一個不能整除的數字,以便發現問題
                } else {
                    speed = -7;
                }
                //問題出現,由於最終結果不為0,所以會因為有一定的偏差而相對抖動,我們所能夠解決的是在存在偏差的情況下,結束抖動,解決辦法如下:
                if (Math.abs(iTarget-oDiv.offsetLeft)<=7){
                    clearInterval(timer);

                    //因為上面偏差是不能消除的,此時我們為了消除偏差,強行令left值等於目標值
                    oDiv.style.left = iTarget+'px';    //由於程式執行的速度較快,這種強行賦值使用肉眼是觀察不到的
                } else {
                    oDiv.style.left = oDiv.offsetLeft+speed+'px';
                }
            }, 30);
        }
    </script>
</head>
<body>
    <button onclick="startMove(100)">到100px</button>
    <button onclick="startMove(300)">到300px</button>
    <div id="div1"></div>
    <div id="div2"></div>
    <div id="div3"></div>
</body>
</html>
View Code