Start · Sprachen · JavaScript · Referenz · Element: pointercancel

Element: pointercancel

Ereignis

Wird ausgelöst, wenn der Browser eine laufende Zeigerinteraktion abbricht, etwa weil er die Geste selbst übernimmt (Scrollen, Zoomen) oder das Gerät keine Ereignisse mehr liefert.

seit JavaScript Baseline: alle modernen Browser (seit 2020) Kategorie: webapi

Signatur

element.addEventListener("pointercancel", handler)

Beschreibung

Das Ereignis pointercancel signalisiert, dass für den aktuellen Zeiger (Finger, Stift, Maus) keine weiteren Zeigerereignisse mehr folgen werden. Typische Auslöser: Der Browser erkennt nach pointerdown eine Scroll- oder Zoom-Geste und übernimmt sie selbst (Pan/Zoom gemäß touch-action). Weitere Auslöser sind eine Änderung der Bildschirmausrichtung, ein zu Ende gegangener Hardware-Kontakt, das Erreichen der maximalen Anzahl gleichzeitiger Berührungen oder ein modaler Dialog des Systems, der die Eingabe unterbricht.

Nach pointercancel sendet der Browser noch pointerout und pointerleave. Ein pointerup kommt nicht. Wer also Drag-and-Drop, Zeichenflächen, Wischgesten oder eigene Schieberegler baut, muss pointercancel genauso behandeln wie pointerup: Zustand zurücksetzen, Pointer-Capture freigeben und visuelle Rückmeldungen (z. B. eine gedrückte Hervorhebung) entfernen.

Das Ereignis ist ein PointerEvent. Es blubbert nach oben, lässt sich aber nicht abbrechen (cancelable: false). Neben addEventListener steht die Eigenschaft onpointercancel zur Verfügung, die es auf Elementen, document und window gibt.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "pointercancel".
$handler Pflicht (event: PointerEvent) => void Callback, der ein PointerEvent erhält. Wichtige Eigenschaften sind pointerId, pointerType ("mouse", "pen" oder "touch"), isPrimary, clientX und clientY.
$options boolean | AddEventListenerOptions false Optionen wie once, capture, passive oder signal. passive ändert hier nichts, weil das Ereignis ohnehin nicht abgebrochen werden kann.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt undefined zurück. Der Rückgabewert des Handlers wird nicht ausgewertet.

Beispiele

Drag-Zustand bei Abbruch zuverlässig zurücksetzen

const box = document.querySelector('#draggable');
let dragging = false;

const endDrag = (event) => {
  if (!dragging) return;
  dragging = false;
  box.classList.remove('is-dragging');
  if (box.hasPointerCapture(event.pointerId)) {
    box.releasePointerCapture(event.pointerId);
  }
  console.log(`Drag beendet durch: ${event.type}`);
};

box.addEventListener('pointerdown', (event) => {
  dragging = true;
  box.classList.add('is-dragging');
  box.setPointerCapture(event.pointerId);
});

box.addEventListener('pointermove', (event) => {
  if (!dragging) return;
  box.style.translate = `${event.clientX}px ${event.clientY}px`;
});

// pointerup UND pointercancel gleich behandeln
box.addEventListener('pointerup', endDrag);
box.addEventListener('pointercancel', endDrag);
Drag beendet durch: pointercancel // z. B. wenn der Browser auf dem Touchscreen scrollt

Ungewollten Abbruch durch touch-action vermeiden

const canvas = document.querySelector('canvas');

// Ohne diese Zeile übernimmt der Browser Wischgesten zum Scrollen
// und löst pointercancel aus, sobald der Finger sich bewegt.
canvas.style.touchAction = 'none';

canvas.addEventListener('pointercancel', (event) => {
  console.warn('Abgebrochen:', event.pointerType, event.pointerId);
});

on-Property verwenden und Listener wieder entfernen

const button = document.querySelector('#hold-button');

// Variante 1: on-Property (nur ein Handler möglich)
button.onpointercancel = (event) => {
  button.classList.remove('pressed');
};

// Variante 2: addEventListener mit removeEventListener
const onCancel = (event) => {
  console.log('Abbruch für Zeiger', event.pointerId);
};
button.addEventListener('pointercancel', onCancel);

// Später, z. B. beim Abbau der Komponente:
button.removeEventListener('pointercancel', onCancel);
button.onpointercancel = null;

Alle Listener per AbortController abräumen

const controller = new AbortController();
const { signal } = controller;
const slider = document.querySelector('.slider');

const reset = () => slider.classList.remove('active');
slider.addEventListener('pointerup', reset, { signal });
slider.addEventListener('pointercancel', reset, { signal });

// Beide Listener auf einmal entfernen
controller.abort();

// Wichtig · Fallstricke

  • Häufigster Fehler: Man lauscht nur auf pointerup. Bricht der Browser die Interaktion ab, bleibt die Anwendung dann z. B. im Zustand „wird gezogen“ hängen. Deshalb immer auch pointercancel behandeln.
  • Auf Touch-Geräten löst der Browser pointercancel aus, sobald er Scrollen oder Zoomen übernimmt. Mit CSS touch-action: none (oder pan-y, pan-x) auf dem Element lässt sich das gezielt steuern. Ein Aufruf von preventDefault() in pointerdown verhindert das Scrollen nicht.
  • Nach pointercancel geht die Pointer-Capture automatisch verloren, es folgt lostpointercapture. Ein zusätzlicher releasePointerCapture()-Aufruf schadet nicht, wenn man vorher hasPointerCapture() prüft.
  • Das Ereignis lässt sich nicht abbrechen. event.preventDefault() hat keine Wirkung.
  • Bei der Maus tritt pointercancel sehr selten auf. Man sollte es vor allem mit echten Touch- und Stiftgeräten testen, da die Geräte-Emulation der DevTools abweichen kann.
  • Kompatibilität: Pointer Events werden in allen aktuellen Browsern unterstützt (Chrome 55+, Firefox 59+, Safari 13+, Edge). Sehr alte iOS-Versionen kennen nur Touch-Events (touchcancel).