Gesten für Kneifen und Zoomen
Das Hinzufügen von Gesten zu einer Anwendung kann die Benutzererfahrung erheblich verbessern. Es gibt viele Arten von Gesten, von der einfachen Einfinger-Wisch-Geste bis zur komplexeren Mehrfinger-Dreh_Geste, bei der sich die Berührungspunkte (auch _Zeiger genannt) in unterschiedliche Richtungen bewegen.
Dieses Beispiel zeigt, wie Sie die Kneifen/Zoomen-Geste erkennen können. Es verwendet Pointer Events, um zu erkennen, ob der Benutzer zwei Zeiger näher zueinander oder weiter voneinander entfernt bewegt.
Eine Live-Version dieser Anwendung ist auf GitHub verfügbar. Der Quellcode ist auf GitHub verfügbar; Pull-Requests und Fehlermeldungen sind willkommen.
Beispiel
In diesem Beispiel verwenden Sie die Pointer Events, um gleichzeitig zwei Zeigegeräte beliebigen Typs zu erkennen, einschließlich Finger, Maus und Stifte. Die Hereinzoomen (Verkleinern)-Geste, bei der die beiden Zeiger zueinander bewegt werden, ändert die Hintergrundfarbe des Zielelements auf lightblue
. Die Herauszoomen (Vergrößern)-Geste, bei der die beiden Zeiger voneinander entfernt werden, ändert die Hintergrundfarbe des Zielelements auf pink
.
Berührungsziel definieren
Die Anwendung verwendet ein <div>
, um die Zielbereiche der Zeiger zu definieren.
div {
margin: 0em;
padding: 2em;
}
#target {
background: white;
border: 1px solid black;
}
Globaler Zustand
Das Unterstützen einer Zwei-Zeiger-Geste erfordert, den Ereigniszustand eines Zeigers während verschiedener Ereignisphasen beizubehalten. Diese Anwendung verwendet zwei globale Variablen, um den Ereigniszustand zu zwischenspeichern.
// Global vars to cache event state
const evCache = [];
let prevDiff = -1;
Ereignishandler registrieren
Ereignishandler werden für die folgenden Pointer Events registriert: pointerdown
, pointermove
und pointerup
. Der Handler für pointerup
wird für die pointercancel
, pointerout
und pointerleave
Ereignisse verwendet, da diese vier Ereignisse in dieser Anwendung dieselbe Semantik haben.
// Install event handlers for the pointer target
const el = document.getElementById("target");
el.onpointerdown = pointerdownHandler;
el.onpointermove = pointermoveHandler;
// Use same handler for pointer{up,cancel,out,leave} events since
// the semantics for these events - in this app - are the same.
el.onpointerup = pointerupHandler;
el.onpointercancel = pointerupHandler;
el.onpointerout = pointerupHandler;
el.onpointerleave = pointerupHandler;
Zeiger herunter
Das pointerdown
-Ereignis wird ausgelöst, wenn ein Zeiger (Maus, Stift/Stylus oder Berührungspunkt auf einem Touchscreen) Kontakt mit der Kontaktoberfläche herstellt. In dieser Anwendung muss der Zustand des Ereignisses zwischengespeichert werden, falls dieses Down-Ereignis Teil einer Zwei-Zeiger-Kneifen/Zoom-Geste ist.
function pointerdownHandler(ev) {
// The pointerdown event signals the start of a touch interaction.
// This event is cached to support 2-finger gestures
evCache.push(ev);
log("pointerDown", ev);
}
Zeiger bewegen
Der pointermove
-Ereignishandler erkennt, ob ein Benutzer eine Zwei-Zeiger-Kneifen/Zoom-Geste verwendet. Wenn zwei Zeiger heruntergedrückt sind und der Abstand zwischen den Zeigern zunimmt (signalisierend ein Herauszoomen oder Vergrößern), wird die Hintergrundfarbe des Elements auf pink
geändert, und wenn der Abstand zwischen den Zeigern abnimmt (ein Hereinzoomen oder Verkleinern), wird die Hintergrundfarbe auf lightblue
geändert. In einer anspruchsvolleren Anwendung könnte die Bestimmung des Herein- oder Herauszoomens verwendet werden, um anwendungsspezifische Semantiken anzuwenden.
Wenn dieses Ereignis verarbeitet wird, wird der Rahmen des Ziels auf dashed
gesetzt, um eine klare visuelle Anzeige zu bieten, dass das Element ein Bewegungsereignis empfangen hat.
function pointermoveHandler(ev) {
// This function implements a 2-pointer horizontal pinch/zoom gesture.
//
// If the distance between the two pointers has increased (zoom in),
// the target element's background is changed to "pink" and if the
// distance is decreasing (zoom out), the color is changed to "lightblue".
//
// This function sets the target element's border to "dashed" to visually
// indicate the pointer's target received a move event.
log("pointerMove", ev);
ev.target.style.border = "dashed";
// Find this event in the cache and update its record with this event
const index = evCache.findIndex(
(cachedEv) => cachedEv.pointerId === ev.pointerId,
);
evCache[index] = ev;
// If two pointers are down, check for pinch gestures
if (evCache.length === 2) {
// Calculate the distance between the two pointers
const curDiff = Math.abs(evCache[0].clientX - evCache[1].clientX);
if (prevDiff > 0) {
if (curDiff > prevDiff) {
// The distance between the two pointers has increased
log("Pinch moving OUT -> Zoom in", ev);
ev.target.style.background = "pink";
}
if (curDiff < prevDiff) {
// The distance between the two pointers has decreased
log("Pinch moving IN -> Zoom out", ev);
ev.target.style.background = "lightblue";
}
}
// Cache the distance for the next move event
prevDiff = curDiff;
}
}
Zeiger hoch
Das pointerup
-Ereignis wird ausgelöst, wenn ein Zeiger von der Kontaktoberfläche entfernt wird. Wenn dies geschieht, wird das Ereignis aus dem Ereigniscache entfernt und die Hintergrundfarbe und der Rahmen des Zielelements werden auf ihre ursprünglichen Werte zurückgesetzt.
In dieser Anwendung wird dieser Handler auch für pointercancel
, pointerleave
und pointerout
Ereignisse verwendet.
function pointerupHandler(ev) {
log(ev.type, ev);
// Remove this pointer from the cache and reset the target's
// background and border
removeEvent(ev);
ev.target.style.background = "white";
ev.target.style.border = "1px solid black";
// If the number of pointers down is less than two then reset diff tracker
if (evCache.length < 2) {
prevDiff = -1;
}
}
Anwendungs-UI
Die Anwendung verwendet ein <div>
-Element für den Berührungsbereich und bietet Schaltflächen zum Aktivieren eines Protokolls und zum Löschen des Protokolls.
Um zu verhindern, dass das Standard-Touch-Verhalten des Browsers die Zeigerbehandlung dieser Anwendung überschreibt, wird die touch-action
-Eigenschaft auf das <body>
-Element angewendet.
<div id="target">
Touch and Hold with 2 pointers, then pinch in or out.<br />
The background color will change to pink if the pinch is opening (Zoom In) or
changes to lightblue if the pinch is closing (Zoom out).
</div>
<!-- UI for logging/debugging -->
<button id="log">Start/Stop event logging</button>
<button id="clear-log">Clear the log</button>
<p></p>
<output></output>
body {
touch-action: none; /* Prevent default touch behavior */
}
Verschiedene Funktionen
Diese Funktionen unterstützen die Anwendung, sind jedoch nicht direkt im Ereignisfluss beteiligt.
Cache-Verwaltung
Diese Funktion hilft bei der Verwaltung der globalen Ereigniscaches evCache
.
function removeEvent(ev) {
// Remove this event from the target's cache
const index = evCache.findIndex(
(cachedEv) => cachedEv.pointerId === ev.pointerId,
);
evCache.splice(index, 1);
}
Ereignisprotokollierung
Diese Funktionen werden verwendet, um die Ereignisaktivität an das Anwendungsfenster zu senden (um das Debuggen und Erlernen des Ereignisflusses zu unterstützen).
// Log events flag
let logEvents = false;
document.getElementById("log").addEventListener("click", enableLog);
document.getElementById("clear-log").addEventListener("click", clearLog);
// Logging/debugging functions
function enableLog(ev) {
logEvents = !logEvents;
}
function log(prefix, ev) {
if (!logEvents) return;
const o = document.getElementsByTagName("output")[0];
o.innerText += `${prefix}:
pointerID = ${ev.pointerId}
pointerType = ${ev.pointerType}
isPrimary = ${ev.isPrimary}
`;
}
function clearLog(event) {
const o = document.getElementsByTagName("output")[0];
o.textContent = "";
}
Siehe auch
- Pointer Events jetzt im Firefox Nightly; Mozilla Hacks; von Matt Brubeck und Jason Weathersby; 04. Aug. 2015
- jQuery Pointer Events Polyfill
- Gesten; Material Design