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