Signatur
Beschreibung
Das Event canplaythrough wird an einem <audio>- oder <video>-Element ausgelöst, wenn der Browser das Medium abspielen kann und schätzt, dass bei der aktuellen Download-Geschwindigkeit genug Daten vorliegen, um es bis zum Ende ohne Unterbrechung zum Puffern abzuspielen. Zu diesem Zeitpunkt erreicht readyState den Wert HAVE_ENOUGH_DATA (4).
Das Event ist nicht abbrechbar und steigt nicht auf (kein Bubbling). Sie registrieren es entweder mit addEventListener("canplaythrough", handler) oder über die Eigenschaft oncanplaythrough. Der Handler erhält ein einfaches Event-Objekt.
Typische Anwendungen: einen Ladeindikator ausblenden, einen „Abspielen“-Button aktivieren, ein Hintergrundvideo erst dann einblenden, wenn es flüssig läuft, oder Soundeffekte in Spielen vorladen. Die Reihenfolge der Lade-Events ist in der Regel loadstart → durationchange → loadedmetadata → loadeddata → canplay → canplaythrough.
Beachten Sie, dass es sich nur um eine Schätzung handelt: Sinkt die Bandbreite, kann das Medium trotzdem stocken (waiting-Event). Außerdem kann canplaythrough mehrfach feuern, etwa nach einem Sprung mit currentTime oder nach erneutem Puffern.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Eventname "canplaythrough". |
|
| $handler Pflicht | (event: Event) => void | Callback, der beim Auslösen aufgerufen wird. Erhält ein generisches Event-Objekt. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie { once: true }, um den Listener nach dem ersten Auslösen automatisch zu entfernen. |
Rückgabewert
addEventListener gibt nichts zurück; der Handler erhält ein Event-Objekt ohne zusätzliche Eigenschaften.Beispiele
Ladeindikator ausblenden, sobald das Video flüssig läuft
const video = document.querySelector('#intro');
const spinner = document.querySelector('#spinner');
video.addEventListener('canplaythrough', () => {
spinner.hidden = true;
console.log('Bereit, readyState =', video.readyState);
}, { once: true });
Über die on-Property und Entfernen des Listeners
const audio = new Audio('/sounds/theme.mp3');
const onReady = () => {
console.log('Musik kann ohne Unterbrechung laufen');
audio.removeEventListener('canplaythrough', onReady);
};
audio.addEventListener('canplaythrough', onReady);
// Alternative per Property (überschreibt frühere Zuweisungen):
// audio.oncanplaythrough = onReady;
// audio.oncanplaythrough = null; // entfernen
Mehrere Soundeffekte vorladen (Promise-basiert)
const preload = (src) => new Promise((resolve, reject) => {
const audio = new Audio();
audio.preload = 'auto';
audio.addEventListener('canplaythrough', () => resolve(audio), { once: true });
audio.addEventListener('error', () => reject(new Error(`Fehler: ${src}`)), { once: true });
audio.src = src;
// Falls schon gepuffert (z. B. aus dem Cache):
if (audio.readyState >= HTMLMediaElement.HAVE_ENOUGH_DATA) resolve(audio);
});
const sounds = await Promise.all(['/sfx/jump.wav', '/sfx/coin.wav'].map(preload));
console.log(`${sounds.length} Sounds geladen`);
// Wichtig · Fallstricke
- Nur eine Schätzung: Trotz
canplaythroughkann die Wiedergabe bei schwankender Bandbreite stocken. Behandeln Sie zusätzlichwaitingundstalled. - Mehrfaches Auslösen: Nach Sprüngen (
seeking) oder erneutem Puffern kann das Event erneut feuern. Nutzen Sie{ once: true }, wenn Sie nur die erste Bereitschaft interessiert. - Listener zu spät registriert: Ist das Medium bereits gepuffert (Cache), ist das Event schon vorbei. Prüfen Sie vorher
readyState >= 4. preload-Attribut: Beipreload="none"oder"metadata"und auf vielen Mobilgeräten (vor allem iOS Safari) wird ohne Benutzerinteraktion nicht genug geladen –canplaythroughfeuert dann erst nachplay()oder gar nicht vorab.- Kein Bubbling: Ein Listener am Elternelement fängt das Event nur in der Capture-Phase ab (
addEventListener(..., true)). - Kompatibilität: von allen modernen Browsern unterstützt.