Dzisiejszy wpis jest pierwszym z dwóch, w których pokaż na czym polega obsługa ekranów dotykowych w JavaScript. W pierwszym z nich zajmę się przypadkiem podstawowym czyli zdarzaniami standardowo dostępnymi w tym języku, a w drugim… jak się być może domyślacie, przypadkiem szczególnym, a mianowicie obsługą zdarzeń dotyku w Internet Explorer… No bo przecież IE nie może robić tego tak jak inne przeglądarki… Ech;)

Zanim zacznę – prezentowane tu dziś przykłady wymagają oczywiście do działania ekranu dotykowego, więc przy próbach z myszką mogą nie działać…

Zdarzenia obsługujące dotyk

W języku JavaScript mamy dostępne trzy najbardziej podstawowe „eventy” pozwalające nam obsługiwać dotykanie ekranu przez użytkownika. Ich lista poniżej, wraz z krótkim opisem:

  • touchstart – ma miejsce w momencie gdy palec dotknie ekranu
  • touchmove – wyzwalany jest w trakcje ruchu palcem po ekranie
  • touchend – następuje kiedy użytkownik zabierze palec z ekranu

Oczywiście dociekliwi (oraz „hejterzy”) zaraz w komentarzach wytkną mi, że przecież jest ich więcej niż trzy… Rzeczywiście specyfikacja wspomina o kolejnych trzech zdarzeniach, więc o nich również wspomnę, chociaż nie będę się w nie zagłębiał. Ich obsługa w wielu przeglądarkach wygląda gorzej niż w powyższych, a i bez nich da się zrobić sporo fajnych efektów. Ich lista poniżej:

  • touchenter – wywoływany jest w momencie gdy przesuwający się palec „wjedzie” na podpięty do niego (w sensie do tego zdarzenia) element DOM
  • touchleave – odwrotność poprzedniego, czyli następuje kiedy palec opuści dany element DOM
  • touchcancel – wyzwala się w przypadku wystąpienia zakłóceń danego punktu styku (?)

Skupmy się jednak na tych trzech podstawowych „eventach” z pierwszej listy. Generalnie co do zasady, w momencie wywołania zdarzenia „touchstart”, a więc dotknięcia ekranu przez palec, tworzony jest obiekt opisujący punkt styku (ang. touch point). Każde z tych zdarzeń zawiera trzy właściwości, będące tablicami takich obiektów. Oto te kolekcje:

  • touches – lista punktów styku znajdujących się w danym momencie na ekranie (jeśli dotkniemy ekran kilkoma palcami, takich punktów jest więcej niż jeden)
  • targetTouches – lista punktów styku znajdujących się w podpiętym do danego zdarzenia elemencie DOM
  • changedTouches – najbardziej powiązana ze zdarzeniem lista, ponieważ zawiera te punkty styku, które bezpośrednio go dotyczą – na przykład dla „touchmove” będzie to lista tych punktów, które w tym momencie się poruszają

Informacje zawarte w obiekcie punktów styku

Tak jak wspomniałem, powyższe tablice zawierają obiekty punktów styku. Pora więc teraz wymienić jakie konkretnie informacje zawiera taki obiekt. Poniżej kolejna lista… tym razem najistotniejsze właściwości obiektu punktu styku:

  • identifier – unikalny identyfikator konkretnego punktu styku na ekranie
  • target – obiekt elementu DOM powiązanego ze zdarzeniem
  • trzy rodzaje współrzędnych:
    • screenX, screenY – współrzędne X i Y punktu styku względem brzegów ekranu
    • clientX, clientY – współrzędne X i Y punktu styku względem okna przeglądarki (tej jej części, która wyświetla stronę); nie biorą pod uwagę „scrolli” jeśli się pojawiają
    • pageX, pageY – współrzędne X i Y punktu styku względem dokumentu; w tym przypadku „scrolle” są brane pod uwagę
  • parametry opisujące powierzchnię styku palca z ekranem (punkt styku jest gdzieś wewnątrz tej powierzchni):
    • radiusX, radiusY – są to współrzędne elipsy tworzonej przez palec wokół punktu styku (jak wiadomo końcówka palca jest większa niż pojedynczy piksel)
    • rotationAngle – kąt wyrażony w stopniach, o jaki wspomniana wyżej elipsa musi zostać obrócona względem poziomu, by jak najlepiej pokrywać miejsce styku palca z ekranem
  • siła – wartość od 0 do 1 określająca siłę z jaką użytkownik przyciska palec do ekranu

To tyle na temat teorii dotyczącej zdarzeń dotyku w języku JavaScript. Pora na jakiś przykład, jak można z tych dobrodziejstw korzystać.

Przykład wykorzystania zdarzeń dotyku

Tyle teorii… Wydaje mi się, że najlepiej jest pokazać jak działa obsługa ekranów dotykowych w JavaScript na przykładzie. Na potrzeby tego wpisu wystarczy jak pokażę coś prostego – pierwsze co przychodzi mi do głowy to mały kwadrat, który można przesuwać palcem w obrębie większego kwadratu. Do tego celu wystarczy nam tylko jedno zdarzenie – „touchmove”. Ale po kolei, najpierw kod HTML, na którym będziemy pracować:

<div id="box1">
  <div id="box2">Przesuń</div>
</div>

Czyli tak jak napisałem wcześniej – jeden kwadrat („box1”), a w nim drugi mniejszy („box2”).

Style

Przydałoby się jeszcze zadbać o walory wizualne tego przykładu, a więc trochę CSS:

#box1 {
    width: 300px;
    height: 300px;

    border: 1px solid black;
}

#box2 {
    width: 70px;
    height: 70px;

    position: relative;

    left: 5px;
    top: 5px;

    margin: 0;

    background: lightblue;
}

Nic dodać, nic ująć – pusty biały kwadrat z obramowaniem, a w nim mały jasno niebieski kwadracik – nie ma co się rozwodzić.

Kod JavaScript

Lepiej przejść do najważniejszego, czyli kodu JavaScript, który nada temu wszystkiemu sens:

var box2 = document.getElementById('box2');

box2.addEventListener('touchmove', function(event) {
    var borderLeft = 0,
    borderRight = 300 - 70,
    borderTop = 0,
    borderBottom = 300 - 70;

    // wylaczamy scrollowanie itp.
    event.preventDefault();

    // tylko dla pojedynczego palca
    if (event.targetTouches.length == 1) {
        var touch = event.targetTouches[0];

        // ustawiamy odpowiednie style
        if (touch.pageX > borderLeft && touch.pageX < borderRight) { this.style.left = touch.pageX + 'px'; } if (touch.pageY > borderTop && touch.pageY < borderBottom) {
            this.style.top = touch.pageY + 'px';
        }
    }
}, false);

Tak to mniej więcej może wyglądać. Na początek pobieramy obiekt małego kwadratu, by następnie podpiąć go do zdarzenia „touchmove”. W funkcji ‘callback’ tego zdarzenia, na początek ustalamy granice, w jakich poruszać się będzie niebieski ruchomy kwadrat (dla uproszczenia po prostu przypisałem im odpowiednie wartości zamiast pobierać je z obiektu „box1”). W kolejnej linii, zabezpieczamy się przed „bąbelkowaniem” zdarzenia w górę aby zabezpieczyć się na przykład przed niepożądanym „scrollowaniem” całego ekranu. Później jeszcze sprawdzenie czy aby na pewno tylko jeden palec dotyka ekranu (to również uproszczenie na potrzeby przykładu) i możemy przejść już do najważniejszego czyli przesuwania kwadratu…

Jak widać jest to zrobione bardzo prosto - na początek (dla ułatwienia) przypisujemy do zmiennej pierwszy element listy „targetTouches”, który jak wiemy z poprzedniego akapitu, zawiera punkty styku znajdujące się w obiekcie „box2. Kolejna rzecz to już proste ustawienie styli na podstawie współrzędnych „pageX” i „pageY”, dbając przy okazji o to, bo nie wyjechać kwadratem za obramowanie („borderLeft”, „borderTop”, itd.).

Całość możecie przetestować, oczywiście z użyciem urządzenia z ekranem dotykowym ;) w jsfiddle - przykład z wpisu pod tym linkiem.

Obsługa ekranów dotykowych w JavaScript - podsumowanie

To tyle na dziś. Mam nadzieję, że obsługa ekranów dotykowych w JavaScript jest teraz trochę bardziej dla Ciebie jasna. Tak jak napisałem na wstępie, w Internet Explorer trzeba sobie ze zdarzeniami obsługującymi dotyk radzić trochę inaczej i o tym w niedalekiej przyszłości. Zapraszam.