Tworzenie stron internetowych obsługujących płatności wielodotykowe

Wprowadzenie

Urządzenia mobilne, takie jak smartfony i tablety, są zwykle wyposażone w ekran dotykowy do rejestrowania interakcji z palcami użytkownika. Internet mobilny ewoluuje, aby umożliwiać coraz bardziej zaawansowane aplikacje, dlatego programiści potrzebują sposobów na radzenie sobie z tymi wydarzeniami. Na przykład w niemal każdej grze o dynamicznym tempie gracz musi nacisnąć wiele przycisków naraz, co w kontekście ekranu dotykowego oznacza obsługę wielodotyku.

Firma Apple wprowadziła interfejs touch events API w iOS 2.0. Android dotrzymuje kroku temu standardowemu standardowi i łączy z nimi tę lukę. Niedawno grupa robocza W3C pracowała nad tą specyfikacją zdarzeń dotknięcia.

W tym artykule omówię interfejs API zdarzeń dotykowych dostępny na urządzeniach z iOS i Androidem oraz komputerowy Chrome na sprzęcie obsługującym dotyk. Omówię też rodzaje aplikacji, które można tworzyć, przedstawię sprawdzone metody oraz przydatne techniki ułatwiające tworzenie aplikacji z obsługą dotykową.

Zdarzenia dotknięcia

Specyfikacja obejmuje 3 podstawowe zdarzenia dotyku, które są powszechnie zaimplementowane na urządzeniach mobilnych:

  • touchstart: palec jest umieszczany na elemencie DOM.
  • touchmove: przeciąganie palcem wzdłuż elementu DOM.
  • touchend: usuwa palec z elementu DOM.

Każde zdarzenie dotknięcia obejmuje 3 listy dotknięć:

  • dotknięcia: lista wszystkich palców obecnie widocznych na ekranie.
  • targetTouches: lista palców na bieżącym elemencie DOM.
  • changedTouches: lista palców biorących udział w bieżącym zdarzeniu. W przypadku zdarzenia dotykowego jest to na przykład usunięty palec.

Listy te składają się z obiektów zawierających dane dotykowe:

  • identifier: liczba jednoznacznie identyfikująca bieżący palec w sesji dotykowej.
  • target: element DOM będący celem działania.
  • współrzędne klienta/strony/ekranu: miejsce na ekranie, w którym wystąpiła akcja.
  • współrzędne promieniowe i kąt obrotu: podaj elipsę określającą kształt palca.

Aplikacje obsługujące dotyk

Zdarzenia touchstart, touchmove i touchend udostępniają wystarczająco obszerny zestaw funkcji, aby obsługiwać praktycznie każdy rodzaj interakcji dotykiem, w tym wszystkie zwykłe gesty polegające na dotknięciu palcami, takie jak ściągnięcie czy rozsunięcie palców czy obrót.

Ten fragment umożliwia przeciąganie elementu DOM jednym palcem:

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);

Poniżej znajdziesz przykład, który przedstawia wszystkie dotknięcia ekranu. Warto tylko sprawdzić, jak reaguje urządzenie.

Śledzenie palca.
// 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);

Przykłady

Dostępnych jest już wiele interesujących prezentacji interaktywnych, takich jak rysowanie na płótnie autorstwa Paula Irelanda i innych twórców.

Zrzut ekranu z rysunkiem

Z kolei Browser Ninja, czyli klon Fruit Ninja, który korzysta z przekształceń i przejść CSS3 oraz ma kanw na płótnie:

Ninja przeglądarki

Sprawdzone metody

Zapobiegaj powiększaniu

W przypadku obsługi wielodotykowej ustawienia domyślne nie sprawdzają się zbyt dobrze, ponieważ przesuwania i gesty są często powiązane z działaniem przeglądarki, np. przewijaniem i powiększaniem.

Aby wyłączyć powiększanie, skonfiguruj widoczny obszar tak, aby nie był skalowalny dla użytkowników, korzystając z tego metatagu:

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

Więcej informacji o ustawianiu widocznego obszaru znajdziesz w tym artykule na temat mobilnego HTML5.

Zapobiegaj przewijaniu

Niektóre urządzenia mobilne mają domyślny sposób działania przesuwania dotykiem, np. klasyczny efekt dalekiego przewijania w systemie iOS, który powoduje, że widok cofa się, gdy przewijanie przekracza granicę treści. Jest to mylące w wielu aplikacjach obsługujących różne interakcje i można je łatwo wyłączyć:

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

Starannie renderuj

Jeśli piszesz aplikację wielodotykową, która obejmuje złożone gesty wymagające użycia wielu palców, zachowaj ostrożność w reagowaniu na zdarzenia dotknięcia, ponieważ będzie się obsługiwać wiele takich gestów naraz. Przyjrzyjmy się próbce z poprzedniej sekcji, w której widoczne są wszystkie dotknięcia ekranu. Możesz zacząć rysować, gdy tylko pojawi się ekran dotykowy:

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

Ta technika nie jest jednak skalowana odpowiednio do liczby palców na ekranie. Możesz zamiast tego śledzić wszystkie palce i renderować w pętli, aby uzyskać znacznie lepsze wyniki:

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

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

Korzystanie z dotknięcia docelowego i zmiany Touches

Pamiętaj, że event.touches to tablica WSZYSTKICH palców w kontaktach z ekranem, a nie tylko tych z miejscem docelowym elementu DOM. Zdecydowanie lepszym rozwiązaniem może być użycie parametru event.targetTouches lub event.changedTouches.

Ponieważ Twoja aplikacja jest przeznaczona na urządzenia mobilne, zapoznaj się z ogólnymi sprawdzonymi metodami, które zostały omówione w artykule Erica Bidelmana oraz w tym dokumencie organizacji W3C.

Pomoc dotycząca urządzenia

Niestety implementacje zdarzeń kliknięcia różnią się znacznie pod względem kompletności i jakości. Udało mi się utworzyć skrypt diagnostyczny, który wyświetla podstawowe informacje o implementacji interfejsu Touch API, m.in. o obsługiwanych zdarzeniach i rozdzielczości uruchamiania przesuwania dotykiem. Przetestowałem Androida 2.3.3 na sprzęcie Nexus One i Nexus S, Androida 3.0.1 na Xoom oraz iOS 4.2 na iPadzie i iPhonie.

Ogólnie rzecz biorąc, wszystkie testowane przeglądarki obsługują zdarzenia touchstart, touchend i touchmove.

Specyfikacja podaje 3 dodatkowe zdarzenia kliknięcia, ale żadnej z przetestowanych przeglądarek ich nie obsługuje:

  • touchenter: ruchomy palec wchodzi w element DOM.
  • touchmove: poruszający się palec opuszcza element DOM.
  • touchcancel: kliknięcie jest przerywane (dotyczy konkretnej implementacji).

W ramach każdej listy dotknięć testowane przeglądarki udostępniają też listy dotykowe dotknięć, targetTouch i changedTouch. Jednak żadna z testowanych przeglądarek nie obsługuje formatów radiusX, radiusY i vertAngle, które określają kształt palca dotykanego ekranu.

Podczas ruchu dotykowego na wszystkich testowanych urządzeniach zdarzenia są wywoływane około 60 razy na sekundę.

Android 2.3.3 (Nexus)

W przeglądarce Android Gingerbread Browser (testowanej na Nexusie One i Nexusie S) nie obsługujemy obsługi wielodotykowej. Jest to znany problem.

Android 3.0.1 (Xoom)

W przeglądarce Xoom dostępna jest podstawowa obsługa wielodotyku, ale działa tylko na pojedynczym elemencie DOM. Przeglądarka nie reaguje prawidłowo na 2 jednoczesne dotknięcia różnych elementów DOM. Inaczej mówiąc, na 2 jednoczesne dotknięcia będą reagowały następujące elementy:

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

Nie będą jednak:

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)

Urządzenia z iOS w pełni obsługują wielodotyk, potrafią śledzić sporo palców i bardzo szybko reagują na dotyk w przeglądarce.

Narzędzia dla programistów

W przypadku programowania na urządzenia mobilne często łatwiej jest zacząć tworzyć prototypy na komputerze, a potem zająć się częściami przeznaczonymi dla urządzeń mobilnych na urządzeniach, które mają być obsługiwane. Obsługa wielodotyku to jedna z tych funkcji, którą trudno jest przetestować na PC, ponieważ większość komputerów nie ma dotyku.

Testowanie na urządzeniach mobilnych może wydłużyć cykl programowania, ponieważ każda wprowadzana zmiana musi zostać przekazana na serwer, a następnie wczytana na urządzeniu. Po uruchomieniu niewiele da się już zdebugować, ponieważ na tabletach i smartfonach nie ma narzędzi dla programistów stron internetowych.

Rozwiązaniem tego problemu jest symulowanie zdarzeń dotknięcia na komputerze do programowania. W przypadku dotknięcia jednym dotknięciem zdarzenia dotknięcia mogą być symulowane na podstawie zdarzeń myszy. Zdarzenia polegające na dotyku można symulować, jeśli masz urządzenie z dotykowym wprowadzaniem danych, np. nowoczesny komputer Apple MacBook.

Zdarzenia polegające na jednym kliknięciu

Jeśli chcesz symulować takie zdarzenia na komputerze, Chrome udostępnia w narzędziach dla programistów emulację zdarzeń dotyku. Otwórz Narzędzia dla programistów, kliknij kolejno koło zębate Ustawienia, „Zastąpienia” lub „Emulacja” i włącz „Emuluj zdarzenia dotknięcia”.

W innych przeglądarkach możesz wypróbować aplikację Phantom Limb, która symuluje zdarzenia dotknięcia na stronach i uruchamia olbrzymią dłoń.

Dostępna jest też wtyczka Touchable w języku jQuery, która ujednolica zdarzenia kliknięcia i myszy na różnych platformach.

Zdarzenia uwzględniające wielodotyk

Aby umożliwić działanie aplikacji internetowej wielodotykowej w przeglądarce na trackpadzie wielodotykowym (np. na urządzeniu Apple MacBook lub MagicPad), utworzyliśmy kod polyfill MagicTouch.js. Rejestruje zdarzenia dotyku z trackpada i przekształca je w zgodne ze standardami zdarzenia dotyku.

  1. Pobierz wtyczkę npTuioClient NPAPI i zainstaluj ją w ~/Library/Internet Plug-Ins/.
  2. Pobierz aplikację TongSeng TUIO na urządzenie MagicPad na Macu i uruchom serwer.
  3. Pobierz MagicTouch.js, bibliotekę JavaScript, aby symulować zgodne ze specyfikacją zdarzenia kliknięcia na podstawie wywołań zwrotnych npTuioClient.
  4. Dodaj do aplikacji skrypt magictouch.js i wtyczkę npTuioClient w ten sposób:
<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>

Konieczne może być włączenie wtyczki.

Na stronie paulirish.com/demo/multi dostępna jest wersja demonstracyjna na żywo wykorzystująca magictouch.js:

Ta metoda była testowana tylko w Chrome 10, ale powinna działać w innych nowoczesnych przeglądarkach z niewielkimi poprawkami.

Jeśli Twój komputer nie jest wyposażony w tryb wielodotykowy, możesz symulować zdarzenia dotknięcia za pomocą innych lokalizatorów TUIO, np. reacTIVision. Więcej informacji znajdziesz na stronie projektu TUIO.

Pamiętaj, że gesty mogą być takie same jak na poziomie systemu operacyjnego. W OS X możesz konfigurować zdarzenia systemowe, otwierając panel ustawień trackpada w Preferencjach systemowych.

Ponieważ funkcje wielodotykowe są coraz częściej obsługiwane w przeglądarkach mobilnych, cieszę się, że nowe aplikacje internetowe w pełni wykorzystują możliwości tego multimedialnego interfejsu API.