JS錯誤記錄 – 右側懸浮框 – 緩衝運動

CarpenterZoe發表於2018-12-25

 

本次練習錯誤總結:

 

1.  正確:
startMove( document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop);
錯誤:
startMove(document.documentElement.clientHeight - oDiv.offsetTop + scrollTop);
startMove(iTarget); 這個函式的目標點 iTarget 應該是 可視窗高度 – div的高度 + 滾動條上方的滾動距離
div的高度是  offsetHeight,是一整個div的高度。 div的offsetTop是它的top位置值。
 
2.  必須用timer指定定時器,否則清除定時器時清除不了。 

timer = setInterval(function (){ },30)    // 不能直接寫setInterval(function (){ },30)

3.  函式作用域問題?? (感覺經常犯這種錯誤)
var speed = (iTarget - oDiv.offsetTop)/4;
該速度變數是定時器使用,所以要定義在定時器的函式裡面。 而不是定義到startMove( ); 這個運動函式裡。
 
4. 
 startMove(document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop); 

//這裡末尾不應該加‘px’, 括號內是函式的引數,而不是賦值給樣式!
且後面定時器裡 if(oDiv.offsetTop == iTarget)  offsetTop返回值為數字。 iTarget不需要px單位。

5.  clearInterval ( ); 清除定時器是在startMove ( ); 運動函式裡面的一開始去清除,而不是外面。且應該在括號內指定(timer)。

6.  該段程式碼oDiv獲取過兩次。在window.onscroll函式和 function startMove( )裡分別獲取了。
因為運動函式和視窗啟動自帶的滾動條函式不是包含關係,所以要重新獲取一遍div變數。


7.  定時器格式  setInterval ( function () {  },30)   括號裡要跟function函式。

8. 
 if(iTarget==oDiv.offsetTop)     //應該是oDiv.offsetTop == iTarget,即運動的位置達到了目標值 

疑問
為什麼window.onscroll函式 和後面的startMove函式是分別執行的關係,而不是包含關係?

第二次寫的程式碼批註:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>右側懸浮框</title>
  <style>
    #div1{
      width: 100px;
      height: 150px;
      background-color: plum;
      position: absolute;
      right: 0;
      bottom: 0;
    }
  </style>
  <script>
    window.onscroll = function () {
      var oDiv = document.getElementById(`div1`);
      var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;

      //startMove(document.documentElement.clientHeight-oDiv.offsetTop+scrollTop);
      startMove(document.documentElement.clientHeight-oDiv.offsetHeight+scrollTop);
      //這裡應該是oDiv.offsetHeight,不是offsetTop。  區別是???
    };

    var timer = null;

    function startMove(iTarget) {

      clearInterval(timer);

      var oDiv = document.getElementById(`div1`);

      //setInterval(function (){   這裡沒用timer指定定時器。。。所以前面清除定時器和這裡對應不上。
      timer = setInterval(function (){
        var speed = (iTarget - oDiv.offsetTop)/4; //這個變數是定時器裡面使用的,要定義到定時器的函式裡。
        speed = speed>0? Math.ceil(speed):Math.floor(speed);

        if (oDiv.offsetTop == iTarget)
        {
          clearInterval(timer);
        }
        else
        {
          oDiv.style.top = oDiv.offsetTop + speed + `px`;
        }
      },30)
    }
  </script>
</head>
<body style="height: 2000px";>
<div id="div1">
</div>
</body>
</html>

 

錯誤程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>右側懸浮框</title>
    <style>
        #div1{
            width: 100px;
            height: 150px;
            background-color: palevioletred;
            position: absolute;
            right: 0;
            bottom: 0;
        }
    </style>
    <script>
        window.onscroll = function () {
            var oDiv = document.getElementById(`div1`);
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;

            startMove(document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop); //這裡末尾不應該加‘px’! 括號內是函式的引數,而不是賦值給樣式!
        };
            
            var timer = null;
            //clearInterval();     //此處是否需要清除? 要清除,是在startMove運動開始裡面去清除。

            //timer=setInterval(function startMove(iTarget) //寫法錯誤,定時器是在startMove函式裡面開啟,定時器和函式不是同級的。
            function startMove(iTarget)
            {
                var oDiv = document.getElementById(`div1`);
                //運動函式和視窗啟動自帶的滾動條函式不是包含關係,所以要重新獲取一遍div變數。

                clearInterval(timer);

                timer=setInterval(function () {    //setInterval格式:括號裡面要跟個函式function
                    var speed = (iTarget - oDiv.offsetTop)/4; // speed不是前面startMove傳參的,是新的變數,這裡要用var!!
                    speed=speed>0?Math.ceil(speed):Math.floor(speed);

                    //if(iTarget==oDiv.offsetTop){   //應該是oDiv.offsetTop == iTarget,即運動的位置達到了目標值
                    if(oDiv.offsetTop == iTarget)
                    {
                        clearInterval(timer);
                    }
                    else
                    {
                        oDiv.style.top = oDiv.offsetTop+speed+`px`;
                    }
                },30);
            }
    </script>
</head>
<body style="height: 2000px;">
<div id="div1">
</div>
</body>
</html>

 

正確程式碼:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>無標題文件</title>
    <style>
        #div1 {width:100px; height:150px; background:red; position:absolute; right:0; bottom:0;}
    </style>
    <script>
        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+`px`;
            startMove(document.documentElement.clientHeight-oDiv.offsetHeight+scrollTop);
            //可視窗高度-div高度+滾動條頂部距離
       };

        var timer=null;

        function startMove(iTarget)
        {
            var oDiv=document.getElementById(`div1`);
            //為什麼要分別獲取div1??
            // 為什麼window.onscroll函式 和後面的startMove函式是分別執行的關係,而不是包含關係?

            clearInterval(timer);
            timer=setInterval(function (){
                var speed=(iTarget-oDiv.offsetTop)/4;
                speed=speed>0?Math.ceil(speed):Math.floor(speed);

                if(oDiv.offsetTop==iTarget)
                {
                    clearInterval(timer);
                }
                else
                {
                    oDiv.style.top=oDiv.offsetTop+speed+`px`;
                }
            }, 30);
        }
    </script>
</head>

<body style="height:2000px;">
<div id="div1"></div>
</body>
</html>

 

相關文章