---恢復內容開始---
今天在學習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語句,清除計時器.
理解了.