關於javascript的window.onscroll方法


---恢復內容開始---

今天在學習javascript的過程中被onscroll這個東西堵了一下午.心情極度郁悶.

在高度較大的網頁中,我們通常會加一個返回頂部的按鈕,方便用戶操作.

代碼如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
        <style type="text/css">
            div{height:300px;}
            #btn1{position:fixed;bottom:0;right:0;}
        </style>
        <script type="text/javascript">
            window.onload = function(){
                var oDiv = document.getElementsByTagName('div');
                var oBtn = document.getElementById('btn1');
                var timer = null;
                var oSys = true;
                var i = 0;
                for (i = 0;i<oDiv.length;i++)
                {
                    if(i%2 == 0)
                    {
                        oDiv[i].style.background = 'yellow';
                    }else if(i%3 == 0)
                    {
                        oDiv[i].style.background = 'red';
                    }else if(i%5 == 0)
                    {
                        oDiv[i].style.background = 'blue';
                    }else
                    {
                        oDiv[i].style.background = 'green';
                    }
                }
                window.onscroll = function(){
                    if(!oSys)
                    {
                        clearInterval(timer);
                    }
                    oSys = false;
                }
                oBtn.onclick = function(){

                    timer = setInterval(function(){
                        
                        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
                        var iSpeed = Math.floor(-scrollTop/8);
                        oSys = true;
                        if(!scrollTop)
                        clearInterval(timer);
                        document.documentElement.scrollTop = scrollTop + iSpeed ;
                    },300)
                
                    
                }
            }
        </script>
    </head>
    <body>
        <input type="button" id="btn1" value="backtotop" />
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
    </body>
</html>

弄這么多DIV純粹是為了填充高度,其實大可不必,設置一個高大上的DIV足以,但是當時腦殘了.廢話不說.實現的功能就是點擊返回頂部按鈕的時候,頁面可以以一個舒服的緩慢減速效果移動到頂部.這當中就產生了一個問題.如果頁面很長,用戶在點擊返回頂部按鈕后,頁面移動到頂部的過程中想停下來(也許發現了什么有趣的東西),如何去停止計時器.

大家知道,在頁面想頂部移動過程中,勢必要觸發window.scroll事件.如果要在觸發事件后停下來的話,很簡單:

window.onscroll = function(){
     clearInterval(timer);          
}

這樣,只要用戶在頁面返回頂部過程中拖動滑動條,頁面就會停止自動滾動.但是很明顯,返回頂部的函數也會觸發window.onscroll事件,這樣,我們點擊返回頂部后,頁面向上移動一下,就會停下來.因為計時器被清除了.

那么如何才能讓瀏覽器識別出到底是系統在執行函數的自動滾動,還是用戶自己操作的呢?

在第一段代碼中,我們聲明了一個變量:oSys,定義為true.之后我們在計時器函數中插入了它(請自己看代碼).這樣每次計時器執行內置函數的時候,都會初始化oSys的值為true.

結合下面的代碼段:

window.onscroll = function(){
   oSys = false;
    
}

效果就是,當計時器中的函數在執行過程中,oSys變量的值被初始化為true.而一旦函數執行滾動語句,就觸發window.onscroll事件,導致oSys的值變為false?為了檢驗這個結論,下了下面代碼

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <div style="height:5000px;width:100%;background:gray;"></div>
        <input type="button" id="btn1" value="toTop" style="position:fixed;bottom:0;right:0;"/>
        <script type="text/javascript">
            var oSys = true;
            var oBtn = document.getElementById('btn1');
            oBtn.onclick = function(){
                
                setInterval(function(){
                    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
                    var iSpeed = Math.floor(-scrollTop/8);
                    var oSys = true;
                    if(scrollTop){
                        document.documentElement.scrollTop = document.body.scrollTop = scrollTop + iSpeed;
                        alert(oSys);
                    }
                    
                },3000)
            window.onscroll = function(){
                oSys = false;
            }
            }
        </script>
    </body>
</html>

結果發現每次彈出的都是true.這說明我們上面的推論是錯誤的.

那就是說window.onscroll事件是在滾動完成后觸發的,而不是滾動的同時.這也符合函數按順序依次執行的邏輯:在滾動函數執行完成后,進入window.onscroll觸發的函數.那么可以確定,每次進入window.onscroll函數時,oSys的值總是true.而觸發onscroll事件后,進入onscroll引用的函數function(){oSys = false},然后oSys的值變為false.

假設我們加上這樣一段代碼

window.onscroll = function(){
    if(!oSys)
    {
        clearInterval(timer);   
    }  
    oSys = false;  
}

當計時器函數的一個周期執行完畢后,並且觸發的onscroll事件函數也執行完畢后,oSys的值一定為false.此時如果又進入了onscroll事件函數,那么有兩種可能.

1.計時器函數進入了下一次循環,初始化oSys的值為true.執行完自身后,觸發onscroll事件,進入onscroll觸發的匿名函數,此事,oSys的值為true.跳過if語句,不清除計時器.

2.計時器還沒有進入下一次循環,是用戶手動操作觸發了onscroll事件的函數,那么此時oSys的值由於沒有進過計時器函數內部的oSys初始化,所以值仍然為false.所以會進入if語句,清除計時器.

理解了.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM