Signatur
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
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)}°`);
});
Ü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');
}
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);
});
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');
}
});
// Wichtig · Fallstricke
- Nicht standardisiert:
gestureendundGestureEventgibt 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 elementodertypeof GestureEvent !== 'undefined', ob es verfügbar ist. scaleundrotationbeziehen 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 mitpreventDefault()ingesturestart/gesturechange(der Listener darf dafür nichtpassivesein) oder mit CSStouch-action. Neuere iOS-Versionen ignorieren aus Gründen der Barrierefreiheit teilweiseuser-scalable=noim 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.