Memory-​Effekt in jQuery-​Animationen

Von in javascript, jquery, netzthetik

Das jQuery-Framework bietet Funktionen, mit deren Hilfe und nur wenigen Zeilen Code ansehnliche Animationen erzeugt werden können. Dabei treten mitunter aber auch unerwartete Effekte auf. Einen solchen möchte ich hier beschreiben: Den Memory-Effekt bei der Verwendung der jQuery-Funktion .hover() in Kombination mit einer Animation.

Achtung! Sie haben in Ihren Browsereinstellungen JavaScript deaktiviert. Dieser Blogartikel nutzt JavaScript, um die Thematik besser beschreiben zu können. Bitte aktivieren Sie JavaScript in den Browsereinstellungen, um alle Features, zum Beispiel die unten angeführten Beispiele, dieser Seite nutzen zu können!

Stellen wir uns ein DOM-Objekt vor, das wir, wenn sich der Mauszeiger über dem Objekt befindet, animieren möchten. Dabei soll es sich um ein paar Pixel nach oben bewegen. Entfernt sich die Maus wieder vom Objekt, soll es sich in die Ausgangsposition zurückbewegen. Hier bietet sich die Funktion .hover() an. In diesem Artikel wird später nebenbei gezeigt, wie die Funktion eingesetzt wird. Verwendet man sie in Kombination mit einer Animation, wird man beim Testen auf folgendes Verhalten aufmerksam werden: Wenn man rasch mehrmals die Maus über das Objekt hinweg bewegt, führt das Objekt die Animationen nicht nur dann aus, wenn die Maus die hover-Funktion auslöst, sondern das Objekt scheint sich die durchgeführten Trigger zu "merken" und die Animationen so lange und so oft auszuführen, wie die Maus zuvor das Objekt überfahren hat. Das mag auf den ersten Blick amüsieren, der Benutzer wird davon jedoch irritiert sein. Weil dieser Memory-Effekt etwas schwierig zu beschreiben ist, habe ich ein Video erstellt, das das Verhalten etwas bildlicher beschreibt:

Ich möchte hier auch ein Live-Beispiel zum Ausprobieren anbieten:

 

  • Tab 1
  • Tab 2
  • Tab 3

 

Diesem Beispiel liegt folgender JavaScript-Code zugrunde:

$(document).ready(function(){

    $("ul li").hover(
        function(){
            $(this).animate(
            {
                marginTop: "-20px"
            },
            "fast" );
        },
        function(){
            $(this).animate(
            {
                marginTop: "0px"
            },
            "fast");
        }
    );

});

Das Vorgehen ist einfach: Dem Objekt, hier jedem Listeneintrag, wird ein Event-Handler angehängt (Zeile 3). Fährt man mit der Maus über das Objekt, erfolgt eine Animation des Margins um 20px nach oben (erste Funktion, Zeile 4), verlässt die Maus das Objekt, erfolgt die Animation nach unten (zweite Funktion, Zeile 11). Dabei führt JavaScript die Animation auf Gedeih und Verderb aus, egal, was in der Zwischenzeit passiert. Denn ein weiterer Mouseover bindet erneut das Event auf das Objekt und JavaScript führt es aus, wenn die letzte Animation beendet wurde. Und darin liegt auch schon die Lösung des Problems: Bei erneutem Triggern der Funktion muss zuerst die möglicherweise laufende Animation gestoppt werden. Sehen wir uns zunächst den Code dazu an:

$(document).ready(function(){

    $("ul li").hover(
        function(){
            $(this).is(":animated").stop();
            $(this).animate(
            {
                marginTop: "-20px"
            },
            "fast" );
        },
        function(){
            $(this).is(":animated").stop();
            $(this).animate(
            {
                marginTop: "0px"
            },
            "fast");
        }
    );

});

Jetzt wird in Zeile 5 und Zeile 13 abgefragt, ob das Objekt gerade animiert wird. Wenn dem so ist, wird die Animation sofort gestoppt. Damit bekommt das Objekt ein völlig anderes Verhalten. Probieren Sie es aus:

 

  • Tab 1
  • Tab 2
  • Tab 3

 

Hinweis zur eingesetzten Technik:
Die oben angeführten Beispiele dienen der Demonstration der Thematik. Das hover-Event auf die Listenobjekte zu binden ist nicht sonderlich praxistauglich (vereinfacht aber die Erklärungen für das eigentliche Thema in diesem Artikel), denn wenn sich durch die Animation das Objekt so weit von der ursprünglichen Position wegbewegt, dass es nicht mehr unter dem Mauszeiger liegt, kommt es zu einem weiteren unerwünschten Effekt. Bewegen Sie hierzu einfach bei einem der obigen Beispiele den Mauszeiger von unten langsam an einen der drei Tabs heran, bis er den Tab gerade an der unteren Kante berührt. Der Tab fängt dann an zu "hüpfen". Das liegt daran, dass sich eben das Objekt vom Mauszeiger wegbewegt und von selber durch die Animation das mouseout-Event triggert. Darum wäre es für die Praxis besser, das zu animierende Objekt mit einem Blocklevel-Element zu wrappen, etwa einem DIV, das den Animationsradius des zu animierenden Objekts abdeckt. Das hover-Event bindet man dann auf den DIV. So hängt die Position des Mauszeigers nicht mehr von der Position des zu animierenden Objekts ab. Dieses Beispiel soll vor allem auch zeigen, wie unterschiedlich die JavaScript-Engines der verschiedenen Browser den Code interpretieren, denn dieses "Hüpfen" tritt nicht überall auf.

Share on LinkedInShare on Redditshare on TumblrShare on StumbleUponDigg thisShare on FacebookGoogle+Tweet about this on TwitterEmail to someone