Wer eine fertige Slideshow sucht, die er an seine Bedürfnisse anpassen will, sollte vielleicht mal bei Kenwheeler oder Fotorama nachschauen.
Ich zeige hier wie man eine sehr einfache Bildergalerie mit Javascript erstellt. Die Beispiele beginnen mit einer sehr einfachen Bildergalerie und werden mit jedem Beispiel etwas komplexer. Da in meist kein Framework genutzt wird, hat man eine geringe Dateigröße und man kann die Beispiele gut nachvollziehen.
Lediglich in den Beispielen ab Gallery7 wird die Animationsbibliothek Tween Lite von Greensock eingesetzt.
In der folgenden Schritt für Schritt Anleitung, werden mittels mehrerer Beispiele Bildergalerien erstellt. Infos siehe unten.
Lightbox | Aufklappbares Buch | Bilder Carousel | 3D Rotate Gallery | Fade Gallery
Alle Bilder liegen in einem Ordner und sind namentlich durchnummeriert.
img/gallery/bild0.jpg
img/gallery/bild1.jpg
etc.
Diese Bilder sollten vorausgeladen sein, damit es keine Verzögerungen beim Laden gibt. Siehe dazu: Preload bei Mozilla
Mittel eines Link Tag kann man Inhalte vorausladen:
<link rel="preload" href="img/gallery/bild0.jpg" as="image">
Diese Zeile kann man mittels einer For-Schleife für alle großen Bilder einfügen. Dazu erzeuge ich im Head Bereich der Seite einen Script Bereich:
<script>
for(var i = 0; i < 12; i++){
document.write(' <link rel="preload" href="img/gallery/bild'+i+'.jpg" as="image">');
}
</script>
Preloader Basic Mediaevent / Preloader Delftstack mehre Bilder / Preload bei Mozilla
let picture = ["blueMedusa.jpg", "blueStar.jpg", "starVodoo.jpg"]; let preloaded = 0; function preLoader(e) { for (var i = 0; i < picture.length; i++) { var tempImage = new Image(); tempImage.addEventListener("load", progress, true); tempImage.src = picture[i]; } } function progress() { preloaded++; if (preloaded == picture.length) { // Aktion wenn alles geladen ist } } this.addEventListener("DOMContentLoaded", preLoader, true);
Ein Bild mit der id slideImg liegt im Body-Bereich.
<img src="img/gallery/bild0.jpg" width="940" height="600" alt="Möbel" id="slideImg"/>
Die Größe des Bildes passt sich an kleinere Bildschirmgrößen an.
img { max-width: 100%; height: auto; }
Direkt vor dem schließenden Body-Tag wird das Javascript eingefügt.
var amount = 12;
// Die Anzahl der Bilder
var nr = 0;
// eine Zählvariable, welche die aktuelle Bildnummer speichert
var bilder = new Array();
// Pfade zu den Bildern
In einer for-Schleife werden die Pfade zu den Bildern dem Array zugewiesen.
for(i=0; i < amount; i++){ bilder[i] = "img/gallery/bild"+i+".jpg"; }
Das Bild im Body bekommt einen EventListener und ruft die Funktion nexPic auf.
document.getElementById("slideImg").onclick = nextPic;
In einer if Struktur wird die Variable nr um 1 erhöht oder auf 0 gesetzt, wenn der höchste Index des Arrays "bilder" erreicht ist.
Mit dieser Variable nr kann man jeweils das nächste Arrayelement ansprechen. bilder[nr].
Mittels DOM wird die Referenz auf das Bild geändert.
document.getElementById('slideImg').setAttribute('src', bilder[nr]);
Beispiel Gallery 1
In diesem Beispiel Gallery 2 kommen 2 Navigationsbuttons hinzu (prev.png und next.png).
Die Buttons werden links und rechts über dem Bild positioniert. Das geschieht mit position:absolute;
Das Bild und die Buttons liegen in einem div mit der id="imgContainer"
Dieser bekommt position:relative
, denn sonst könnte Position absolute nicht greifen.
Die vertikale Positionierung geschieht mittles flexbox, denn ein absoluter vertikaler Wert würde nicht funktionieren, wenn das Bild bei kleinerer Bildschrimgröße verkleinert dargestellt wird.
div#imgContainer{ position:relative; display: flex; justify-content: center; align-items: center; }
Bei einer Querformat Bildschirmanzeige, beispielsweise auf dem Smartphone, wird die Bildhöhe als maximaler Größenwert genommen. Das geschieht mittels CSS und Media Querie
@media only screen and (orientation: landscape) { img#slideImg { max-width: 144vh; max-height: 90vh; } }
144vh errechnet man aus dem Seitenverhältnis der Bilder.
Die Bilder haben alle das gleiche Seitenverhältnis 940 x 600 Pixel oder 94/60 = 1,5666
Die Breite ist somit 1,5666 mal größer als die Höhe.
Die maximale Höhe wurde auf 90vh gesetzt. 90% der Viewport Höhe
Die Breite wird errechnet mit 90vh * 1,5666 = 141vh und ein paar Zerquetschte.
Bei einer anderen Bildgröße muss selbstverständlich dieses CSS angepasst werden.
Im Javascript bekommt jeder Button einen EventHandler mit Funktionsaufruf. Es gibt 2 Funktionen nextPic und prevPic. Dort wird die Variable nr rauf- bzw. runtergezählt.
In Beispiel Gallery 3 wird ein Ein und Ausblenden mittels CSS transition
und der CSS Eigenschaft opacity
erzeugt.
transition: opacity 0.4s;
Die Schwierigkeit ist hier, dass das Neuladen des anderen Bildes erst dann geschehen darf, wenn das Bild ausgeblendet ist und danach soll sich das neu geladene Bild einblenden. Das Aus und Einblenden dauert immer 400 Millsekunden, wegen des eingebenen CSS Wertes 0.4s
Die Funktion showNext und showPrev blendet das Bild aus und ruft mit einer Zeitverzögerung von 4 Millisekunden die Funktion nextPic, bzw prevPic auf.
setTimeout('nextPic()',400);
In diesen Funktionen wird das Bild gewechselt und eingeblendet.
Das Einblenden dauert wieder 4 Millisekunden. Selbstverständlich kann manhier auch andere CSS Eigenschaften einsetzen, wie im nächsten Beispiel.
Alternativ könnte man CSS Animations oder Transitions mittels Javascript Events animationend oder transitionend steuern.
Siehe MDN Webdocs Animation
Siehe dazu auch CSS Tricks,
Dieses Beispiel Gallery 4 funtkioniert auf gleiche Art wie das vorige Beispiel nur die CSS Eigenschaft opacity wurde durch CSS transform rotateY
ersetzt.
Dieses Beispiel Gallery 5 ist responsive, es werden je nach Bildschirmbreite kleinere oder größere Bilder geladen.
Siehe dazu w3schools Media Queries Javascript oder sitepoint match media
Es gibt hier einen Ordner mit großen Bildern von 1200 Pixeln Breite und einen Ordner mit kleinen Bildern von 600 Pixeln Breite.
In den vorigen Versionen wurden die ULRs zu den Bilder mittels for-Schleife dem Array bilder zugewiesen.
In diesem Beispiel gibt es eine if- Struktur, welche auf maximal 700 Pixel Bildschirmbreite abfragt. Je nachdem wird dann auf eine von beiden Forschleifen verwiesen. Eine for-Schleife verweist auf die kleinen Bilder, die andere auf die großen Bilder. Die Bilder werden dem Array bilder zugewiesen.
Siehe dazu auch meinen Tipp CSS3 Transform.
Der perspektivische Effekt entsteht, wenn man dem Elternelement die CSS Eigenschaft perspective zuweist.
perspective: 800px;
Im Javascript bekommt das Bild ein rotateX und ein scale zugewiesen.
bigPic.style.transform = 'rotateX(90deg) scale(0.1,0.1)';
In meinem CSS Tipp Transform befinden sich weitere Beispiele mit Galerien und 3D Drehung, die auch mit Javascript gesteuert werden.
In Gallery6 wird ein Touch oder Swipe Event hinzugefügt. Der Einfachheit halber wurde hier die Javascript Bibliothek hammer.js eingebunden. Diese sollte man sich herunterladen und im Head Bereich einbinden.
<script type="text/javascript" src="js/hammer.min.js">
Im Script wird ein neues Hammer Objekt erzeugt mit Verweis auf ein Element. In diesem Fall das img Element mit der Klasse slideImg.
var mc = new Hammer(slideImg);
Es werden die beiden Events swiperight
und swipeleft
hinzugefügt und die zuvor erstellten Funktionen aufgerufen. In diesem Beispiel habe ich die CSS Animation etwas geändert.
var mc = new Hammer(slideImg); mc.on("swiperight", showNext); mc.on("swipeleft", showPrev);
Da hamner.js auch ein Ziehen mit der Maus nach links oder rechts unterstützt, habe ich die beiden Pfeil-Buttons an den linken und rechten Rand des Browserfensters gesetzt. Dazu habe ich im umgebenden div#imgContainer die Eigenschaft position:relative entfernt. Siehe CSS Position absolute.
Diese Gallery 7 hat einen schönen Übergangseffekt. Der Übergangseffekt ist ein Quantensprung zu den vorigen Varianten und macht dadurch die Sache etwas schwieriger. In den vorigen Versionen, wurde ein Bild ausgeblendet, gedreht etc. und wieder mit anderer Bildquelle angezeigt. Hier sind jeddoch 2 Bilder auf einmal zu sehen. Das Bild welches herausgeschoben wird und das welches hereingeschoben wird. Selbstverständlich ist es nicht so programmiert, dass alle Bilder auf der Bühne liegen und diese jeweils etwas verschoben werden. Es entsteht nur der Eindruck.
2 Bilder werden nach rechts verschoben in einer Animation. Nach der Animation werden sie wieder schlagartig in die ursprüngliche Position versetzt und der Bildaustausch findet statt, indem die src Eigenschaft geändert wird. bild1.src = "img/0.jpg";
Klicke in den Grafiken auf die Pfeilbuttons unten rechts.
Hier wird vor der Animation die Position der beiden Bilder geändert und die Quelle beider Bilder geändert. Dann erfolgt die Verschiebung nach Links in einer Animation.
Die Animation wurde mit Tween Lite gemacht von Greensock. Hier ein paar TweenLite Tipps von mir.
Zuerst muss die Bibliothek eingebunden werden:
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.4/gsap.min.js">
Das Tweenen mit Greensock Tween Lite ist denkbar einfach.
Die Parameter sind.
TweenLite (Element, Zeit in Sekunden{eigenschaft: Wert, eigenschaft: Wert, onComplete:Funktion, overwrite:true})
Mit onComplete kann man eine Funktion anhängen, die nach der Animation aufgerufen wird. Genau das was wir brauchen.
Mittels overwrite: true
, gibt es keine Konflikte, wenn jemand wie ein Bekloppter erneut klickt, bevor eine Animation abgelaufen ist. Siehe dazu die Greensock Docu Conflict
myTween = new TweenLite(bildbox, 0.5, {right:-900, onComplete:setRightBack, overwrite:true});
bildbox ist ein Element in welchem 2 Bilder nebeneinander liegen. Siehe CSS (white-space:nowrap) bildbox ist 1800px breit. Ein Bild ist 900px breit. bildbox liegt in einem Div-Element mit der id container. Dieser ist 900px breit liegt mittig und hat overflow: hidden.
<div id="container"> <div id="bildbox"> <img src="img/1.jpg" alt="Industrie" id="bild1"> <img src="img/0.jpg" alt="Industrie" id="bild2"> </div> <img src="img/prev.png" alt="previous" id="prevBtn"/> <img src="img/next.png" alt="next" id="nextBtn"/> </div>CSS
#container { position: relative; margin: 20px auto; padding: 0px; width: 900px; height: 675px; overflow:hidden; } #bildbox{ position: absolute; width: 1805px; right: 0px; white-space: nowrap; } #nextBtn, #prevBtn { position: absolute; z-index: 10; cursor: pointer; top: calc(50% - 100px); }
Die beiden Buttons werden in den container nach der bildbox eingefügt und auch per position: absolute
positioniert. Sie haben eine Höhe von 200Pixel, Das mittige Ausrichten geschieht in CSS. Damit der Mittelpunkt der Bilder auf 50% der Höhe liegt, muss die halbe Pixelhöhe der Pfeilbilder abgezogen werden. calc(50% - 100px);
Das liegt daran weil top:50%
bedeutet, dass die Oberkante des Elements/ Pfeilbildes auf der verikalen Mittlelinie des umgebenden Elements #bildbox liegt, also genau eine halbe Bildhöhe zu tief.
bildbox wird in 0.5 Sekunden um 900 Pixel nach rechts verschoben. Dadurch schiebt sich das rechte Bild nach rechts heraus und das linke Bild herein. Nach dem Tweening (onComplete
) wird die Funktion setRightBack aufgerufen. In der Funktion werden die Bildquellen ausgetauscht und die bildbox ohne Animation wieder nach links geschoben. siehe Quellcode
Die Animation zurück funktioniert nach dem gleichen Prinzip, nur dass hier am Anfang des Tweenings die Bildquellen ausgetauscht werden.
Das Austauschen der Bildquellen ist am Anfang und Ende sehr tricky. Die id wird rauf oder runtergezählt, aber sie muss am Anfang und Ende für 2 Bilder richtig funktionieren. Daher die vielen if-Strukturen in den Funktionen moveLeft() und moveRight(); Auch die Startwerte müssen stimmen.
JavascriptnextBtn.addEventListener("click", moveRight); prevBtn.addEventListener("click", moveLeft); let id = 0; //---------------------------moveRight-------------------------- function moveRight(){ myTween = new TweenLite(bildbox, 0.5, {right:-900, overwrite: true, onComplete:setRightBack}); } //------------------------------------------------------------- function setRightBack(){ if(id < 11){ id++; }else{ id = 0; } picSrc(bild1, id+1); picSrc(bild2, id); if(id == 11)picSrc(bild1, 0); bildbox.style.right = "0"; } //------------------------------------------------------ function moveLeft(){ if(id == 0){ picSrc(bild2, 11); }else{ picSrc(bild2, (id-1) ); } picSrc(bild1, id); bildbox.style.right = -900+"px"; myTween = new TweenLite(bildbox, 0.5, {right:0, overwrite: true}); if(id > 0){ id--; }else{ id = 11; } } //------------------------------------------------------------- function picSrc(bild, nr){ bild.src = "img/"+nr+".jpg"; }
In der Funktion picSrc() wird das Bild und eine Nummer erwartet, die im Bildnamen erscheint. Dadurch erspart man sich das ständige Zusammensetzen des Bildpfades. Der Code wird etwas übersichtlicher.
function picSrc(bild, nr){ bild.src = "img/"+nr+".jpg"; }
In Gallery 8 wird Gallery 7 responsive gemacht. Der feststehende Wert 900 Pixel, verhindert dass es responsive ist. Dieser Wert definiert die maximale container Breite und die ursprüngliche Bildbreite, die bildbox im container ist doppelt so breit und der Wert der Verschiebung entspricht 900 oder -900. Der Wert sollte kleiner werden wenn der container nicht mehr in die Fensterbreite passt. Das kann man mit window.onresize
abfragen.
Für diesen Wert wird die Variable maxWidth deklariert. In checkWindowSize wird die Breite von container ermittelt und maxWidth auf diesen Wert gesetzt. Außerdem werden alle Maße angepasst. container Höhe, bildbox Breite, Bilder Breite.
Als Wert für das Tweening in den Funktion moveLeft() und moveRight() wird maxWidth oder ein Minus Wert von maxWidth eingesetzt.
Die beiden Buttons werden beim Berühren (mouseover
) von container eingeblendet und wenn man mit der Maus container verlässt (mouseout
), werden sie ausgeblendt. Die Buttons haben mit CSS transition: opacity 2s
zugewiesen bekommen. Durch CSS transition wird eine Veränderung der opacity
Eigenschaft immer animiert und dauert 2 Sekunden.
container bekommt 2 EventListener zugewiesen einmal mit Event type mouseover
und einmal mit Event type mouseout
. In den Funktionen hideBtn() und showBtn() wird die opacity
Eigenschaft der beiden Buttons gesetzt.