JavaScript/Tutorials/Bildwechsler/Animieren in JavaScript

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Die Grundlage einer jeden Animation in JavaScript ist das zeitgesteuerte Verändern von CSS-Eigenschaften bestimmter HTML-Elemente. Im Wesentlichen verwendet man dazu heute das Animation-Objekt, um die CSS-Eigenschaften eines HTML-Elements direkt ändern zu können, während früher die Werte in eigens geschriebenen Animationsfunktionen schrittweise bei jedem Aufruf mit setTimeout oder requestAnimationFrame immer wieder verändert werden mussten.

Empfehlung: Folgende Artikel können zum Verständnis wichtig sein:


Inhaltsverzeichnis

[Bearbeiten] Ladebalken

Ein Beispiel für eine sehr einfache Animation ist ein Ladebalken, denn hier wird die Breite eines Elements vergrößert. Das lässt sich relativ leicht bewerkstelligen.

Beispiel ansehen …
  function animiere() { 
    var ladebalken = document.getElementById('ladebalken');
    ladebalken.animate([{
      width: '1em',
      background: 'green'
      }, {
      width: '20em',
      background: 'lime'
      }
      ], {
      duration: 2000,
      iterations: 1,
      fill: 'forwards'
    });
  }
In diesem Beispiel wird in einem script-Bereich eine Funktion (animiere) definiert. Diese Funktion legt sich eine Referenz auf das betreffende HTML-Element mit der id ladebalken in einer Variablen ab, um bequem darauf zurückgreifen zu können.

Beim Auslösen der Funktion werden die Breite und Farbe des span-Elements, das diese id enthält, animiert.

Neben den keyframes der Animation werden mit duration: 2000 eine Dauer von 2 Sekunden (in Millisekunden) und mit iterations: 1 eine einmalige Durchführung festgelegt. fill: 'forwards' legt fest, dass das animierte Objekt im Endzustand der Animation bleibt und nicht zum Ausgangspunkt mit 1em Breite zurückspringt.
Beachten Sie: Sowohl die Keyframes als auch die Timing Options werden in Literal-Schreibweise notiert. Die einzelnen Werte werden durch Kommata getrennt; am Ende einer Aufzählung darf aber kein Komma mehr stehen.
Dieser Umstand sorgt immer wieder für Fehlerquellen und sollte deshalb von jedem Script-Autor jedes Mal peinlich genau überprüft werden.
Beachten Sie, dass der Wert forwards genauso wie die Werte für die CSS-Eigenschaften aus Zeichenketten bestehen und deshalb in Anführungszeichen gesetzt werden müssen. Ohne Anführungszeichen wird eine Variablendeklaration gesucht.


Um dieses und die folgenden Beispiele auch in älteren Browsern ausprobieren zu können, wurde ein Polyfill eingebunden:

Beispiel: Polyfill für WAAPI
<script src="https://cdn.jsdelivr.net/web-animations/latest/web-animations.min.js"></script>

[Bearbeiten] Bilderkarussell

Das CSS-Bilderkarussell litt unter zwei Mankos, zum einen mussten bei einer Änderung der Bildanzahl die keyframes angepasst und mühsam von Hand neu berechnet werden, zum anderen war es nur bedingt responsiv, da der gallery, bzw. dessem Elternelement die feste Höhe fehlte.

Beispiel ansehen …
  // Auswahl des Bildwechslers und seiner Kindelemente
  var changer = document.querySelector( '#gallery' ),
      children = changer.querySelectorAll( 'figure'),
      container = document.querySelector( '#container'),
      newWidth = (children.length* 100) + '%';
 
  // sets container, puts figure-elements horizontal 
     container.classList.add('container');
     changer.classList.add('changer');
     changer.style.width = newWidth;	
     var newMargin = ((children.length-1)* -100) + '%';
 
  // animate changer
       var marquee = changer.animate([{
	 marginLeft: '0%'
       }, {
         marginLeft: newMargin
       }
       ], {
         duration: children.length * 3000,
	 directions: 'alternate',
         iterations: Infinity
     });
}
Ohne JavaScript werden die Bilder untereinander angezeigt.
Beim Laden des JavaScripts erhält die gallery eine neue Klasse changer. In ihr werden die Bilder waagerecht angeordnet; durch die ebenfalls neu hinzugefügte Klasse container des Elternelements ist aber immer nur ein Bild sichtbar.
Neben der Klasse erhält die gallery auch noch mit style.width eine Breite, die sich aus der mittels querySelectorAll ermittelten Anzahl der vorhandenen figure-Elemente ergibt.
Der changer wird nun animiert. Durch eine Verschiebung des linken Randes laufen die Bilder in einer Dia-Show nacheinander ab. Dabei wird der Maximalwert wieder aus der Anzahl der vorhandenen Bilder dynamisch ermittelt. Auch die Dauer der Animation wird in duration: children.length * 3000, von der Anzahl der in der Animation vorhandenen Bilder bestimmt.
Am Ende der Animation wird mit direction die Richtung der Animation geändert; die timing option iterations legt die Anzahl der Wiederholungen fest, beim Schlüsselwort Infinity also unendlich.

Mit nur wenigen Zeilen JavaScript können beliebige Bildergalerien zu einem Karussell animiert werden. Allerdings laufen die Bilder hier nur durch und werden nicht einzeln für sich angezeigt. In nächsten Beispiel stellen wir Ihnen einen Bildwechsler vor, in dem die Bilder nacheinander ein- und wieder ausgeblendet werden. Im folgenden Artikel wird dieser Bildwechsler dann mit umfangreichen Steuerung ausgestattet.

[Bearbeiten] Überblendung

Beim Überblenden passiert im Grunde nichts anderes, als dass man bei zwei übereinander liegenden Bildern zuerst das untere mit voller Deckkraft darstellt, und das zweite völlig transparent deckungsgleich darüber. In der Animation erhöhen Sie nun die Deckkraft des zweiten Bildes, dass es das darunterliegende Bild immer mehr und schließlich ganz überdeckt.

Dazu bedient man sich der CSS-Eigenschaft opacity, die die Deckkraft (Opazität) eines Elements steuert. Je höher der Wert, desto weniger durchsichtig ist ein Element. Dabei darf der Wert für opacity Dezimalwerte zwischen 0.0 und 1.0 annehmen, stellt also den Prozentwert dar (20% Transparenz entsprächen dann 80% Deckkraft, also opacity:0.8).

[Bearbeiten] HTML und CSS

Die HTML-Struktur unseres Bildwechslers haben wir aus dem CSS-Tutorial übernommen. Das Bild wird zusammen mit einer figcaption-Bildunterschrift innerhalb eines figure-Elements platziert.

Beispiel ansehen …
  <div id="gallery">
    <figure>
      <img src="Berge1.jpg" alt="">
      <figcaption>Bild 1 </figcaption>
    </figure>
    <figure>  
      <img src="Berge2.jpg" alt="">
      <figcaption>Bild 2 </figcaption>
    </figure></div>
#gallery {
  position: relative;
}
 
#gallery figure {
  position: absolute; 
  left: 0; 
  top: 0; 
}
Damit das zweite Bild genau über dem ersten zu liegen kommt, muss es absolut positioniert werden. Damit sein Bezugspunkt aber nicht die linke obere Ecke des Browserfensters, sondern das vorherige Bild wird, wurde das direkte Elternelement der figure-Elemente (hier das div mit der id gallery) relativ positioniert. Dadurch ändert sich die "Nullmarke" für absolut positionierte Kindelemente (in diesem Fall die figure-Elemente). Nun können die Bilder mittels top:0 und left:0 passgenau übereinander gelegt werden, was für das Überblenden unverzichtbar ist.

[Bearbeiten] JavaScript

Beispiel ansehen …
(function () {
    function init() {   
    var imageChanger = document.getElementById('gallery').lastChild;
        imageChanger.animate([{
            opacity: '0'
        }, {
            opacity: '1'
        }
        ], {
            duration: 2000,
	    direction: 'alternate',
            iterations: Infinity
        });
    };
 
	document.addEventListener(
		"DOMContentLoaded",
		function () { init(); }
	);
}());
Mit document.getElementById('gallery').lastChild wird der letzte Kindknoten des div mit der id gallery selektiert und mit Element.animate() animiert.
Die Animation ändert die Deckkraft des zweiten figure-Elements von 0 auf 1, sodass es innerhalb von 2 Sekunden von durchscheinend auf volle Deckkraft wechselt. Durch die Angabe 'alternate' bei direction wird nach jedem Durchlauf die Richtung geändert. Über das Schlüsselwort Infinity der iterations-Eigenschaft wird festgelegt, dass die Animation unendlich oft wiederholt wird.
Beachten Sie, dass das schließende Tag des divs gleich hinter dem </figure>-Tag folgt. Wenn Sie hier die übliche Formatierung verwenden würden, wäre das letzte Kind des div ein (leerer) Textknoten mit dem Zeilenumbruch, sodass die Animation nicht ausgeführt werden würde.

[Bearbeiten] Laden des JavaScripts

Vielleicht ist ihnen schon aufgefallen, dass das JavaScript speziell strukturiert ist. Die function init() ist in einer anonymen Funktion "verpackt", die so notiert wird, dass sie sofort ausgeführt wird. Eine solche Verpackungsfunktion nennt man im Englischen "immediately invoked function expression" (IIFE), zu deutsch "sofort ausgeführter Funktionsausdruck".

Beispiel ansehen …
(function () {
    function init() {   
      ...
    };
 
    document.addEventListener(
	"DOMContentLoaded",
	function () { init(); }
    );
}());
Sowohl die function init() als auch das Anbinden des addEventListener an das Dokument sind in einer anonymen Funktion verpackt. Dies hat den Vorteil, dass Variablen nie einen globalen Scope erhalten können und mit gleichnamigen Variablen in anderen Skripten kollidieren können.
In addEventListener wird beim Ereignis DOMContentLoaded, wenn das DOM aber noch nicht alle externen Ressourcen wie Bilder geladen sind, die Funktion init() aufgerufen.

[Bearbeiten] Fader mit mehreren Bildern

Nachdem nun der Mechanismus des Überblendens geklärt ist, kann das Konzept ausgeweitet werden, um mehrere Bilder in einer Slideshow anzuzeigen. Dazu werden im Dokument einfach mehrere Bilder definiert, durch die sich das Script hindurcharbeiten muss. Bei der aufgerufenen Animation ändern sich nur Verzögerung vor dem Start und dann die Wartezeit nach der Animation, damit die Bilder passend ein- und wieder ausgeblendet werden.

Beispiel ansehen …
    function init() {   
 
  // Auswahl des Bildwechslers und seiner Kindelemente
  var changer = document.querySelector( '#gallery' ),
      children = changer.querySelectorAll( 'figure'),	
      aniÜbergang = 1000,
      aniDur = 1000,	  
      dauer = (aniÜbergang + aniDur),
      aniStartDelay = aniÜbergang,
      aniEndDelay = (children.length -1)* (dauer);
 
  // figure-Elemente werden in absteigender Schleife durchlaufen
  for (var i = children.length - 1; i >= 0; i--) {
      children[i].animate([{
            opacity: '1'
        }, {
            opacity: '0'
        }
        ], {
            duration: aniDur,
	    delay: aniStartDelay,
    	    endDelay: aniEndDelay,
	    fill: 'forwards',	
            iterations: 1
        });
    var gesamt = aniDur + aniStartDelay + aniEndDelay;
    alert (gesamt);
    aniStartDelay = aniStartDelay + dauer;
    aniEndDelay = aniEndDelay - dauer;
    };
Die Bildergalerie mit der id gallery wird mit querySelector selektiert. Anschließend werden mit querySelectorAll alle figure-Elemente ausgesucht.

Da diese absolut positioniert sind, liegt das im Markup letzte figure-Element oben. In einer Schleife werden diese dann absteigend so animiert, dass sie nach einer Verzögerung innerhalb von 1s (1000 Millisekunden) ausgeblendet werden, sodass das darunterliegende Bild sichtbar wird.

Die Verzögerung (delay) und das Warten nach der erfolgten Animation (endDelay) sind so getaktet, dass die Bilder nacheinander zu sehen sind und alle Animationen gleichzeitig beendet sind, damit es bei einer Wiederholung nicht zu Rucklern kommt.
Beachten Sie: Wenn Sie die Animation mehrfach wiederholen, indem Sie den Wert von iterations vergrößern oder das Schlüsselwort Infinity einsetzen, gerät die Taktung außer Kontrolle und die Bilder werden nur noch unregelmäßig angezeigt.

Der Grund dafür ist, dass die Angaben von delay und endDelay nur zu Beginn und am Ende der Animation wirken, nicht jedoch zwischen den Wiederholungen.

Deshalb werden wir im folgenden Beispiel einen anderen Ansatz verfolgen.

[Bearbeiten] Weblinks

Meine Werkzeuge
Namensräume

Varianten
Aktionen
Übersicht
Index
Mitmachen
Werkzeuge
Spenden
SELFHTML