Wskazywanie drogi naprzód

Sérgio Gomes

Kiedyś wskazanie rzeczy w internecie było proste. Miała mysz, została poruszona czasem trzeba było naciskać przyciski. Wszystko, co nie było był emulowany jako jeden, a programiści wiedzieli, na co zwracać uwagę.

Prostota nie zawsze musi być jednak dobra. Z czasem staje się coraz bardziej Ważne, by nie wszystko, co jest (lub udawało) mysz. długopisy z możliwością przechylenia i odporności na nacisk zapewniają niezwykłą swobodę twórczą; możesz używać palców, więc potrzebne były tylko urządzenie i ręka. a dlaczego nie używać więcej niż jednego palca,

Mieliśmy już zdarzenia dotykowe aby nam w tym pomóc, ale są to zupełnie odrębne interfejsy API. specjalnie dla dotyku, co zmusza do kodowania dwóch oddzielnych modeli zdarzeń, jeśli chcesz obsługiwać zarówno mysz, jak i dotyk. Chrome 55 jest udostępniany z nowszym standardem ujednolica oba modele: zdarzenia wskaźnika.

Model pojedynczego zdarzenia

Zdarzenia wskaźnika łączą wartości model danych wejściowych wskaźnika dla przeglądarki, który łączy dotyk, długopisy i myszy w jeden zbiór zdarzeń. Na przykład:

document.addEventListener('pointermove',
    ev => console.log('The pointer moved.'));
foo.addEventListener('pointerover',
    ev => console.log('The pointer is now over foo.'));

Oto lista wszystkich dostępnych zdarzeń. Zdarzenia powinny wyglądać dobrze, jeśli: albo wiesz, czym są zdarzenia myszy:

pointerover Wskaźnik znalazł się w ramce ograniczającej elementu. Na urządzeniach obsługujących najechanie kursorem lub przed Zdarzenie pointerdown w przypadku urządzeń, które go nie używają.
pointerenter Podobne do pointerover, ale nie zawiera bąbelków ani uchwytów w inny sposób. Szczegóły specyfikacji
pointerdown Wskaźnik przeszedł w stan aktywnego przycisku, a jeden z nich naciśnięcie lub nawiązanie kontaktu, w zależności od semantyki elementu urządzenia wejściowego.
pointermove Wskaźnik zmienił się w pozycji.
pointerup Wskaźnik opuścił aktywny przycisk.
pointercancel Wystąpił problem i jest mało prawdopodobne, że wskaźnik wyemituje żadne wydarzeń. Oznacza to, że należy anulować wszystkie trwające działania i przejść dalej z powrotem do neutralnego stanu danych wejściowych.
pointerout Wskaźnik opuścił ramkę ograniczającą elementu lub ekranu. Także po pointerup, jeśli urządzenie nie obsługuje najeżdżania kursorem.
pointerleave Podobne do pointerout, ale nie zawiera bąbelków ani uchwytów w inny sposób. Szczegóły specyfikacji
gotpointercapture Element został przechwycony wskaźnikiem.
lostpointercapture Przechwycony wskaźnik został został zwolniony.

Różne typy danych wejściowych

Ogólnie zdarzenia wskaźnika umożliwiają pisanie kodu w sposób niezależny od danych wejściowych, bez konieczności rejestrowania osobnych modułów obsługi zdarzeń dla różnych urządzeń wejściowych. Musisz oczywiście pamiętać o różnicach między typami danych wejściowych, np. o tym, obowiązuje koncepcja najechania kursorem. Jeśli chcesz rozróżnić różne typy urządzeń wejściowych – np. aby dla różnych danych wejściowych – możesz jednak to zrobić w ramach tych samych modułów obsługi zdarzeń za pomocą właściwości pointerType funkcji PointerEvent. za pomocą prostego interfejsu online. Na przykład jeśli kodujesz boczny panel nawigacji, możesz w zdarzeniu pointermove zastosuj te funkcje logiczne:

switch(ev.pointerType) {
    case 'mouse':
    // Do nothing.
    break;
    case 'touch':
    // Allow drag gesture.
    break;
    case 'pen':
    // Also allow drag gesture.
    break;
    default:
    // Getting an empty string means the browser doesn't know
    // what device type it is. Let's assume mouse and do nothing.
    break;
}

Działania domyślne

W przeglądarkach obsługujących dotyk niektóre gesty są używane do przewijania, powiększania i odświeżania strony. W przypadku zdarzeń dotknięcia będziesz nadal otrzymywać zdarzenia, gdy te domyślne wykonywanych czynności – na przykład podczas przewijania strony użytkownik touchmove zostanie wywołany.

W przypadku zdarzeń wskaźnika po wywołaniu domyślnego działania, takiego jak przewijanie lub powiększanie, wyświetli się zdarzenie pointercancel z informacją, że przeglądarka nad wskaźnikiem. Na przykład:

document.addEventListener('pointercancel',
    ev => console.log('Go home, the browser is in charge now.'));

Wbudowana szybkość: ten model domyślnie pozwala na lepszą wydajność, w porównaniu ze zdarzeniami dotknięcia, w których trzeba użyć pasywne detektory zdarzeń aby osiągnąć taki sam poziom reakcji.

Można uniemożliwić przeglądarce przejęcie kontroli przy użyciu touch-action właściwość CSS. Ustawienie wartości none w elemencie spowoduje wyłączenie wszystkich określone przez przeglądarkę działania dotyczące tego elementu. Istnieje jednak wiele wersji inne wartości umożliwiające bardziej precyzyjną kontrolę, takie jak pan-x, pozwalające na przeglądarka reaguje na ruch na osi X, ale nie na osi Y. Chrome 55 obsługuje następujące wartości:

auto Domyślne; przeglądarka może wykonać dowolne działanie domyślne.
none Przeglądarka nie ma uprawnień do wykonywania żadnych domyślnych działań.
pan-x Przeglądarka może wykonywać tylko domyślne działanie przewijania w poziomie.
pan-y Przeglądarka może wykonywać tylko domyślne działanie przewijania w pionie.
pan-left Przeglądarka może wykonywać tylko domyślne działanie przewijania w poziomie, i przesuwać stronę w lewo.
pan-right Przeglądarka może wykonywać tylko domyślne działanie przewijania w poziomie, i przesuwać stronę w prawo.
pan-up Przeglądarka może wykonywać tylko domyślne działanie przewijania w pionie, i przesuwać stronę w górę.
pan-down Przeglądarka może wykonywać tylko domyślne działanie przewijania w pionie, i przesuwać stronę w dół.
manipulation Przeglądarka może wykonywać tylko działania związane z przewijaniem i powiększaniem.

Przechwytywanie wskaźnika

Zdarzyło Ci się spędzić frustrującą godzinę na debugowaniu uszkodzonego mouseup zdarzenia, aż do stwierdzenia, że użytkownik puszcza przycisk, poza docelową liczbą kliknięć? Nie? No dobrze, może tylko ja.

Do tej pory jednak nie mieliśmy zbyt dobrego sposobu na rozwiązanie tego problemu. Jasne, można skonfigurować moduł obsługi mouseup w dokumencie i zapisać stan w Twojej aplikacji. Nie jest to najczystsze rozwiązanie, zwłaszcza jeśli tworzysz komponent internetowy i chcesz, aby wszystko izolowane.

Znacznie lepszym rozwiązaniem są zdarzenia wskaźników: możesz przechwycić wskaźnik, aby na pewno uzyskać dostęp do zdarzenia pointerup (lub jakiegokolwiek innego znajomych).

const foo = document.querySelector('#foo');
foo.addEventListener('pointerdown', ev => {
    console.log('Button down, capturing!');
    // Every pointer has an ID, which you can read from the event.
    foo.setPointerCapture(ev.pointerId);
});

foo.addEventListener('pointerup', 
    ev => console.log('Button up. Every time!'));

Obsługa przeglądarek

W chwili pisania zdarzenia wskaźnika są obsługiwane w przeglądarce Internet Explorer 11, Microsoft Edge, Chrome i Opera, a częściowo obsługiwana w przeglądarce Firefox. Dostępne opcje Zapoznaj się z aktualną listą produktów na stronie caniuse.com.

Do i wypełniam luki. Sprawdzanie obsługi przeglądarki w czasie działania jest też proste:

if (window.PointerEvent) {
    // Yay, we can use pointer events!
} else {
    // Back to mouse and touch events, I guess.
}

Zdarzenia typu wskaźnik doskonale nadają się do stopniowego ulepszania: zmodyfikuj swoje metody inicjowania, aby sprawdzić powyżej, dodaj zdarzenie wskaźnika w bloku if i przenieś moduły obsługi zdarzeń myszy/dotyku do modułu Blokada: else.

Wypróbuj go i podziel się z nami swoją opinią.