Multi-Touch-Webentwicklung

Boris Smus
Boris Smus

Einführung

Mobilgeräte wie Smartphones und Tablets haben in der Regel einen kapazitiven berührungsempfindlichen Bildschirm, um Interaktionen mit den Fingern des Nutzers zu erfassen. Da sich das mobile Web weiterentwickelt, um immer ausgefeiltere Anwendungen zu ermöglichen, benötigen Webentwickler eine Möglichkeit, mit diesen Ereignissen umzugehen. In fast jedem schnelllebigen Spiel muss der Spieler mehrere Tasten gleichzeitig drücken, was im Kontext eines Touchscreens Multi-Touch impliziert.

Apple hat mit iOS 2.0 die Touch Events API eingeführt. Android hat diesen De-facto-Standard erreicht und die Lücke geschlossen. Vor Kurzem hat sich eine W3C-Arbeitsgruppe zusammengetan, um an der Spezifikation für Touch-Ereignisse zu arbeiten.

In diesem Artikel geht es um die Touch Events API, die von iOS- und Android-Geräten sowie von Chrome für Desktop-Computer auf Hardware unterstützt wird, die Touchbedienung unterstützt. Außerdem stelle ich Ihnen einige Best Practices vor und erläutere nützliche Techniken, die die Entwicklung von Apps mit Touch-Funktion erleichtern.

Touch-Ereignisse

In der Spezifikation sind drei grundlegende Touch-Ereignisse aufgeführt und auf allen Mobilgeräten implementiert:

  • touchstart: Ein Finger wird auf ein DOM-Element gelegt.
  • touchmove: Ein Finger wird über ein DOM-Element gezogen.
  • touchend: Ein Finger wird von einem DOM-Element entfernt.

Jedes Touch-Ereignis umfasst drei Listen von Berührungen:

  • touches: eine Liste aller Finger, die sich aktuell auf dem Bildschirm befinden
  • targetTouches: eine Liste der Finger des aktuellen DOM-Elements.
  • changedTouches: eine Liste der Finger, die am aktuellen Ereignis beteiligt sind. Bei einem Touchend-Ereignis ist dies beispielsweise der Finger, der entfernt wurde.

Diese Listen bestehen aus Objekten, die Touch-Informationen enthalten:

  • identifier: eine Zahl, die den aktuellen Finger in der Touch-Sitzung eindeutig identifiziert
  • target: Das DOM-Element, das das Ziel der Aktion war.
  • Client-/Seite-/Bildschirmkoordinaten: wo auf dem Bildschirm die Aktion stattgefunden hat.
  • radius-Koordinaten und RotationAngle: beschreiben die Ellipse, die ungefähr der Fingerform entspricht

Apps mit Touchscreen

Die Ereignisse touchstart, touchmove und touchend bieten einen ausreichenden Funktionsumfang, um praktisch jede berührungsbasierte Interaktion zu unterstützen – einschließlich aller üblichen Multi-Touch-Gesten wie Zoomen durch Auseinander- und Zusammenziehen der Finger und Drehen.

Mit diesem Snippet können Sie ein DOM-Element mit einem Finger verschieben:

var obj = document.getElementById('id');
obj.addEventListener('touchmove', function(event) {
  // If there's exactly one finger inside this element
  if (event.targetTouches.length == 1) {
    var touch = event.targetTouches[0];
    // Place element where the finger is
    obj.style.left = touch.pageX + 'px';
    obj.style.top = touch.pageY + 'px';
  }
}, false);

Unten siehst du ein Beispiel, in dem alle aktuellen Berührungen auf dem Bildschirm angezeigt werden. Das ist nützlich, um ein Gefühl für die Reaktionsfähigkeit des Geräts zu bekommen.

Fingerbewegungen
// Setup canvas and expose context via ctx variable
canvas.addEventListener('touchmove', function(event) {
  for (var i = 0; i < event.touches.length; i++) {
    var touch = event.touches[i];
    ctx.beginPath();
    ctx.arc(touch.pageX, touch.pageY, 20, 0, 2*Math.PI, true);
    ctx.fill();
    ctx.stroke();
  }
}, false);

Demos

Es gibt bereits eine Reihe interessanter Multi-Touch-Demos, zum Beispiel diese Demo zum Canvas-basierten Zeichnen von Paul Irish und anderen Entwicklern.

Screenshot: Zeichnung

Und Browser Ninja, eine technische Demo, bei der es sich um einen Fruit Ninja-Klon handelt, der CSS3-Transformationen und -Übergänge sowie Canvas verwendet:

Browser-Ninja

Best Practices

Zoom verhindern

Die Standardeinstellungen eignen sich nicht gut für Multi-Touch-Gesten, da Ihre Wischbewegungen und Gesten häufig mit dem Browserverhalten verbunden sind, z. B. Scrollen und Zoomen.

Wenn Sie das Zoomen deaktivieren möchten, richten Sie Ihren Darstellungsbereich mithilfe des folgenden Meta-Tags so ein, dass er nicht nutzerskalierbar ist:

<meta name="viewport" 
  content="width=device-width, initial-scale=1.0, user-scalable=no>

Weitere Informationen zum Festlegen des Darstellungsbereichs finden Sie in diesem Artikel zu HTML5 für Mobilgeräte.

Scrollen verhindern

Einige Mobilgeräte haben Standardverhalten für Touchmove-Ereignisse, z. B. der klassische Overscroll-Effekt von iOS, der dazu führt, dass die Ansicht zurückspringt, wenn das Scrollen die Grenzen des Inhalts überschreitet. Dies ist in vielen Multi-Touch-Anwendungen verwirrend und kann leicht deaktiviert werden:

document.body.addEventListener('touchmove', function(event) {
  event.preventDefault();
}, false); 

Sorgfältig rendern

Wenn Sie eine Multi-Touch-Anwendung schreiben, die komplexe Mehrfinger-Touch-Gesten beinhaltet, achten Sie darauf, wie Sie auf Touch-Ereignisse reagieren, da Sie so viele gleichzeitig verarbeiten werden. Betrachten Sie das Beispiel im vorherigen Abschnitt, in dem alle Berührungen des Bildschirms dargestellt sind. Sie könnten zeichnen, sobald eine Berührungseingabe erfolgt:

canvas.addEventListener('touchmove', function(event) {
  renderTouches(event.touches);
}, false);

Diese Technik lässt sich jedoch nicht mit der Anzahl der Finger auf dem Bildschirm skalieren. Stattdessen können Sie alle Finger erfassen und in einer Schleife rendern, um die Leistung deutlich zu verbessern:

var touches = []
canvas.addEventListener('touchmove', function(event) {
  touches = event.touches;
}, false);

// Setup a 60fps timer
timer = setInterval(function() {
  renderTouches(touches);
}, 15);

targetTouches und changedTouches verwenden

Denken Sie daran, dass „event.touches“ ein Array von ALLEN Fingern ist, die den Bildschirm berühren, nicht nur die Finger auf dem DOM-Element-Ziel. Möglicherweise ist es sinnvoller, stattdessen event.targetTouches oder event.changedTouches zu verwenden.

Da Sie schließlich für Mobilgeräte entwickeln, sollten Sie sich mit den allgemeinen Best Practices für Mobilgeräte vertraut machen, die in Eric Bidelmans Artikel und in diesem W3C-Dokument behandelt werden.

Gerätesupport

Leider variieren die Implementierungen von Touch-Ereignissen erheblich in Vollständigkeit und Qualität. Ich habe ein Diagnoseskript geschrieben, das einige grundlegende Informationen zur Touch API-Implementierung anzeigt, einschließlich der unterstützten Ereignisse und der Auflösung zum Auslösen von Touchmove-Ereignissen. Ich habe Android 2.3.3 auf Nexus One- und Nexus S-Hardware, Android 3.0.1 auf Xoom und iOS 4.2 auf iPad und iPhone getestet.

Kurz gesagt: Alle getesteten Browser unterstützen die Ereignisse touchstart, touchend und touchmove.

Die Spezifikation enthält drei zusätzliche Touch-Ereignisse, die jedoch von keinem der getesteten Browser unterstützt werden:

  • touchenter: Ein Finger bewegt sich in ein DOM-Element.
  • touchleave: Ein Finger in Bewegung verlässt ein DOM-Element.
  • touchcancel: Eine Berührung wird unterbrochen (implementierungsspezifisch).

Innerhalb jeder Touch-Liste stellen die getesteten Browser auch die Touch-Listen touches, targetTouches und changedTouches bereit. Allerdings unterstützen keine der getesteten Browser radiusX, radiusY oder conversionAngle, die die Form des Fingers angeben, der den Bildschirm berührt.

Bei einem Touchmove werden auf allen getesteten Geräten ungefähr 60-mal pro Sekunde Ereignisse ausgelöst.

Android 2.3.3 (Nexus)

Der Android Gingerbread Browser (getestet auf Nexus One und Nexus S) bietet keine Multi-Touch-Unterstützung. Dies ist ein bekanntes Problem.

Android 3.0.1 (Xoom)

Der Xoom-Browser bietet einen grundlegenden Multi-Touch-Support, der jedoch nur mit einem einzelnen DOM-Element funktioniert. Der Browser reagiert nicht korrekt auf zwei gleichzeitige Berührungen verschiedener DOM-Elemente. Mit anderen Worten, Folgendes reagiert auf zwei gleichzeitige Berührungen:

obj1.addEventListener('touchmove', function(event) {
  for (var i = 0; i < event.targetTouches; i++) {
    var touch = event.targetTouches[i];
    console.log('touched ' + touch.identifier);
  }
}, false);

Folgendes gilt jedoch nicht:

var objs = [obj1, obj2];
for (var i = 0; i < objs.length; i++) {
  var obj = objs[i];
  obj.addEventListener('touchmove', function(event) {
    if (event.targetTouches.length == 1) {
      console.log('touched ' + event.targetTouches[0].identifier);
    }
  }, false);
}

iOS 4.x (iPad, iPhone)

iOS-Geräte unterstützen Multi-Touch vollständig, können sehr wenige Finger erfassen und bieten ein sehr reaktionsschnelles Touch-Erlebnis im Browser.

Entwicklertools

Bei der mobilen Entwicklung ist es oft einfacher, mit dem Prototyping auf dem Desktop zu beginnen und dann die mobilspezifischen Teile auf den Geräten anzugehen, die Sie unterstützen möchten. Multi-Touch ist eine dieser Funktionen, die auf dem PC schwer zu testen ist, da die meisten PCs keine Touch-Eingabe haben.

Das Testen auf Mobilgeräten kann Ihren Entwicklungszyklus verlängern, da jede Änderung auf einen Server übertragen und dann auf das Gerät geladen werden muss. Nach der Ausführung gibt es dann kaum noch etwas, was Sie tun können, um Fehler in Ihrer Anwendung zu beheben, da Tablets und Smartphones keine Webentwicklertools haben.

Eine Lösung für dieses Problem besteht darin, Touch-Ereignisse auf Ihrem Entwicklungscomputer zu simulieren. Bei Single-Touch-Ereignissen können Touch-Ereignisse auf der Grundlage von Mausereignissen simuliert werden. Multi-Touch-Ereignisse können simuliert werden, wenn Sie ein Gerät mit Berührungseingabe haben, z. B. ein modernes Apple MacBook.

Single-Touch-Ereignisse

Wenn Sie Single-Touch-Ereignisse auf Ihrem Desktop simulieren möchten, bietet Chrome die Emulation von Touch-Ereignissen über die Entwicklertools an. Öffnen Sie die Entwicklertools, wählen Sie das Zahnradsymbol für die Einstellungen und dann „Überschreibungen“ oder „Emulation“ aus und aktivieren Sie „Touch-Ereignisse emulieren“.

Probieren Sie für andere Browser möglicherweise Phantom Limb aus, das Touch-Ereignisse auf Seiten simuliert und außerdem eine riesige Hand zum Starten bietet.

Außerdem gibt es das jQuery-Plug-in Touchable, mit dem Touch- und Mausereignisse plattformübergreifend vereinheitlicht werden.

Multi-Touch-Ereignisse

Damit Ihre Multi-Touch-Webanwendung in Ihrem Browser auf Ihrem Multi-Touch-Trackpad (z. B. Apple MacBook oder MagicPad) funktioniert, habe ich den MagicTouch.js-Polyfill erstellt. Touch-Ereignisse auf Ihrem Touchpad werden erfasst und in standardkompatible Touch-Ereignisse umgewandelt.

  1. Laden Sie das npTuioClient NPAPI-Plug-in herunter und installieren Sie es unter ~/Library/Internet Plug-Ins/.
  2. Laden Sie die TongSeng TUIO App für das MagicPad auf dem Mac herunter und starten Sie den Server.
  3. Laden Sie MagicTouch.js herunter, eine JavaScript-Bibliothek, um spezifikationskompatible Touch-Ereignisse basierend auf npTuioClient-Callbacks zu simulieren.
  4. Fügen Sie das Skript magictouch.js und das npTuioClient-Plug-in wie folgt in Ihre Anwendung ein:
<head>
  ...
  <script src="/path/to/magictouch.js"></script>
</head>

<body>
  ...
  <object id="tuio" type="application/x-tuio" style="width: 0px; height: 0px;">
    Touch input plugin failed to load!
  </object>
</body>

Möglicherweise müssen Sie das Plug-in aktivieren.

Eine Live-Demo mit magictouch.js ist unter paulirish.com/demo/multi verfügbar:

Ich habe diesen Ansatz nur mit Chrome 10 getestet, aber er sollte mit nur geringfügigen Änderungen auch in anderen modernen Browsern funktionieren.

Wenn Ihr Computer keine Multi-Touch-Eingabe unterstützt, können Sie Touchereignisse mit anderen TUIO-Trackern wie reacTIVision simulieren. Weitere Informationen finden Sie auf der TUIO-Projektseite.

Beachten Sie, dass Ihre Touch-Gesten möglicherweise mit Multi-Touch-Gesten auf Betriebssystemebene identisch sind. Unter OS X können Sie systemweite Ereignisse konfigurieren, indem Sie in den Systemeinstellungen die Touchpad-Einstellungen aufrufen.

Da Multi-Touch-Funktionen in mobilen Browsern immer mehr unterstützt werden, freue ich mich, dass neue Webanwendungen diese umfassende API in vollem Umfang nutzen.