Wprowadzenie
Urządzenia mobilne, takie jak smartfony i tablety, mają zwykle ekrany dotykowe, które rejestrują interakcje z użytkownikiem. Wraz z rozwojem internetu mobilnego, który umożliwia tworzenie coraz bardziej zaawansowanych aplikacji, deweloperzy potrzebują sposobu na obsługę tych zdarzeń. Na przykład prawie każda dynamiczna gra wymaga od gracza jednoczesnego naciśnięcia kilku przycisków, co w kontekście ekranu dotykowego oznacza wielodotykowe sterowanie.
W iOS 2.0 Apple wprowadził interfejs API zdarzeń dotykowych. Android dogania ten standard de facto i zbliża się do niego. Niedawno grupa robocza W3C rozpoczęła pracę nad tą specyfikacją zdarzeń dotykowych.
W tym artykule omówię interfejs API zdarzeń dotykowych dostępny na urządzeniach z iOS i Androidem, a także w Chrome na komputerach z urządzeniami obsługującymi dotyk. Pokażę też, jakie aplikacje możesz tworzyć, przedstawię najlepsze praktyki i omówię przydatne techniki, które ułatwiają tworzenie aplikacji obsługujących dotyk.
Zdarzenia dotknięcia
Specyfikacja obejmuje 3 podstawowe zdarzenia dotknięcia zaimplementowane na urządzeniach mobilnych:
- touchstart: palec jest umieszczany na elemencie DOM.
- touchmove: palec jest przeciągany po elemencie DOM.
- touchend: palec zostaje usunięty z elementu DOM.
Każde zdarzenie dotyku zawiera 3 listy dotknięć:
- dotknięcia: lista wszystkich palców widocznych obecnie na ekranie.
- targetTouches: lista palców na bieżącym elemencie DOM.
- changedTouches: lista palców zaangażowanych w bieżące zdarzenie. Na przykład w przypadku zdarzenia dotknięcie końca będzie to palec, który został usunięty.
Te listy zawierają obiekty, które zawierają informacje o dotyku:
- identifier: numer, który jednoznacznie identyfikuje bieżący palec w sesji dotyku.
- target: element DOM, który był celem działania.
- koordynaty klienta/strony/ekranu: miejsce na ekranie, w którym nastąpiło działanie.
- koordynaty promienia i kąt obrotu: opisują elipsę, która przybliża kształt palca.
Aplikacje obsługujące dotyk
Zdarzenia touchstart, touchmove i touchend zapewniają wystarczająco bogaty zestaw funkcji, aby obsługiwać praktycznie dowolny rodzaj interakcji dotykowych, w tym wszystkie zwykłe gesty wielodotykowe, takie jak powiększanie przez zbliżenie palców, obracanie itp.
Ten fragment kodu pozwala przeciągnąć element DOM dookoła 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 znajduje się przykład, który pokazuje wszystkie bieżące dotknięcia ekranu. Przydaje się to tylko do oceny responsywności urządzenia.
// 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);
Prezentacje
W sieci można znaleźć wiele interesujących demonstracji obsługi wielodotykowej, takich jak rysowanie na płótnie przez Paula Irisha i innych.
Browser Ninja to techniczna prezentacja, która jest klonem Fruit Ninja korzystającym z przekształceń i przejść CSS3 oraz canvasa:
Sprawdzone metody
Zapobieganie powiększaniu
Ustawienia domyślne nie działają zbyt dobrze w przypadku urządzeń wielodotykowych, ponieważ gesty i przesunięcia są często powiązane z działaniem przeglądarki, takim jak przewijanie i powiększanie.
Aby wyłączyć powiększanie, skonfiguruj widoczny obszar tak, aby nie można było go skalować. Użyj do tego tego metatagu:
<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no>
Aby dowiedzieć się więcej o ustawianiu widoku, przeczytaj ten artykuł o HTML5 na urządzenia mobilne.
Zablokuj przewijanie
Niektóre urządzenia mobilne mają domyślne zachowania w przypadku dotyku i przesuwania, takie jak klasyczny efekt przewijania na iOS, który powoduje, że widok wraca do pozycji wyjściowej, gdy przewijanie wykracza poza granice treści. W wielu aplikacjach wielodotykowych może to być mylące, ale można to łatwo wyłączyć:
document.body.addEventListener('touchmove', function(event) {
event.preventDefault();
}, false);
Renderowanie
Jeśli piszesz aplikację wielodotykowa, która wymaga obsługi złożonych gestów wielopalcowych, uważaj, jak reagujesz na zdarzenia dotykowe, ponieważ będziesz obsługiwać wiele z nich jednocześnie. Weź pod uwagę przykład z poprzedniej sekcji, który rejestruje wszystkie dotknięcia ekranu. Możesz rysować, gdy tylko pojawi się dotyk:
canvas.addEventListener('touchmove', function(event) {
renderTouches(event.touches);
}, false);
Ta technika nie skaluje się jednak w zależności od liczby palców na ekranie. Zamiast tego możesz śledzić wszystkie palce i renderować treści w pętli, aby uzyskać dużo 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 elementów targetTouches i changedTouches
Pamiętaj, że event.touches to tablica WSZYSTKICH palców stykających się z ekranem, a nie tylko tych na elemencie DOM. Może się okazać, że znacznie przydatniejsze będzie użycie event.targetTouches lub event.changedTouches.
Ponieważ zajmujesz się tworzeniem aplikacji mobilnych, musisz znać ogólne sprawdzone metody dotyczące urządzeń mobilnych, które omawiane są w artykule Erica Bidelmana oraz w tym dokumencie W3C.
Obsługa urządzeń
Niestety implementacje zdarzeń dotykowych różnią się znacznie pod względem kompletności i jakości. Napisałem skrypt diagnostyczny, który zawiera podstawowe informacje o implementacji interfejsu Touch API, m.in. listę obsługiwanych zdarzeń i rozdzielczość uruchamiania funkcji Touchmove. Przetestowałem Androida 2.3.3 na Nexusie One i Nexusie S, Androidzie 3.0.1 na Xoom oraz iOS 4.2 na iPadzie i iPhonie.
Krótko mówiąc, wszystkie testowane przeglądarki obsługują zdarzenia touchstart, touchend i touchmove.
Specyfikacja obejmuje 3 dodatkowe zdarzenia dotyku, ale żadna z testowanych przeglądarek ich nie obsługuje:
- touchenter: palec przesuwa się na element DOM.
- touchleave: palec przesuwa się poza element DOM.
- touchcancel: dotyk został przerwany (w zależności od implementacji).
W ramach każdej listy dotyku przetestowane przeglądarki udostępniają również listy kontaktów, targetTouches i changedTouches. Żadna z przetestowanych przeglądarek nie obsługuje parametrów radiusX, radiusY ani rotationAngle, które określają kształt palca dotykającego ekranu.
Podczas dotykania i przesuwania palcem na wszystkich testowanych urządzeniach zdarzenia są wywoływane średnio 60 razy na sekundę.
Android 2.3.3 (Nexus)
Przeglądarka Gingerbread na Androida (testowana na Nexusach One i Nexus S) nie obsługuje funkcji wielodotyku. To znany problem.
Android 3.0.1 (Xoom)
W przeglądarce Xoom dostępna jest podstawowa obsługa wielodotyku, ale działa ona tylko z jednym elementem DOM. Przeglądarka nie reaguje prawidłowo na 2 jednoczesne dotknięcia różnych elementów DOM. Inaczej mówiąc, na te elementy zareagujesz, dotykając je 2 razy jednocześnie:
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 spowoduje to 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ą wielodotykowe interfejsy, są w stanie śledzić ruchy wielu palców i zapewniają bardzo responsywną obsługę dotykiem w przeglądarce.
Narzędzia dla programistów
W przypadku programowania na urządzenia mobilne często łatwiej jest utworzyć prototyp na komputerze, a następnie zająć się częściami przeznaczonymi na urządzenia mobilne, które mają być obsługiwane. Wielodotykowe sterowanie to jedna z funkcji, które trudno jest przetestować na komputerze, ponieważ większość komputerów nie ma ekranu dotykowego.
Testowanie na urządzeniach mobilnych może wydłużyć cykl programowania, ponieważ każda wprowadzona zmiana musi zostać przesłana na serwer, a następnie załadowana na urządzenie. Gdy aplikacja jest uruchomiona, trudno jest ją debugować, ponieważ tablety i smartfony nie mają narzędzi dla programistów internetowych.
Rozwiązaniem tego problemu jest symulowanie zdarzeń dotyku na maszynie do testów. W przypadku pojedynczego dotknięcia zdarzenia dotyku można symulować na podstawie zdarzeń myszy. Jeśli masz urządzenie z ekranem dotykowym, np. nowy MacBook firmy Apple, możesz symulować zdarzenia wielodotykowe.
Zdarzenia dotknięcia
Jeśli chcesz symulować zdarzenia jednodotykowe na komputerze, Chrome udostępnia emulację zdarzeń dotykowych w narzędziach dla programistów. Otwórz Narzędzia dla programistów, kliknij ikonę ustawień (koło zębate), „Zastąpienia” lub „Emulacja” i włącz opcję „Emuluj zdarzenia dotknięcia”.
W przypadku innych przeglądarek możesz wypróbować Phantom Limb, który symuluje zdarzenia dotykowe na stronach i zawiera też ogromną rękę.
Dostępna jest też wtyczka jQuery Touchable, która umożliwia ujednolicenie zdarzeń dotyku i myszy na różnych platformach.
Zdarzenia wielodotykowe
Aby umożliwić działanie aplikacji internetowej wielodotykowej w przeglądarce na trackpadzie wielodotykowym (np. Apple MacBook lub MagicPad), stworzyłem polyfill MagicTouch.js. rejestruje zdarzenia dotyku z touchpada i przekształca je w zgodnie ze standardem zdarzenia dotyku.
- Pobierz i zainstaluj wtyczkę npTuioClient NPAPI w ~/Library/Internet Plug-Ins/.
- Pobierz aplikację TongSeng TUIO na tablet MagicPad na Macu i uruchom serwer.
- Pobierz MagicTouch.js, bibliotekę JavaScriptu, która symuluje zgodne ze specyfikacją zdarzenia dotyku na podstawie wywołań zwrotnych npTuioClient.
- Dodaj do aplikacji skrypt magictouch.js i wtyczkę npTuioClient w następujący 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>
Może być konieczne włączenie wtyczki.
Prezentacja na żywo wykorzystująca magictouch.js jest dostępna na stronie paulirish.com/demo/multi:
Testowałem to podejście tylko w przypadku Chrome 10, ale powinno ono działać w innych nowoczesnych przeglądarkach po wprowadzeniu drobnych poprawek.
Jeśli Twój komputer nie ma obsługi wielodotykowej, możesz symulować zdarzenia dotyku za pomocą innych trackerów TUIO, takich jak reacTIVision. Więcej informacji znajdziesz na stronie projektu TUIO.
Pamiętaj, że gesty mogą być identyczne z gestami wielodotykowymi na poziomie systemu operacyjnego. W OS X możesz skonfigurować zdarzenia systemowe w Preferencjach systemowych w panelu ustawień trackpada.
Cieszę się, że nowe aplikacje internetowe w pełni wykorzystują ten bogaty interfejs API, ponieważ coraz więcej funkcji obsługujemy w przeglądarkach mobilnych.