Signatur
Beschreibung
Das Ereignis lostpointercapture gehört zur Pointer-Events-API und ist das Gegenstück zu gotpointercapture. Es wird an dem Element ausgelöst, das vorher einen Zeiger per setPointerCapture() erfasst hatte, sobald diese Erfassung endet. Der Handler bekommt ein PointerEvent. Dessen Eigenschaft pointerId gibt an, welcher Zeiger freigegeben wurde, und pointerType nennt die Zeigerart ("mouse", "pen" oder "touch"). Das Ereignis steigt im DOM auf (Bubbling), lässt sich aber nicht abbrechen.
Die Erfassung endet in diesen Fällen:
- durch einen ausdrücklichen Aufruf von
element.releasePointerCapture(pointerId), - automatisch nach
pointerupoderpointercancel, - wenn ein anderes Element die Erfassung für denselben Zeiger mit
setPointerCapture()übernimmt, - wenn das erfassende Element aus dem DOM entfernt wird. Dann wird das Ereignis am
documentausgelöst.
Am besten nutzt man lostpointercapture als zentrale Stelle zum Aufräumen bei Drag-, Slider-, Zeichen- oder Resize-Interaktionen. Das Ereignis kommt immer an, egal ob die Interaktion normal mit pointerup endet oder abgebrochen wird, etwa durch eine System-Geste, einen Fensterwechsel oder pointercancel. So setzt man CSS-Klassen, Zustands-Flags und temporäre Listener an einer einzigen Stelle zurück und muss dieselbe Logik nicht in mehreren Handlern wiederholen.
Statt mit addEventListener() kann man den Handler auch über die Eigenschaft element.onlostpointercapture zuweisen. Die Eigenschaft hält aber nur einen einzigen Handler, und jede neue Zuweisung überschreibt den vorherigen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname, hier immer "lostpointercapture". |
|
| $handler Pflicht | (event: PointerEvent) => void | EventListenerObject | Callback, der ein PointerEvent erhält. Wichtige Eigenschaften: pointerId, pointerType, isPrimary, clientX/clientY und target. |
|
| $options | boolean | { capture?: boolean, once?: boolean, passive?: boolean, signal?: AbortSignal } | false | Optionale Listener-Optionen. Mit signal lassen sich mehrere Listener gleichzeitig entfernen, once entfernt den Listener nach dem ersten Aufruf automatisch. |
Rückgabewert
addEventListener() gibt nichts zurück. Der Handler selbst erhält ein PointerEvent. Sein Rückgabewert wird ignoriert, denn das Ereignis lässt sich nicht abbrechen.Beispiele
Drag-Interaktion mit zentralem Aufräumen
const handle = document.querySelector('.drag-handle');
let startX = 0;
let offsetX = 0;
handle.addEventListener('pointerdown', (e) => {
handle.setPointerCapture(e.pointerId);
startX = e.clientX - offsetX;
handle.classList.add('is-dragging');
});
handle.addEventListener('pointermove', (e) => {
// Nur verschieben, solange dieser Zeiger erfasst ist
if (!handle.hasPointerCapture(e.pointerId)) return;
offsetX = e.clientX - startX;
handle.style.transform = `translateX(${offsetX}px)`;
});
// Aufräumen an EINER Stelle – gilt für pointerup UND pointercancel
handle.addEventListener('lostpointercapture', (e) => {
handle.classList.remove('is-dragging');
console.log(`Erfassung beendet (Zeiger ${e.pointerId}, ${e.pointerType})`);
});
Handler per on-Property setzen und wieder entfernen
const slider = document.querySelector('#volume');
const onLost = (e) => {
slider.dataset.active = 'false';
console.log('Slider losgelassen, Wert:', slider.value);
};
// Variante 1: on-Property (nur ein Handler möglich)
slider.onlostpointercapture = onLost;
// ... später entfernen:
slider.onlostpointercapture = null;
// Variante 2: addEventListener / removeEventListener
slider.addEventListener('lostpointercapture', onLost);
slider.removeEventListener('lostpointercapture', onLost);
Zeichenfläche: temporäre Listener mit AbortController abbauen
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.addEventListener('pointerdown', (e) => {
canvas.setPointerCapture(e.pointerId);
const controller = new AbortController();
const { signal } = controller;
ctx.beginPath();
ctx.moveTo(e.offsetX, e.offsetY);
canvas.addEventListener('pointermove', (ev) => {
if (ev.pointerId !== e.pointerId) return;
ctx.lineTo(ev.offsetX, ev.offsetY);
ctx.stroke();
}, { signal });
// Beim Verlust der Erfassung alle temporären Listener entfernen
canvas.addEventListener('lostpointercapture', (ev) => {
if (ev.pointerId !== e.pointerId) return;
controller.abort();
console.log('Strich abgeschlossen');
}, { signal });
});
Reihenfolge der Ereignisse protokollieren
const box = document.querySelector('#box');
['pointerdown', 'gotpointercapture', 'pointerup', 'pointercancel', 'lostpointercapture']
.forEach((type) => box.addEventListener(type, (e) => console.log(type, e.pointerId)));
box.addEventListener('pointerdown', (e) => box.setPointerCapture(e.pointerId));
// Wichtig · Fallstricke
- Reihenfolge: Bei normalem Ende kommt zuerst
pointerup, danachlostpointercapture. Code, der den Endzustand liest, gehört deshalb inlostpointercaptureund nicht umgekehrt. - Asynchrone Freigabe:
releasePointerCapture()löst das Ereignis nicht sofort aus. Es kommt erst, wenn der Browser das nächste Pointer-Ereignis verarbeitet. Unmittelbar nach dem Aufruf darf man also nicht davon ausgehen, dass der Handler schon gelaufen ist. - Implizite Erfassung bei Touch: Browser erfassen Touch-Zeiger bei
pointerdownoft automatisch. Deshalb kannlostpointercaptureauf Touch-Geräten auch ohne eigenensetPointerCapture()-Aufruf eintreffen. - Element entfernt: Wird das erfassende Element aus dem DOM entfernt, geht das Ereignis an das
documentund nicht an das Element. Wer das abfangen will, braucht dort einen eigenen Listener. - Mehrere Zeiger: Bei Multitouch immer
event.pointerIdprüfen, damit nicht eine fremde Interaktion zurückgesetzt wird. - Das Ereignis steigt auf (Bubbling), lässt sich aber nicht abbrechen.
preventDefault()bewirkt nichts. - Kompatibilität: Wird von allen modernen Browsern unterstützt (Chrome/Edge 55+, Firefox 59+, Safari 13+). Der Internet Explorer kannte nur die Variante mit Präfix,
MSLostPointerCapture.