Signatur
Beschreibung
PointerEvent fasst Maus-, Stift- und Touch-Eingaben in einem gemeinsamen Ereignismodell zusammen. Statt getrennte Handler für mouse* und touch* zu schreiben, reagiert man auf pointerdown, pointermove, pointerup, pointercancel, pointerover, pointerout, pointerenter, pointerleave, gotpointercapture und lostpointercapture. Ein PointerEvent erbt von MouseEvent, deshalb stehen auch clientX, clientY, button, buttons und die Modifikatortasten zur Verfügung.
Dazu kommen zeigerspezifische Eigenschaften: pointerId (eindeutige ID pro aktivem Zeiger, wichtig für Multitouch), pointerType ("mouse", "pen" oder "touch"), isPrimary, width/height (Kontaktfläche in CSS-Pixeln), pressure und tangentialPressure (0–1 bzw. −1–1), tiltX/tiltY, twist, altitudeAngle/azimuthAngle sowie die Methoden getCoalescedEvents() und getPredictedEvents().
Typische Einsatzfälle sind Zeichen-Apps (Druck- und Neigungsempfindlichkeit), Drag-and-Drop, Schieberegler, Gesten wie Pinch-Zoom und Spiele. Mit element.setPointerCapture(pointerId) leitet man alle weiteren Ereignisse eines Zeigers an ein Element um, selbst wenn der Zeiger es verlässt – ideal für Ziehbewegungen.
Wichtig: Bei Touch führt der Browser standardmäßig eigene Gesten (Scrollen, Zoomen) aus und feuert dann pointercancel. Über die CSS-Eigenschaft touch-action (z. B. touch-action: none) steuert man, welche Gesten der Browser übernimmt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Ereignistyp für den Konstruktor new PointerEvent(type, options), z. B. "pointerdown". |
|
| $options | PointerEventInit | {} | Optionales Objekt mit allen MouseEventInit-Feldern plus pointerId, width, height, pressure, tangentialPressure, tiltX, tiltY, twist, altitudeAngle, azimuthAngle, pointerType, isPrimary, coalescedEvents, predictedEvents. |
Rückgabewert
PointerEvent-Objekt, das mit dispatchEvent() ausgelöst werden kann (isTrusted ist dann false).Beispiele
Gerätetyp und Druck auswerten
const canvas = document.querySelector('#zeichenflaeche');
canvas.addEventListener('pointerdown', (event) => {
console.log(`Typ: ${event.pointerType}, ID: ${event.pointerId}`);
console.log(`Druck: ${event.pressure.toFixed(2)}, primär: ${event.isPrimary}`);
});
Ziehen mit Pointer Capture (inkl. Entfernen der Listener)
// CSS: #regler { touch-action: none; }
const knopf = document.querySelector('#regler');
let startX = 0;
const onMove = (e) => {
knopf.style.transform = `translateX(${e.clientX - startX}px)`;
};
const onEnd = (e) => {
knopf.releasePointerCapture(e.pointerId);
knopf.removeEventListener('pointermove', onMove);
knopf.removeEventListener('pointerup', onEnd);
knopf.removeEventListener('pointercancel', onEnd);
};
knopf.onpointerdown = (e) => {
startX = e.clientX;
knopf.setPointerCapture(e.pointerId);
knopf.addEventListener('pointermove', onMove);
knopf.addEventListener('pointerup', onEnd);
knopf.addEventListener('pointercancel', onEnd);
};
Flüssige Linien mit getCoalescedEvents()
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.addEventListener('pointermove', (event) => {
if (event.buttons !== 1) return;
// Alle zwischengespeicherten Zwischenpunkte zeichnen
const punkte = event.getCoalescedEvents?.() ?? [event];
for (const p of punkte) {
const r = 1 + p.pressure * 6;
ctx.beginPath();
ctx.arc(p.offsetX, p.offsetY, r, 0, Math.PI * 2);
ctx.fill();
}
});
Multitouch: aktive Zeiger zählen und synthetisches Ereignis
const aktiv = new Map();
const flaeche = document.querySelector('#flaeche');
flaeche.addEventListener('pointerdown', (e) => {
aktiv.set(e.pointerId, e);
console.log('Aktive Zeiger:', aktiv.size);
});
['pointerup', 'pointercancel'].forEach((typ) =>
flaeche.addEventListener(typ, (e) => aktiv.delete(e.pointerId))
);
// Synthetisches Ereignis, z. B. für Tests
flaeche.dispatchEvent(new PointerEvent('pointerdown', {
pointerId: 42, pointerType: 'touch', isPrimary: true, bubbles: true
}));
// Wichtig · Fallstricke
- touch-action nicht vergessen: Ohne
touch-action: none(oderpan-yo. ä.) übernimmt der Browser bei Touch das Scrollen und feuertpointercancel– Ziehgesten brechen dann ab. - pointercancel immer behandeln, sonst bleiben Zustände (z. B. „wird gezogen“) hängen.
- Browser feuern nach Pointer-Events weiterhin kompatible
mouse*-Ereignisse;preventDefault()inpointerdownunterdrückt diese, nicht aberclick. pressureist bei Geräten ohne Drucksensor 0,5 bei gedrückter Taste und sonst 0.width/heightsind bei der Maus 1.getCoalescedEvents()fehlt in älteren Safari-Versionen und ist nur im sicheren Kontext verfügbar;getPredictedEvents(),altitudeAngleundazimuthAnglesind neuer und nicht überall vorhanden – per Feature-Erkennung prüfen.pointermovekann sehr häufig feuern; aufwendige Arbeit perrequestAnimationFramebündeln und Listener mit{ passive: true }registrieren, wenn keinpreventDefault()nötig ist.pointerId-Werte sind nur während der Lebensdauer eines Zeigers eindeutig und dürfen nicht als stabile Geräte-ID verwendet werden.