Signatur
Beschreibung
Das Ereignis pointermove ist Teil der Pointer Events API und fasst Maus-, Stift- und Touch-Eingaben in einem einheitlichen Modell zusammen. Es wird ausgelöst, sobald ein aktiver Zeiger seine Position ändert. Es feuert auch dann, wenn sich Eigenschaften wie pressure, tiltX/tiltY, width/height oder der Tastenzustand ändern und dafür kein anderes Pointer-Ereignis zuständig ist. Die Handler-Funktion erhält ein PointerEvent, das von MouseEvent erbt.
Registrieren lässt sich das Ereignis mit element.addEventListener("pointermove", handler) oder über die Eigenschaft element.onpointermove = handler. Das Ereignis steigt im DOM auf (Bubbling), ist abbrechbar (cancelable) und passiert Shadow-DOM-Grenzen (composed).
Typische Einsatzfälle sind Drag-and-Drop, Zeichen-Anwendungen, eigene Schieberegler, Hover-Effekte und Gesten. Zusammen mit setPointerCapture() bekommt das Element alle weiteren Bewegungen eines Zeigers, auch wenn dieser das Element verlässt.
Bei Touch-Eingaben bricht der Browser den Zeiger mit pointercancel ab, sobald er selbst scrollt oder zoomt. Danach kommen keine pointermove-Ereignisse mehr an. Mit der CSS-Eigenschaft touch-action (z. B. touch-action: none) legst du fest, welche Browser-Gesten erlaubt bleiben.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "pointermove". |
|
| $handler Pflicht | (event: PointerEvent) => void | Callback, der bei jeder Zeigerbewegung aufgerufen wird. Wichtige Eigenschaften: clientX/clientY, offsetX/offsetY, pointerId, pointerType ("mouse", "pen", "touch"), pressure, buttons, isPrimary. |
|
| $options | boolean | { capture?: boolean, once?: boolean, passive?: boolean, signal?: AbortSignal } | false | Optionen für addEventListener. Mit passive: true kann der Browser flüssiger rendern, wenn du preventDefault() nicht brauchst. Mit signal lässt sich der Listener gezielt entfernen. |
Rückgabewert
addEventListener gibt undefined zurück. Der Handler erhält ein PointerEvent-Objekt.Beispiele
Zeigerposition live anzeigen (addEventListener)
const box = document.querySelector('#flaeche');
const info = document.querySelector('#info');
box.addEventListener('pointermove', (event) => {
info.textContent = `${event.pointerType}: x=${event.offsetX}, y=${event.offsetY}, Druck=${event.pressure.toFixed(2)}`;
});
Element ziehen mit Pointer Capture
const knob = document.querySelector('#knob');
knob.style.touchAction = 'none'; // Browser soll bei Touch nicht scrollen
let start = null;
knob.addEventListener('pointerdown', (e) => {
knob.setPointerCapture(e.pointerId);
start = { x: e.clientX - knob.offsetLeft, y: e.clientY - knob.offsetTop };
});
knob.addEventListener('pointermove', (e) => {
if (!knob.hasPointerCapture(e.pointerId)) return;
knob.style.left = `${e.clientX - start.x}px`;
knob.style.top = `${e.clientY - start.y}px`;
});
knob.addEventListener('pointerup', (e) => {
knob.releasePointerCapture(e.pointerId);
});
on-Property und Entfernen per removeEventListener
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const zeichnen = (e) => {
if (e.buttons !== 1) return; // nur bei gedrückter Haupttaste
ctx.fillRect(e.offsetX, e.offsetY, 2, 2);
};
canvas.addEventListener('pointermove', zeichnen);
// Nach 10 Sekunden Zeichnen deaktivieren
setTimeout(() => canvas.removeEventListener('pointermove', zeichnen), 10_000);
// Alternative: Einzel-Handler per on-Property
canvas.onpointermove = (e) => console.log('Bewegung', e.pointerId);
// canvas.onpointermove = null; // wieder entfernen
Hochauflösende Stift-Eingabe mit getCoalescedEvents()
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.addEventListener('pointermove', (e) => {
if (e.buttons !== 1) return;
// Zwischenpunkte, die der Browser zu einem Ereignis zusammengefasst hat
const punkte = e.getCoalescedEvents?.() ?? [e];
for (const p of punkte) {
ctx.fillRect(p.offsetX, p.offsetY, 1 + p.pressure * 4, 1 + p.pressure * 4);
}
});
// Wichtig · Fallstricke
- Hohe Frequenz:
pointermovefeuert sehr oft. Aufwendige Arbeit (Layout, DOM-Änderungen) gehört gebündelt inrequestAnimationFrame(). Browser fassen Ereignisse oft pro Frame zusammen. Die einzelnen Zwischenpunkte liefertgetCoalescedEvents(), Safari unterstützt das erst seit Version 18. - Touch und
touch-action: Ohne passendestouch-actionim CSS übernimmt der Browser bei Touch das Scrollen. Er sendet dannpointercancel, und weiterepointermove-Ereignisse bleiben aus. - Mehrere Zeiger: Beim Multitouch kommt jedes Ereignis mit einer eigenen
pointerId. PrüfeisPrimaryoder verwalte die Zeiger in einerMap. - Maus ohne Taste: Bei der Maus feuert
pointermoveauch ohne gedrückte Taste. Für Drag-Logik solltest dubuttonsoderhasPointerCapture()prüfen. preventDefault()inpointermoveverhindert kein Scrollen. Dafür isttouch-actionzuständig.- Kompatibilität: Alle aktuellen Browser unterstützen das Ereignis. Safari kann es seit Version 13, der Internet Explorer 10 nur mit Präfix (
MSPointerMove).