Javascript Image

Javascript image

Javascript erzeugt ein Image Object mit createElement oder new Image. Das Image-Objekt ist kein Bestandteil der Programmiersprache wie Date(), Array() oder String(), sondern gehört zum Document Object Model.

Das Objekt hat keine Methoden, sondern nur Eigenschaften wie src, width, height, naturalWidth ….

23-02-02 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

new Image

Es macht keinen Unterschied, ob das Bild mit createElement oder mit new Image angelegt wird. Allenfalls könnte man ins Feld räumen, dass createElement konsistenter ist.

Bilder können in Javascript als mit

let myImg = document.createElement('img');

oder mit

let myImg = new Image();

angelegt werden.

Eigenschaften: Image Properties

alt
Setzt das alt-Attribut oder gibt den Wert des alt-Attributs zurück
complete
Gibt zurück, ob der Browser das Bild vollständig geladen hat. complete ist kein Event!, sondern gibt true oder false zurück.
crossOrigin
Setzt die CORS-Einstellung (Cross Origin) oder gibt sie zurück
height
Setzt die Höhe des Bildes oder gibt des Wert des height-Attributs zurück
isMap
Setzt ein Bild als Teil einer serverseitigen Image Map oder gibt zurück, ob das Bild Teil einer server-seitigen Image Map ist
naturalHeight
Gibt die (physikalische) Höhe des Bildes zurück
naturalWidth
Gibt die (physikalische) Breite des Bildes zurück. Das Bild muss vollständig geladen sein, bevor die Größe des Originals mit Javascript naturalHeight und naturalWidth bestimmt werden kann (ab IE9).
src
Setzt das src-Attribut des Bildes oder gibt des Wert des src-Attributs zurück
useMap
Setzt das useMap-Attribut des Bildes oder gibt den Wert des useMap-Attributs zurück
width
Setzt die Breite des Bildes oder gibt des Wert des width-Attributs zurück
align, border, hspace, longDesc, name, vspace
veraltet und nicht mehr in HTML5 vertreten

Javascript fetch HEAD kann schon vor dem Laden des Bildes die Dateigröße auslesen, während die Abmessungen des Bildes erst nach dem Laden abgefragt werden können.

Javascript Abfrage: Bild geladen?

Bilder werden geladen, nachdem ein HTTP-Request für das Bild abgesendet wurde. Das passiert entweder durch ein img-Tag oder durch einen Funktionsaufruf.

Beim window onload Event sind das DOM, CSS-Dateien und Bildern geladen. Das DOMContentLoaded Event hingegen feuert bereits, wenn das HTML DOM vollständig geladen und navigierbar ist – ohne auf das Laden von CSS-Dateien, Bildern und iframes zu warten (ähnlich wie jQuery ready).

Genauso sieht es aus, wenn das Script im Fuß der Seite vor dem schließenden body-Tag sitzt: Dann ist das Dokument geladen, aber das Bild u.U. noch nicht.

snail-900
let image = new Image();
image.onload = function () {
	console.log ("Schnecke Height: " + this.naturalHeight);
	console.log ("Schnecke Width: " + this.naturalWidth);
	// Mach was mit dem Bild
};
image.src = "snail.webp";

console.log("Direkt nach image.src");

Reihenfolge der Ausführung:

Direkt nach image.src
…
Schnecke Height: 531
Schnecke Width: 900

Es ist wichtig, dass zuerst der Handler image.onload oder image.addEventListener("load", function () {}) aufgerufen wird, und erst danach image.src. Wenn das Bild bereits im Cache liegt, würde anderenfalls das Event verpasst.

Der Browser wartet nicht ab, bis das Bild fertig geladen ist, sondern führt Anweisungen, die auf image.onload und image.src folgen, sofort weiter aus. Der Browser triggert das onload-Event und benachrichtig das Script etwas später, dass das Bild geladen ist – erst dann werden die Anweisungen innerhalb von image.onload ausgeführt.

Wenn es wichtig ist, dass Anweisungen in einer bestimmten Reihenfolge ausgeführt werden, kann eine callback-Funktion eingreifen.

Spinner zeigen, bis ein Bild geladen ist

Da bei sehr großen Bildern eine Weile ins Land gehen kann, bis der Browser das Bild vollständig geladen hat, zeigen Galerien und Slideshows einen Spinner.

buffalo-mini

Der HTML-Teil ist ganz einfach

Thumbnail, Overlay und Spinner
<div id="buffalo">
	<img id="thumbnail" src="buffalo-mini.jpg">
	
	<div id="overlay"></div>
	
	<div class="spinner"><svg><use xlink:href="#wheel"/></svg></div>
</div>

Der Spinner ist ein SVG, könnte aber ebensogut ein animiertes GIF oder CSS (z.B. von 50+ CSS Loader Animation Snippet and Examples) sein.

document.getElementById('thumbnail').addEventListener('click', function (e) {
	const overlay = document.getElementById('overlay');
	const spinner = document.querySelector(".spinner");

	highRes = new Image();
	spinner.setAttribute("style","display:block");

	// zuerst den Listener für das Laden des Bildes
	highRes.addEventListener ('load', function () {
		spinner.parentNode.removeChild(spinner);
		overlay.appendChild(highRes);
	});

	// entfernt das hochauflösende Bild bei einem Klick
	highRes.addEventListener ('click',function () {
		highRes.parentNode.removeChild(highRes);
		overlay.parentNode.appendChild(spinner);
		overlay.style.display = 'none';
		spinner.setAttribute("style","display:none");
	});

	overlay.style.display = 'block';

	// src erst nach dem Aufsetzen des Listeners angeben
	highRes.src = "buffalo.jpg";
});

Lazy Loading Images – Nachladen

Bilder stellen die größte Last bei Laden von Webseiten. Sie bringen ein Vielfaches der Speichergröße der eigentlichen Webseite und verzögern das Laden der Seite insgesamt.

Lazy Loading nennt man Techniken, die Bilder erst laden, wenn sie beim Scrollen der Seite in den Viewport kommen. Die klassische Technik berechnete den Abstand des Bilds vom Viewport mithilfe von getBoundingClientRect und Scroll-Events.

Die aktuellen Browser unterstützen das Intersection Observer-Api, das den Anstand eines Elements von einem Root-Element (meist dem Viewport des Browsers) beobachtet.

Und damit Javascript hier gar nicht erst eingreifen muss, gibt es das HTML-Attribut loading für das img-Tag mit den drei Werten auto, eager (eifrig) und lazy (nachzüglich).

<img src="pic.png" loading="auto">   // Normal laden

<img src="pic.png" loading="eager">  // Bilder "above the fold"

<img src="pic.png" loading="lazy">   // Nachladen, wenn das Bild in den Viewport kommt
	

Noch unterstützen nicht alle Browser das Nachladen von Bildern via loading (nicht Safari und nicht IE). Edge, Chrome, Firefox hingegen sind bereits dabei.

Image Preload mit Javascript

Wenn ein Image Objekt erzeugt wurde und dem Objekt eine URL zugewiesen wird, lädt der Browser das Bild in seinen Cache, z.B. um das Bild später bei einem Klick auf einen Button oder nach längerem Scrollen ohne Verzögerung anzuzeigen.

<script>
let myImage = new Image();
myImage.src = 'einbild.jpg';
</script>

An dieser Stelle hat der Browser das Bild in den Cache geladen und das Image-Objekt myImage enthält das Bild einbild.jpg.

Heute kann allerdings ein Link mit rel="preload" im Head der Seite Ressourcen (Bilder, CSS, Scripte) elegant nach dem Laden der Seite im Voraus laden, z.B. um sie erst später auf der Seite zu zeigen oder auszuführen.

<link rel="preload" as="image" href="largemap.png" media="(max-width: 600px)">

Alle modernen Browser, aber nicht IE.

naturalWidth / naturalHeight: Größe eines Bildes

Für Slideshows und die allgegenwärtigen Lightboxen ist es immer wieder erforderlich, die tatsächliche Größe eines Bildes herauszufinden.

Bilder werden als Thumbnail oder Vorschaubild kleiner in Webseiten gesetzt (z.B. damit sie in das Layout der Seite passen). Erst für die Darstellung in der Lightbox wird ihre »natürliche Größe« gebraucht.

image size with Javascript
<img id="theImage" src="image.png" alt="image size" width="400" height="240">

let theImage = document.getElementById("theImage");
let width = theImage.width;
let height = theImage.height;

theImage.width und theImage.height liefern nur die aktuelle Größe.

let natWidth = theImage.naturalWidth;
let natHeight = theImage.naturalHeight;

naturalWidth und naturalHeight liefern die physikalischen Abmessungen – die Größe des Bildes in Pixel – in allen gängigen Browsern.

let theImage = document.getElementById("theImage");
let natWidth;
let natHeight;
if (theImage) {
    if (typeof theImage.naturalWidth == "undefined") {
        let i = new Image();
        i.src = theImage.src;
        natWidth = i.width;
        natHeight = i.height;
	} else {
        natWidth = theImage.naturalWidth;
        natHeight = theImage.naturalHeight;
	}
    theImage.classList.toggle('moveup');
    document.getElementById('imgNaturalSize').innerHTML = "Breite " + natWidth + "px Höhe " + natHeight + 'px';
} else {
    theImage.classList.toggle('moveup');
    document.getElementById('imgNaturalSize').innerHTML = "Bild noch nicht geladen";
}