2009-09-06 13 views
16

Derzeit ist mein Programm an einer Stelle, wo es sowohl für den Benutzer ein bestimmtes Element scrollen, sondern auch manchmal automatisch dieses Element selbst scrollt. (Nicht eine allmähliche, schöne Scroll, aber ein sofortiger Sprung. Es macht Sinn im Zusammenhang, ich schwöre.)Machen Sie "ScrollLeft"/"ScrollTop" Änderungen nicht Scroll Event Listener

Gibt es eine Möglichkeit, die Scroll-Ereignis nicht auslösen, wenn das Scrollen durch Einstellung ScrollLeft oder ScrollTop getan wurde? Mein erster Gedanke war ein Basisschalter, wie:

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

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

aber da Ereignisse nicht sofort auslösen (oops, duhh), das ist keine praktikable Lösung. Welche anderen Antworten könnte ich versuchen? Ich benutze auch jQuery, wenn das irgendwas hilft.

Antwort

17

einfachste generische Methode ? Setzen Sie das Flag im Event-Handler zurück. Sie sollten zuerst überprüfen, ob Sie tatsächlich den Wert ändern, da sonst ein Ereignis nicht ausgelöst wird - als Rodrigo notes ist es eine gute Übung, dies in so genannte "Setter" -Funktionen zu berücksichtigen:

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

... 

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

    if (ignore) return false; 

    ... 
} 

Aber, je nach Ihren Bedürfnissen, speichern Sie die Scroll-Position möglicherweise bereits irgendwo; Wenn ja, aktualisiere und überprüfe das als deine Flagge. Etwas wie:

element.scrollLeft = currentScrollLeft = x; 

... 

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

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

    ... 
} 
+0

In meinem Code habe ich ein Problem gefunden: Manchmal passiert es, dass scrollLeft bereits 0 ist, dann setzt mein Code es ebenfalls auf 0. Daher wird kein Scroll-Ereignis ausgelöst und der nächste Benutzer wird ignoriert. (Das ist nur ein Problem, wenn sie mit Home, End usw. scrollen). Aber das ist definitiv eine nahe Lösung - und ich wusste, dass ich in dieser Dummy-Implementierung etwas Dummes verpasst habe. Vielen Dank! – Matchu

+0

Ich habe mich gefragt, ob ... Dann ist es am besten zu überprüfen, ob Sie den Wert ändern, bevor Sie die Flagge setzen - setzen Sie ihn nicht, wenn Sie nicht sind.Möglicherweise haben Sie diesen Code bereits in einer separaten Funktion ausgeklammert, aber wenn nicht, würde es das einfacher machen - sehen Sie Rodrigos Antwort für ein Beispiel dafür. – Shog9

1

könnte Sie constantly check wenn die scroll position Änderungen ...

+0

Das ist keine schöne Lösung, aber wenn Sie sagen, dass die Ereignisse nicht sofort auslösen ... – marcgg

+0

Wenn ich sage, dass Ereignisse nicht sofort auslösen, meine ich das im Allgemeinen. Wenn ich die ersten drei Zeilen verwende, kommen und gehen sie alle, wenn das Scroll-Ereignis ausgelöst wird, da Javascript genau so funktioniert. – Matchu

+0

Diese Lösung ist schöner als die akzeptierte Lösung, denke ich. Die akzeptierte Lösung möchte, dass Sie eine globale Variable erstellen und brechen, sobald Sie zwei 'onScroll'-Handler haben möchten. Diese Lösung liefert jedoch keine bissige UX, also sind es überall Steine ​​und harte Stellen. – jcarpenter2

0

Sie könnten versuchen, den Offset oben auf Ihrem Element zu speichern und gegen die scrollTop passend, wenn Sie innerhalb OnScroll Schritt:

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

Wie wäre es mit einem Setter?

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

In Ordnung, meine endgültige Lösung, aus den Bau von Shog9 (nicht mein richtiger Code, aber mein Ansatz):

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

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

Die if-Anweisung nur die Flagge ignorieren setzt wenn der scrollLeft-Wert sich tatsächlich ändert, werden Fälle wie die Einstellung von 0 auf 0 das Flag nicht falsch setzen.

Danke, alle!

+0

so ist die richtige Antwort? – Rodrigo

+0

Unsicher. Was ist Protokoll hier? Wenn ich einen Teil einer Antwort verwende, dann baue ich ihn aus, um die vollständige Antwort zu erhalten, markiere ich meine eigene oder die andere? – Matchu

+0

Die angenommene Antwort wurde so bearbeitet, dass sie diesen Vorbehalt enthält, also passt sie nun zu dieser Antwort :) Cool! – Matchu