Start · Sprachen · JavaScript · Referenz · Element: gestureend

Element: gestureend

Ereignis

Das nicht standardisierte <code>gestureend</code>-Ereignis (nur Safari/WebKit) wird ausgelöst, wenn eine Mehrfinger-Geste endet, weil weniger als zwei Finger die Oberfläche berühren.

seit JavaScript Nicht standardisiert: nur Safari (iOS 2+, macOS 10 Kategorie: webapi

Signatur

element.addEventListener("gestureend", handler)

Beschreibung

Das Ereignis gestureend gehört zu den proprietären Gesten-Ereignissen von WebKit. Zusammen mit gesturestart und gesturechange bildet es den Lebenszyklus einer Mehrfinger-Geste, etwa einer Pinch-Zoom- oder Drehbewegung. gestureend wird ausgelöst, sobald nicht mehr mindestens zwei Finger die Touch-Oberfläche (iPhone/iPad) bzw. das Trackpad (macOS-Safari) berühren.

Der Handler erhält ein GestureEvent. Die wichtigsten Eigenschaften sind scale (Skalierungsfaktor relativ zum Beginn der Geste, 1 = unverändert) und rotation (Drehung in Grad, positiv im Uhrzeigersinn). Beim gestureend stehen dort die Endwerte der Geste. Damit lässt sich eine Transformation, die während gesturechange nur vorläufig angezeigt wurde, dauerhaft übernehmen.

Du registrierst das Ereignis mit addEventListener("gestureend", handler). In Safari gibt es zusätzlich die Eigenschaft element.ongestureend. Das Ereignis steigt im DOM auf (Bubbling). Deshalb kannst du es auch per Delegation an einem übergeordneten Element abfangen.

Weil das Ereignis nur in Safari existiert, taugt es höchstens als Ergänzung. Plattformübergreifender Code sollte Gesten über Pointer Events (pointerdown, pointermove, pointerup) oder Touch Events (touchend mit touches.length < 2) selbst erkennen.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "gestureend".
$handler Pflicht (event: GestureEvent) => void Callback, der ein GestureEvent mit u. a. scale, rotation, clientX/clientY, target sowie den Modifikatortasten (altKey, ctrlKey, metaKey, shiftKey) erhält.
$options boolean | AddEventListenerOptions false Optionen wie capture, once, passive oder signal (z. B. ein AbortSignal, um den Listener später zu entfernen).

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler erhält ein GestureEvent.

Beispiele

Pinch-Zoom und Drehung nach dem Ende der Geste übernehmen

const bild = document.querySelector('#foto');
let aktuelleSkalierung = 1;
let aktuelleRotation = 0;

bild.addEventListener('gesturestart', (e) => e.preventDefault());

bild.addEventListener('gesturechange', (e) => {
  e.preventDefault();
  // Vorläufige Vorschau während der Geste
  bild.style.transform = `scale(${aktuelleSkalierung * e.scale}) rotate(${aktuelleRotation + e.rotation}deg)`;
});

bild.addEventListener('gestureend', (e) => {
  // Endwerte dauerhaft übernehmen
  aktuelleSkalierung *= e.scale;
  aktuelleRotation += e.rotation;
  console.log(`Geste beendet: scale=${aktuelleSkalierung.toFixed(2)}, rotation=${aktuelleRotation.toFixed(0)}°`);
});
Geste beendet: scale=1.85, rotation=30°

Über die on-Eigenschaft mit Funktionserkennung

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

if ('ongestureend' in karte) {
  karte.ongestureend = (e) => {
    if (e.scale > 1.5) {
      karte.classList.add('vergroessert');
    } else if (e.scale < 0.7) {
      karte.classList.remove('vergroessert');
    }
  };
} else {
  console.log('GestureEvents nicht verfügbar – Pointer-Events-Fallback nutzen');
}
GestureEvents nicht verfügbar – Pointer-Events-Fallback nutzen (in Chrome/Firefox)

Listener per AbortController wieder entfernen

const flaeche = document.querySelector('#zeichenflaeche');
const controller = new AbortController();

const beiGestenende = (e) => {
  console.log('Endgültige Drehung:', Math.round(e.rotation), 'Grad');
};

flaeche.addEventListener('gestureend', beiGestenende, { signal: controller.signal });

// Später, z. B. beim Verlassen der Ansicht:
document.querySelector('#fertig').addEventListener('click', () => {
  controller.abort(); // entfernt den gestureend-Listener
  // alternativ: flaeche.removeEventListener('gestureend', beiGestenende);
});
Endgültige Drehung: 45 Grad

Plattformübergreifender Fallback mit Touch Events

const el = document.querySelector('#zoombereich');
let mehrfingerAktiv = false;

el.addEventListener('touchstart', (e) => {
  if (e.touches.length >= 2) mehrfingerAktiv = true;
});

el.addEventListener('touchend', (e) => {
  // Entspricht sinngemäß gestureend
  if (mehrfingerAktiv && e.touches.length < 2) {
    mehrfingerAktiv = false;
    console.log('Mehrfinger-Geste beendet');
  }
});
Mehrfinger-Geste beendet

// Wichtig · Fallstricke

  • Nicht standardisiert: gestureend und GestureEvent gibt es nur in Safari (iOS/iPadOS und macOS mit Trackpad). Chrome, Firefox und Edge kennen das Ereignis nicht, auch nicht auf Android. Setze es nicht als einzige Lösung ein, sondern prüfe vorher mit 'ongestureend' in element oder typeof GestureEvent !== 'undefined', ob es verfügbar ist.
  • scale und rotation beziehen sich immer auf den Beginn der aktuellen Geste, nicht auf den Zustand vor früheren Gesten. Bei mehreren Gesten nacheinander musst du die Werte selbst aufsummieren bzw. aufmultiplizieren (siehe erstes Beispiel).
  • Den nativen Pinch-Zoom der Seite unterdrückst du nicht über gestureend, sondern mit preventDefault() in gesturestart/gesturechange (der Listener darf dafür nicht passive sein) oder mit CSS touch-action. Neuere iOS-Versionen ignorieren aus Gründen der Barrierefreiheit teilweise user-scalable=no im Viewport-Meta-Tag.
  • Auf iOS laufen parallel auch Touch Events (touchstart/touchend). Wenn du beide Systeme gleichzeitig auswertest, kann eine Geste doppelt verarbeitet werden.
  • Für neuen Code sind Pointer Events der empfohlene, standardisierte Weg. Mehrfinger-Gesten erkennst du dabei, indem du die aktiven pointerIds mitzählst.