Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.Erfahre mehr über dieses Experiment.
Touch events
Um qualitativ hochwertige Unterstützung für berührungsbasierte Benutzeroberflächen bereitzustellen, bieten Touch-Events die Möglichkeit, Finger- (oder Stylus-) Aktivitäten auf Touchscreens oder Trackpads zu interpretieren.
Die Schnittstellen für Touch-Events sind relativ Low-Level-APIs, die verwendet werden können, um anwendungsspezifische Multi-Touch-Interaktionen wie eine Zwei-Finger-Geste zu unterstützen. Eine Multi-Touch-Interaktion beginnt, wenn ein Finger (oder Stylus) erstmals die Kontaktfläche berührt. Weitere Finger können anschließend die Oberfläche berühren und optional über die Touch-Oberfläche bewegt werden. Die Interaktion endet, wenn die Finger von der Oberfläche entfernt werden. Während dieser Interaktion erhält eine Anwendung Touch-Events während der Start-, Bewegungs- und Endphasen.
Touch-Events ähneln Mausereignissen, unterstützen jedoch gleichzeitige Berührungen an verschiedenen Orten auf der Touch-Oberfläche. DasTouchEvent-Interface kapselt alle derzeit aktiven Berührungspunkte. DasTouch-Interface, das einen einzelnen Berührungspunkt darstellt, enthält Informationen wie die Position des Berührungspunkts relativ zur Browseransicht.
In diesem Artikel
Definitionen
- Oberfläche
Die berührungsempfindliche Oberfläche. Dies kann ein Bildschirm oder ein Trackpad sein.
- Berührungspunkt
Ein Berührungspunkt mit der Oberfläche. Dies kann ein Finger (oder Ellbogen, Ohr, Nase, was auch immer, aber typischerweise ein Finger) oder ein Stylus sein.
Schnittstellen
TouchEventRepräsentiert ein Ereignis, das auftritt, wenn sich der Zustand der Berührungen auf der Oberfläche ändert.
TouchRepräsentiert einen einzelnen Berührungspunkt zwischen dem Benutzer und der Touch-Oberfläche.
TouchListRepräsentiert eine Gruppe von Berührungen; dies wird verwendet, wenn der Benutzer beispielsweise mehrere Finger gleichzeitig auf der Oberfläche hat.
Beispiele
Hinweis:Der untenstehende Text verwendet den Begriff "Finger", um den Kontakt mit der Oberfläche zu beschreiben, aber es könnte natürlich auch ein Stylus oder eine andere Kontaktmethode sein.
Zeichenanwendung
Dieses Beispiel verfolgt mehrere Berührungspunkte gleichzeitig, sodass der Benutzer in einem<canvas> mit mehr als einem Finger gleichzeitig zeichnen kann. Es funktioniert nur in einem Browser, der Touch-Events unterstützt.
Erstellen einer Leinwand
Das HTML besteht aus einem einzigen<canvas>-Element. Kurven werden als Reaktion auf die Berührungsgesten des Benutzers gezeichnet. Ein Button ist ebenfalls enthalten, um die Leinwand zu löschen.
<canvas width="600" height="600"> Your browser does not support the canvas element.</canvas><button>Clear canvas</button>#canvas { border: 1px solid black; display: block;}Verfolgung neuer Berührungen
Wir werden alle laufenden Berührungen verfolgen und für jede von ihnen Linien zeichnen.
const canvas = document.getElementById("canvas");const ctx = canvas.getContext("2d");// Mapping from the pointerId to the current finger positionconst ongoingTouches = new Map();Wenn eintouchstart-Ereignis auftritt, das anzeigt, dass eine neue Berührung auf der Oberfläche stattgefunden hat, wird die untenstehendehandleStart()-Funktion aufgerufen.
function handleStart(event) { event.preventDefault(); for (const changedTouch of event.changedTouches) { const touch = { pageX: changedTouch.pageX, pageY: changedTouch.pageY, color: colorForTouch(changedTouch), }; ongoingTouches.set(changedTouch.identifier, touch); ctx.beginPath(); ctx.arc(touch.pageX, touch.pageY, 4, 0, 2 * Math.PI, false); ctx.fillStyle = touch.color; ctx.fill(); }}canvas.addEventListener("touchstart", handleStart);Dies ruftevent.preventDefault() auf, um den Browser daran zu hindern, das Touch-Ereignis weiter zu verarbeiten (dies verhindert auch, dass ein Mausereignis ebenfalls ausgeliefert wird). Dann erhalten wir den Kontext und ziehen die Liste der geänderten Berührungspunkte aus derTouchEvent.changedTouches-Eigenschaft des Ereignisses.
Danach iterieren wir über alleTouch-Objekte in der Liste, fügen sie einem Array von aktiven Berührungspunkten hinzu und zeichnen den Startpunkt für die Zeichnung als kleinen Kreis; wir verwenden eine 4 Pixel breite Linie, sodass ein Kreis mit einem Radius von 4 Pixeln sauber angezeigt wird.
Um die Zeichnung jeder Berührung unterschiedlich aussehen zu lassen, wird diecolorForTouch()-Funktion verwendet, um basierend auf der einzigartigen Kennung der Berührung eine Farbe zu wählen. Diese Kennung ist eine intransparente Zahl, aber wir können zumindest darauf vertrauen, dass sie sich zwischen den aktuell aktiven Berührungen unterscheidet.
function colorForTouch(touch) { const r = touch.identifier % 16; const g = Math.floor(touch.identifier / 3) % 16; const b = Math.floor(touch.identifier / 7) % 16; // convert to hex digits return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`;}Das Ergebnis dieser Funktion ist ein String, der beim Aufrufen von<canvas>-Funktionen zum Festlegen von Zeichenfarben verwendet werden kann. Beispielsweise ergibt einTouch.identifier-Wert von 10 den String "#aa3311".
Umgang mit dem Ende einer Berührung
Wenn der Benutzer einen Finger von der Oberfläche hebt, wird eintouchend-Ereignis gesendet. Wir behandeln dies durch Aufruf der unten stehendenhandleEnd()-Funktion. Ihre Aufgabe ist es, das letzte Liniensegment für jede Berührung zu zeichnen, die beendet wurde, und den Berührungspunkt aus der fortlaufenden Berührungskarte zu entfernen.
function handleEnd(event) { event.preventDefault(); for (const changedTouch of event.changedTouches) { const touch = ongoingTouches.get(changedTouch.identifier); if (!touch) { console.error(`End: Could not find touch ${changedTouch.identifier}`); continue; } ctx.lineWidth = 4; ctx.fillStyle = touch.color; ctx.beginPath(); ctx.moveTo(touch.pageX, touch.pageY); ctx.lineTo(changedTouch.pageX, changedTouch.pageY); ctx.fillRect(changedTouch.pageX - 4, changedTouch.pageY - 4, 8, 8); ongoingTouches.delete(changedTouch.identifier); }}canvas.addEventListener("touchend", handleEnd);Dies ist der vorherigen Funktion sehr ähnlich; die einzigen wirklichen Unterschiede bestehen darin, dass wir ein kleines Quadrat zeichnen, um das Ende zu markieren und dass wir beim Aufruf vonMap.delete() den alten Eintrag aus der fortlaufenden Berührungskarte entfernen, ohne die aktualisierten Informationen hinzuzufügen. Das Ergebnis ist, dass wir diesen Berührungspunkt nicht mehr verfolgen.
Umgang mit abgebrochenen Berührungen
Wenn der Finger des Benutzers in die Browser-UI wandert oder die Berührung aus einem anderen Grund abgebrochen werden muss, wird dastouchcancel-Ereignis gesendet, und wir rufen die untenstehendehandleCancel()-Funktion auf.
function handleCancel(event) { event.preventDefault(); for (const changedTouch of event.changedTouches) { if (!ongoingTouches.has(changedTouch.identifier)) { console.error(`Cancel: Could not find touch ${changedTouch.identifier}`); continue; } ongoingTouches.delete(changedTouch.identifier); }}canvas.addEventListener("touchcancel", handleCancel);Da die Idee darin besteht, die Berührung sofort abzubrechen, entfernen wir sie aus der fortlaufenden Berührungskarte ohne ein letztes Liniensegment zu zeichnen.
Zeichnen beim Bewegen der Berührungen
Jedes Mal, wenn sich ein oder mehrere Finger bewegen, wird eintouchmove-Ereignis ausgeliefert, was dazu führt, dass unserehandleMove()-Funktion aufgerufen wird. Ihre Verantwortung in diesem Beispiel besteht darin, die zwischengespeicherten Berührungsinformationen zu aktualisieren und eine Linie von der vorherigen Position zur aktuellen Position jeder Berührung zu zeichnen.
function handleMove(event) { event.preventDefault(); for (const changedTouch of event.changedTouches) { const touch = ongoingTouches.get(changedTouch.identifier); if (!touch) { console.error(`Move: Could not find touch ${changedTouch.identifier}`); continue; } ctx.beginPath(); ctx.moveTo(touch.pageX, touch.pageY); ctx.lineTo(changedTouch.pageX, changedTouch.pageY); ctx.lineWidth = 4; ctx.strokeStyle = touch.color; ctx.stroke(); const newTouch = { pageX: changedTouch.pageX, pageY: changedTouch.pageY, color: touch.color, }; ongoingTouches.set(changedTouch.identifier, newTouch); }}canvas.addEventListener("touchmove", handleMove);Dies iteriert auch über die geänderten Berührungen, sucht jedoch in unserem zwischengespeicherten Informationsarray nach den vorherigen Informationen zu jeder Berührung, um den Startpunkt für das neue Liniensegment jeder Berührung zu bestimmen. Dies erfolgt, indem dieTouch.identifier-Eigenschaft jeder Berührung betrachtet wird. Diese Eigenschaft ist eine eindeutige Ganzzahl für jede Berührung und bleibt während der Dauer des Kontakts jedes Fingers mit der Oberfläche für jedes Ereignis konsistent.
Dies ermöglicht es uns, die Koordinaten der vorherigen Position jeder Berührung zu erhalten und die entsprechenden Kontextmethoden zu verwenden, um ein Liniensegment zu zeichnen, das die beiden Positionen miteinander verbindet.
Nach dem Zeichnen der Linie rufen wirMap.set() auf, um die vorherigen Informationen über den Berührungspunkt durch die aktuellen Informationen in dertouches-Karte zu ersetzen.
Löschbutton
Fügen Sie schließlich eine Löschfunktion hinzu.
document.getElementById("clear").addEventListener("click", () => { ctx.clearRect(0, 0, canvas.width, canvas.height);});Ergebnis
Sie können dieses Beispiel auf Mobilgeräten testen, indem Sie das Feld unten berühren.
Hinweis:Im Allgemeinen wird das Beispiel auf Plattformen funktionieren, die Touch-Events bieten.Sie können dies auf Desktop-Plattformen testen, die solche Ereignisse simulieren können:
- Aktivieren Sie in Firefox die "Touch-Simulation" imResponsive Design Mode (es kann sein, dass Sie die Seite neu laden müssen).
- Verwenden Sie in Chrome denGerätemodus und setzen Sie denGerätetyp auf einen, der Touch-Events sendet.
Zusätzliche Tipps
Dieser Abschnitt bietet zusätzliche Tipps, wie Sie Touch-Events in Ihrer Webanwendung handhaben können.
Umgang mit Klicks
Da der Aufruf vonpreventDefault() bei einemtouchstart- oder dem erstentouchmove-Ereignis einer Serie die entsprechenden Mausereignisse verhindert, ist es üblich,preventDefault() beitouchmove anstelle vontouchstart aufzurufen. Auf diese Weise können Mausereignisse weiterhin ausgelöst werden und Dinge wie Links funktionieren weiter. Alternativ haben einige Frameworks begonnen, Touch-Events als Mausereignisse erneut auszulösen, um denselben Zweck zu erreichen. (Dieses Beispiel ist vereinfacht und kann zu seltsamem Verhalten führen. Es ist nur als Leitfaden gedacht.)
function onTouch(event) { event.preventDefault(); if ( event.touches.length > 1 || (event.type === "touchend" && event.touches.length > 0) ) return; let type; let touch; switch (event.type) { case "touchstart": type = "mousedown"; touch = event.changedTouches[0]; break; case "touchmove": type = "mousemove"; touch = event.changedTouches[0]; break; case "touchend": type = "mouseup"; touch = event.changedTouches[0]; break; } const newEvent = new MouseEvent(type, { bubbles: true, cancelable: true, view: event.originalTarget.ownerDocument.defaultView, detail: 0, screenX: touch.screenX, screenY: touch.screenY, clientX: touch.clientX, clientY: touch.clientY, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey, metaKey: event.metaKey, button: 0, relatedTarget: null, }); event.originalTarget.dispatchEvent(newEvent);}Aufruf von preventDefault() nur bei einer zweiten Berührung
Eine Technik zur Vermeidung von Aktionen wiepinchZoom auf einer Seite besteht darin,preventDefault() bei der zweiten Berührung einer Serie aufzurufen. Dieses Verhalten ist in der Touch-Events-Spezifikation nicht gut definiert und führt zu unterschiedlichen Verhaltensweisen in verschiedenen Browsern (d.h. iOS wird das Zoomen verhindern, erlaubt jedoch das Scrollen mit beiden Fingern; Android erlaubt Zoomen, jedoch nicht das Scrollen; Opera und Firefox verhindern derzeit alle Scroll- und Zoomvorgänge.) Derzeit wird nicht empfohlen, sich auf ein bestimmtes Verhalten in diesem Fall zu verlassen, sondern vielmehr auf das Meta Viewport, um das Zoomen zu verhindern.
Spezifikationen
| Specification |
|---|
| Touch Events> |
Browser-Kompatibilität
Touch-Events sind in der Regel auf Geräten mit Touchscreen verfügbar, aber viele Browser machen die Touch-Events-API auf allen Desktop-Geräten, auch auf solchen mit Touchscreens, nicht verfügbar.
Der Grund dafür ist, dass einige Websites die Verfügbarkeit von Teilen der Touch-Events-API als Indikator dafür verwenden, dass der Browser auf einem mobilen Gerät läuft. Wenn die Touch-Events-API verfügbar ist, gehen diese Websites davon aus, dass es sich um ein mobiles Gerät handelt und liefern mobil optimierte Inhalte. Dies kann dann zu einer schlechten Benutzererfahrung für Nutzer von Desktop-Geräten mit Touchscreens führen.
Um sowohl Touch- als auch Maus-Eingaben auf allen Gerätetypen zu unterstützen, verwenden Sie stattdessenPointer-Events.