Es ist ziemlich üblich, dass die .animate()-Funktion von jQuery durch ein mouseEnter- oder hover-Ereignis ausgelöst wird. Das ist alles gut und schön, aber es bedeutet, dass wir damit rechnen müssen, dass diese Ereignisse mehrmals ausgelöst werden. Wenn das Element mit dem angehängten Hover-Ereignis mehrmals überfahren wird, bedeutet dies, dass die Animation mehrmals ausgelöst wird, was normalerweise unerwünscht ist. Der übliche Weg, damit umzugehen, ist die Verwendung der .stop()-Funktion, wie zum Beispiel
$(this).stop().animate({ width: "200px" });
Das ist jedoch definitiv keine Allheilmittel-Lösung. Lassen Sie uns also erforschen.
Wir wissen bereits, dass die **Nicht**-Verwendung von .stop() problematisch ist, da sich dann die Animationen in der Warteschlange aufreihen und es bei mehreren schnellen Hovern etwas umständlich ist. Aber die Nicht-Verwendung von .stop() ist auch in gewisser Weise perfekt, da die mouseEnter-Animation und die mouseLeave-Animation vollständig und sequenziell ausgeführt werden. Es ist diese Geschmeidigkeit, die ich hier anstrebe, nur ohne die Warteschlange.
Die Verwendung von .stop() verhindert die Warteschlange, **aber sie verhindert auch, dass die Animationen einen vollständigen Zyklus durchlaufen.** Maus weg, die stop-Funktion wird ausgelöst und stoppt die Animation, die bei mouseEnter ausgelöst wurde, und beginnt die Animation, die alles zurücksetzt.
Das Erste, womit ich anfing zu experimentieren, war die Verwendung von .stop() nur vor der einen oder der anderen Animation, aber das hilft nicht viel. Die .stop()-Funktion hat auch einige Parameter, die Sie übergeben können, wobei der zweite angibt, ob die Animation erzwungen abgeschlossen werden soll. Wenn er auf true gesetzt ist, wird die Animation tatsächlich beendet, aber sie geschieht nicht sanft, sie ruckt zu ihrem Endzustand, was ich im Allgemeinen als unerwünscht empfinde.
Die Lösung liegt darin, **nicht** mit einer neuen Animation zu beginnen, bis der Zustand des Elements nicht mehr animiert wird. Auf diese Weise müssen Sie sich nicht einmal um Warteschlangen kümmern, da ohnehin nur eine Animation gleichzeitig laufen kann. Es gibt ein paar Möglichkeiten, dies zu erreichen, aber diese fand ich am saubersten
$("div").hover(function(){
$(this).filter(':not(:animated)').animate({ width: "200px" });
}, function() {
$(this).animate({ width: "100px" });
});
Auf dem Weg hierher gab es viele Ideen. Schauen Sie sich die unten stehende Demo an, um all die verschiedenen Optionen zu sehen, die ich durchgegangen bin, sowie eine zusätzliche Methode, die ebenfalls funktioniert.
UPDATE: Schauen Sie sich unbedingt Ralf Stoltz's noch bessere Lösung an.
Demo-Seite funktioniert nicht. Ich habe es im Quellcode gesehen :-/
Scheint, als sei in der letzten Stunde etwas passiert.
Sollte behoben sein. Aus irgendeinem unerklärlichen Grund gab es ein Problem mit der Zeichenkodierung der Seite.
Es funktioniert. Sehr schön!
Wow..!
Das ist großartig!
Danke Mann..!
Wow, sehr clever. Danke! Ich habe mich immer auf .stop() verlassen, aber den plötzlichen Abbruch der Animation mochte ich nie.
Oh, ich habe gerade die Demo-Seite getestet. Und mit der von Ihnen vorgeschlagenen neuen Methode werden die Animationen bei allen Elementen ausgelöst, wenn sie schnell überfahren werden. Ich bin mir nicht sicher, ob ich mich verständlich mache. Aber zum Beispiel, wenn Sie dies für ein Menü verwenden und der Benutzer nur schnell mit der Maus über alle Menüpunkte fährt, wird alles gleichzeitig ausgelöst (was bei stop() nicht der Fall war).
Sehr interessant, Chris.
Ich könnte mir Fälle vorstellen, in denen die eine Methode der anderen vorgezogen würde (vollständige Zyklen ausführen vs. nicht).
Aufschlussreich. Danke dafür.
Cool! Tolle Tipps für zukünftige Projekte.
Tolle Recherche – das ist ein Problem, mit dem ich mich viel beschäftigt habe.
Wenn dies ein Menü wäre, gäbe es immer noch ein großes Problem. Das Problem mit dem Filter ist, dass, wenn Sie die Maus außerhalb des Elements bewegen und dann wieder hineinbewegen, bevor es zu seinem Standardzustand zurückanimiert wird, es nicht wieder zu seinem Hover-Zustand animiert wird – obwohl Sie es überfahren.
Super verwirrend. Ich bevorzuge tatsächlich die .stop()-Lösung – sie ist nicht die schönste, aber sie funktioniert.
Das ist genau richtig. Zuerst dachte ich, Chris' Lösung sei besser als die Verwendung von stop(), aber Sie haben den Nagel auf den Kopf getroffen. Ich bleibe vorerst bei stop().
Das ist definitiv ein guter Punkt, für etwas wie ein Dropdown-Menü, bei dem die Hover-Animation etwas anderes als nur rein Ästhetisches bewirkt.
Ich habe gerade die Demo getestet und es scheint, dass die "Dequeue"-Version die einzige war, die zuverlässig funktionierte. Die "Animated Test" machte einmal einen "Zyklus", dann ging ich weg und fuhr sie erneut über (nachdem die Animation offensichtlich abgeschlossen war) und nichts geschah.
Sehr cooles Tutorial und Illustration. Diese können für viele Umstände sehr nützlich sein.
Sehr cool! Ich benutze jetzt
$(this).stop().animate({ width: "200px" }, {queue:false});Ist das gut?
Coole Beispiele, sie scheinen alle ihre Mängel zu haben. Ich würde die Warteschlange vorziehen.
Chris, ich bin beeindruckt von Ihrem jQuery-Wissen. Das ist eine fantastische Sammlung von Beispielen! Vielen Dank für Ihre Einblicke und die Demos!
Chris, du solltest die Sprüche von Duke Nukem übernehmen... besonders in diesem Fall
„verdammt, ich bin gut“.
Die beiden unteren Beispiele auf den Demo-Seiten... Wenn Sie das mouseover-Ereignis auslösen, dann schnell mouseout und wieder mouseover, gibt es Probleme.
Die Animation kehrt zum Nicht-aktiven Zustand zurück und der Mauszeiger befindet sich auf dem Link und es passiert nichts.
Das ist wirklich ein Problem. Gibt es eine Lösung?
Ich benutze :not(:animated) schon seit langer Zeit. Und es ist das Beste. Manchmal benutze ich queue:false, aber nicht viel, und .stop() benutze ich fast nie.
Wieder exzellentes jQuery, Chris. Danke. (
Wow, schöne Lösung, danke Chris.
Sehr schön! Das könnte ich sofort an zwei Stellen auf meiner Website gebrauchen. =)
Ich weiß, dass der Vorschlag eines Plugins für Leute, die sich für programmatische Lösungen für ihre Probleme interessieren, nicht wirklich hilfreich ist (es sei denn, sie sind daran interessiert, den Quellcode des Plugins zu durchsuchen), aber ich hatte gute Erfolge mit hoverintent.
Das Standardverhalten ist nicht immer ideal für alles (hängt auch davon ab, wie unrealistisch Sie Ihre Tests machen wollen), aber ich habe festgestellt, dass es mit ein wenig Feintuning gut funktioniert, um Ihre... äh... Absicht... zu erkennen, zu hovern!
*Entschuldigung für OT*
Chris, welches Related Post Plugin verwendest du gerade auf diesem Blog?
Mein hoverFlow-Plugin ist eine weitere Lösung für Animations-Warteschlangen-Aufbau. Es unterstützt auch ein einzelnes Mouseover/-Out mit einem vollständigen Animationszyklus.
http://www.2meter3.de/code/hoverFlow/
Es ist schön zu sehen, dass Sie auch den langen Weg gegangen sind (… die Demo-Seite), um eine gute Lösung zu finden.
hoverFlow löst auch das Menüproblem, das in den Kommentaren erwähnt wird („schnelles Mouseout und zurückkehren“). Sehen Sie sich die Untermenü-Beispiele an.
Ich habe festgestellt, dass sowohl der :animated Pseudo-Selektor als auch die Lösungen zur Speicherung des Zustands in einer Klasse zu langsam sind (besonders in älteren IE-Versionen). Mein Ansatz ist es, den Zustand mit der data()-Funktion von jQuery zu speichern.
Die eigentliche Animation wird innerhalb einer anonymen Funktion ausgelöst, die in die Warteschlange gestellt wird (queue()). Auf diese Weise kann ich die Animationswarteschlange basierend auf dem aktuellen Zustand (Mausposition) steuern.
NICE. Das ist wirklich raffiniert, Ralf.
Dieses Plugin ist großartig. Ich versuche gerade, einen Verwendungszweck dafür auf meiner Website zu finden. Sieht wirklich gut aus.
Ich benutze hoverflow schon lange =)… hasse .stop(), es funktioniert für mich überhaupt nicht, sieht einfach hässlich aus^^… hoverflow ist eine echte Schönheit! Aber danke, dass du das Problem angesprochen hast, Chris!
Großartige Arbeit hier! Ich hatte ein ähnliches Problem mit einer Animation in Flash mit Actionscript zu lösen. Ich fand eine Lösung, indem ich die Zeitleiste benutzte, um die Animation rückwärts vom Punkt des Maus-Ausstiegs abzuspielen und beim Hover-Ereignis vorwärts abzuspielen.
Selbst Ihre erste Lösung funktioniert jedoch großartig auf einem Mobilgerät (wo sie mit Flash nicht funktionieren würde, aber trotzdem hoffentlich), weil man mit einem Mobilgerät nicht hovern kann (zumindest nicht auf dem iPhone, ich benutze es, während ich das hier schreibe).
Haben Sie Ideen, wie man ein Menüelement mit einem Dropdown und einem Hover-Zustand für einen Nicht-Mobile-Benutzer programmiert, das auch für einen Mobile-Benutzer funktioniert? Ich hatte dieses Problem auf Websites, die ich besucht habe, und ich musste klicken und dann schnell das Laden der Seite stoppen, um auf die Hover-Menüelemente zuzugreifen...
Sehr gut, Chris, ich habe Ihren Filtercode ein wenig angepasst.
Fügen Sie .stop() vor .filter() hinzu
funktioniert gut!
$(“#animate-test div”).hover(function(){
$(this).stop().filter(‘:not(:animated)’).animate({ width: “200px” });
}, function() {
$(this).animate({ width: “100px” });
});
Das ist sehr gut gemacht! Ich liebe es, dass es auf der Demo-Seite viele Beispiele gibt.
http://www.webappers.com/2009/12/18/a-solution-of-jquery-animation-queue-buildup/
Gott, du hast mir damit so sehr geholfen.
Danke! :)
Gibt es eine ähnliche Lösung für das Click-Ereignis?
Ja, ich habe es bei einem Click-Ereignis ausprobiert, es hat für mich großartig funktioniert, das Ereignis ist nicht so wichtig, sondern die Animate ist das, was das hier behebt.
Chris, du bist verdammt großartig!!!
Es hat mir dabei geholfen! :–>
Hookah falling test...
Chris, wie immer sind deine Anleitungen und Tutorials hervorragend. Ich kann dir nicht genug danken.