2009-09-06 211 views
16

當前我的程序處於偵聽用戶滾動某個元素的位置,但有時也會自動自動滾動此元素。 (不是一個漸進的,漂亮的滾動,而是一個瞬間跳躍,這是有道理的,我發誓。)使「scrollLeft」/「scrollTop」更改不會觸發滾動事件偵聽器

有沒有辦法讓滾動事件不觸發,如果滾動是通過設置scrollLeft或scrollTop?我首先想到的是一個基本的開關,如:

ignoreScrollEvents = true; 
element.scrollLeft = x; 
ignoreScrollEvents = false; 

function onScroll() { 
    if(ignoreScrollEvents) return false; 
} 

但由於事件不會立即觸發(哎呀,duhh),這不是一個可行的解決方案。我還可以嘗試其他類型的答案嗎?我也使用jQuery,如果這有幫助的話。

回答

17

最簡單的泛型方法?只需重置事件處理程序中的標誌即可。你需要先檢查一下,如果你真的改變了數值,否則一個事件將不會被觸發 - 因爲Rodrigo notes,這裏的一個好習慣是把這個分解成所謂的「setter」函數:

function setScrollLeft(x) 
{ 
    if (element.scrollLeft != x) 
    { 
    ignoreScrollEvents = true; 
    element.scrollLeft = x; 
    } 
} 

... 

function onScroll() 
{ 
    var ignore = ignoreScrollEvents; 
    ignoreScrollEvents = false; 

    if (ignore) return false; 

    ... 
} 

但是,根據您的需要,您可能已經在某處存儲了滾動位置;如果是這樣,只需更新並檢查該標誌即可。例如:

element.scrollLeft = currentScrollLeft = x; 

... 

function onScroll() 
{ 
    // retrieve element, etc... 

    if (element.scrollLeft == currentScrollLeft) return false; 

    ... 
} 
+0

在我的代碼中,我遇到了一個問題:有時它會發生,比如說scrollLeft已經爲0,那麼我的代碼也會將它設置爲0.因此,不會觸發滾動事件,並且忽略下一個用戶滾動。 (如果他們使用Home,End等進行滾動,這只是一個真正的問題)。但這絕對是一個密切的解決方案 - 而且我知道我在這個虛擬實現中錯過了一些愚蠢的東西。謝謝! – Matchu 2009-09-06 21:26:00

+0

我想知道那件事...那麼你最好的選擇是在設置標誌之前檢查你是否改變了價值 - 如果你不是這樣的話,不要設置它。你可能已經把這個代碼分解成了一個單獨的函數,但是如果沒有,那麼這樣做會更容易一些 - 參見Rodrigo的回答。 – Shog9 2009-09-06 21:29:36

1

你可以constantly check如果scroll position變化...

+0

這不是一個漂亮的解決方案,但如果你說這些事件不會立即觸發... – marcgg 2009-09-06 21:13:30

+0

當我說事件不會立即觸發,我的意思是一般。如果我運行前3行,它們都會在滾動事件觸發時來來去去,因爲這正是Javascript的工作原理。 – Matchu 2009-09-06 21:19:18

+0

我認爲,這種解決方案比我們接受的解決方案更漂亮。被接受的解決方案希望你創建一個全局變量,並且一旦你想要兩個'onScroll'處理器就會中斷。然而,這個解決方案並沒有提供一個敏捷的用戶體驗,所以它確實是一個非常有趣的地方。 – jcarpenter2 2015-06-25 20:28:45

0

你可以嘗試保存你的元素的偏移頂部和匹配它反對scrollTop的,當你進入車內onScroll:

function onScroll(){ 
    var scrollTop = (document.documentElement.scrollTop || document.body.scrollTop), 
    offsetTop = $('selector').offset().top; 
    if(offsetTop > scrollTop){ 
     //user has not scrolled to element so do auto scrolling 
    } 
} 
2

一個二傳手怎麼樣?

var _preventEvent = false; // set global flag 
 

 
function setScrollTop(amount) { 
 
    _preventEvent = true; // set flag 
 
    document.documentElement.scrollTop = amount * Math.random(); 
 
} 
 

 
function setScrollLeft(amount) { 
 
    _preventEvent = true; // set flag 
 
    document.documentElement.scrollLeft = amount * Math.random(); 
 
} 
 

 
// scroll event listener 
 
window.onscroll = function() { 
 
    console.clear(); 
 
    
 
    if (_preventEvent) { 
 
    _preventEvent = false; // reset flag 
 
    return; 
 
    } 
 
    
 
    console.log('normal scroll'); 
 
}
html{ height:500%; width:500%; } 
 
button{ position:fixed; } 
 
button + button{ top:50px; }
<button onclick=setScrollTop(1000)>Random scrollTop</button> 
 
<button onclick=setScrollLeft(1000)>Random scrollLeft</button>

0

好吧,我的最終解決方案,構建關Shog9的(不是我真正的代碼,但我的方法):

var oldScrollLeft = element.scrollLeft; 
element.scrollLeft = x; 
if(element.scrollLeft != oldScrollLeft) { 
    ignoreScrollEvents = true; 
} 

function onScroll() { 
    if(!ignoreScrollEvents) performGreatActions(); 
    ignoreScrollEvents = false; 
} 

if語句只設置忽略標誌當scrollLeft值實際上最終發生變化時,例如從0到0的設置不會錯誤地設置標誌。

謝謝,所有!

+0

所以正確答案是? – Rodrigo 2009-09-09 19:09:00

+0

不確定。這裏有什麼協議?如果我使用答案的一部分,然後建立它以達到完整答案,我會標記自己的還是其他的答案? – Matchu 2009-09-09 21:49:15

+0

接受的答案已被編輯,包括此警告,所以它現在匹配這個答案:)酷! – Matchu 2017-06-30 23:27:33

相關問題