Signatur
Beschreibung
Die schreibgeschützte Eigenschaft animated des Interfaces ImageTrack aus der WebCodecs API zeigt an, ob ein Track eines Bildes animiert ist. Das ist etwa bei animierten GIFs, animierten WebP- oder APNG-Dateien der Fall. Bei statischen Bildern wie JPEG oder einem nicht animierten PNG ist der Wert false.
Nützlich ist die Eigenschaft, wenn du entscheiden musst, ob du nur ein einzelnes Bild dekodierst oder eine Schleife über alle Frames mit ImageDecoder.decode({ frameIndex }) brauchst. Zusammen mit ImageTrack.frameCount und ImageTrack.repetitionCount kannst du eine eigene Wiedergabe für Animationen bauen, zum Beispiel auf einem <canvas>.
Der Wert steht bereit, sobald ImageDecoder.tracks.ready erfüllt ist. Die Eigenschaft sagt nur, ob das Format bzw. der Track als animiert markiert ist. Wie viele Frames es genau gibt, steht in frameCount. Bei gestreamten Daten kann dieser Wert noch wachsen, bis ImageDecoder.completed erfüllt ist.
Beispiele
Prüfen, ob ein Bild animiert ist
const response = await fetch('/bilder/lade-spinner.gif');
const decoder = new ImageDecoder({
data: response.body,
type: 'image/gif'
});
await decoder.tracks.ready;
const track = decoder.tracks.selectedTrack;
console.log('Animiert:', track.animated);
console.log('Frames:', track.frameCount);
Statisches Bild und Animation unterschiedlich behandeln
const renderImage = async (url, type, canvas) => {
const ctx = canvas.getContext('2d');
const res = await fetch(url);
const decoder = new ImageDecoder({ data: res.body, type });
await decoder.tracks.ready;
const track = decoder.tracks.selectedTrack;
if (!track.animated) {
// Nur den ersten Frame dekodieren
const { image } = await decoder.decode();
ctx.drawImage(image, 0, 0);
image.close();
return;
}
// Animation: alle Frames nacheinander abspielen
await decoder.completed;
for (let i = 0; i < track.frameCount; i++) {
const { image } = await decoder.decode({ frameIndex: i });
ctx.drawImage(image, 0, 0);
const dauerMs = (image.duration ?? 100000) / 1000; // Mikrosekunden → ms
image.close();
await new Promise((r) => setTimeout(r, dauerMs));
}
};
await renderImage('/bilder/banner.webp', 'image/webp', document.querySelector('canvas'));
Alle Tracks auflisten
const res = await fetch('/bilder/animation.png');
const decoder = new ImageDecoder({ data: res.body, type: 'image/png' });
await decoder.tracks.ready;
for (let i = 0; i < decoder.tracks.length; i++) {
const t = decoder.tracks[i];
console.log(`Track ${i}: animiert=${t.animated}, Frames=${t.frameCount}, Wiederholungen=${t.repetitionCount}`);
}
// Wichtig · Fallstricke
- Browserunterstützung:
ImageDecodergibt es in Chromium-Browsern (ab Version 94) und in neueren Firefox-Versionen. In Safari fehlt es bisher weitgehend. Prüfe deshalb vorher mit'ImageDecoder' in window, ob die API vorhanden ist. Außerdem ist sie nur in sicheren Kontexten (HTTPS) verfügbar. - Lies die Eigenschaft erst, nachdem
decoder.tracks.readyerfüllt ist. Vorher gibt es womöglich noch gar keinen Track. animated === trueheißt nicht zwingend, dass es mehr als einen Frame gibt. Eine APNG-Datei kann zum Beispiel als animiert markiert sein und trotzdem nur einen Frame enthalten. Prüfe also zusätzlichframeCount.- Bei gestreamten Daten ist
frameCountvordecoder.completedwomöglich noch unvollständig. - Gib dekodierte
VideoFrame-Objekte mitclose()frei, sonst wird Speicher verschwendet. - Prüfe mit
ImageDecoder.isTypeSupported(type), ob der MIME-Typ unterstützt wird.