Start · Sprachen · JavaScript · Referenz · Element: lostpointercapture

Element: lostpointercapture

Ereignis

Wird an einem Element ausgelöst, sobald es die Zeigererfassung für einen Zeiger verliert, etwa nach <code>releasePointerCapture()</code>, <code>pointerup</code> oder <code>pointercancel</code>.

seit JavaScript Baseline: alle modernen Browser (Chrome 55+, Firef Kategorie: webapi

Signatur

element.addEventListener("lostpointercapture", handler)

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 pointerup oder pointercancel,
  • 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 document ausgelö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

Typ
undefined
Beschreibung
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})`);
});
Erfassung beendet (Zeiger 1, mouse)

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 });
});
Strich abgeschlossen

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));
pointerdown 1 gotpointercapture 1 pointerup 1 lostpointercapture 1

// Wichtig · Fallstricke

  • Reihenfolge: Bei normalem Ende kommt zuerst pointerup, danach lostpointercapture. Code, der den Endzustand liest, gehört deshalb in lostpointercapture und 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 pointerdown oft automatisch. Deshalb kann lostpointercapture auf Touch-Geräten auch ohne eigenen setPointerCapture()-Aufruf eintreffen.
  • Element entfernt: Wird das erfassende Element aus dem DOM entfernt, geht das Ereignis an das document und nicht an das Element. Wer das abfangen will, braucht dort einen eigenen Listener.
  • Mehrere Zeiger: Bei Multitouch immer event.pointerId prü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.