Как работать с тачскрином в JavaScript

Если вы ещё не оптимизировали свои сайты под мобильные устройства — пора это исправить. Рассказываем, что нужно сделать.

Практически все сайты хорошо адаптированы для работы с компьютерной мышью: мы можем кликать левой и правой кнопками, скролить, двигать курсор и так далее. Для этого разработчикам даже не приходится ничего делать — такие задачи берёт на себя браузер.

Ситуация с сенсорными экранами хоть и не печальная, но всё же далека от идеала.

Евгений Кучерявый

Пишет о программировании, в свободное время создает игры. Мечтает открыть свою студию и выпускать ламповые RPG.


Как работать с тачскринами

Есть четыре основных события, которые помогут адаптировать сайт для мобильных устройств с сенсорными экранами:

  • touchstart — начало касания, пользователь нажал на экран;
  • touchmove — пользователь двигает пальцем по экрану;
  • touchend — пользователь отпустил экран;
  • touchcancel — отмена касания. Это событие срабатывает, если пользователь заходит за край страницы, переворачивает экран, сворачивает браузер и так далее.

Информация о касаниях находится в параметре changedTouches объекта event. changedTouches — это массив, в котором хранится информация обо всех текущих касаниях, что позволяет обрабатывать нажатия несколькими пальцами.

В этой статье мы напишем интерфейс для сайта, который может реагировать на все четыре события, а также определяет, в каком направлении свайпает пользователь.

Вёрстка страницы

Перечисленные выше события можно ловить на любом элементе или на всём окне сразу. Но чтобы работа скрипта была более наглядной, мы создадим холст (canvas), на который будем выводить действия пользователя.

Для начала напишем код самой страницы:

<!DOCTYPE html>
<html>
    <head>
   	 <title>Touches</title>
   	 <meta charset="utf-8">
   	 <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' />
   	 <meta name="apple-mobile-web-app-capable" content="yes">
   	 <meta name="mobile-web-app-capable" content="yes">
   	 <meta name="HandheldFriendly" content="true"/>
   	 <link rel="stylesheet" type="text/css" href="/touches/styles/app.css">
    </head>
    <body>
   	 <div class="wrapper">
   		 <canvas width="300" height="300" id="canvas" class="canvas"></canvas>
   	 </div>
   	 <div class="info">
   		 <div class="info__content">
   			 <b>Last action: </b> <span id="msg-box"></span>
   		 </div>
   	 </div>
   	 <script type="text/javascript" src="/touches/scripts/app.js"></script>
    </body>
</html>

Теперь добавим немного стилей:

body, html
{
    width: 100%;
    height: 100%;
    padding: 0;
    margin: 0;
    font-size: 16px;
    font-family: arial;
    background: #f7f7f7;
    color: #373737;
}

.wrapper
{
    width: 100%;
}

.canvas
{
    background: #fff;
    width: 100%;
    height: 100%;
    position: fixed;
    top: 0;
    left: 0;
    margin: 0;
}

.info
{
    position: fixed;
    bottom: 0;
    left: 0;
    background: #fff;
}

.info__content
{
    padding: 5px;
}

Добавим небольшой скрипт, который будет следить, чтобы размер холста всегда соответствовал размеру экрана.

InitApp(); //Инициализировать приложение

window.addEventListener("resize", InitApp); //При растягивании окна приложение будет инициализироваться заново

function InitApp() //Растягиваем холст на весь экран
{
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
}

Сайт готов к началу работы, остаётся только включить симулятор событий тачскрина.

Для этого откройте в своём браузере консоль (по умолчанию F12) и найдите режим имитации различных размеров экрана (по умолчанию Ctrl + Shift + M), а затем запустите симуляцию тачскрина. Теперь нажатия мышью будут восприниматься браузером как нажатия на сенсорный экран.

Пример из Mozilla Firefox

Написание скрипта

Для работы с сенсорным экраном напишем несколько функций:

  • TouchStart() — срабатывает при начале касания, сохраняет стартовую позицию.
  • TouchMove() — срабатывает при движении, сохраняет новую позицию.
  • TouchEnd() — очищает информацию о стартовой и текущей позициях.
  • CheckAction() — проверяет, соответствуют ли движения пользователя по экрану какому-нибудь жесту. В нашем случае — свайпу.

Также будут две вспомогательные функции:

  • Draw() — рисует точку на текущей позиции.
  • DrawLine() — рисует линию между стартовой и конечной позициями.

Можем приступать:

//Получение холста и его контекста
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

//Чувствительность — количество пикселей, после которого жест будет считаться свайпом
const sensitivity = 20;

//Получение поля, в котором будут выводиться сообщения
const msgBox = document.getElementById("msg-box");

var touchStart = null; //Точка начала касания
var touchPosition = null; //Текущая позиция

//Перехватываем события
canvas.addEventListener("touchstart", function (e) { TouchStart(e); }); //Начало касания
canvas.addEventListener("touchmove", function (e) { TouchMove(e); }); //Движение пальцем по экрану
//Пользователь отпустил экран
canvas.addEventListener("touchend", function (e) { TouchEnd(e, "green"); });
//Отмена касания
canvas.addEventListener("touchcancel", function (e) { TouchEnd(e, "red"); });

function TouchStart(e)
{
    //Получаем текущую позицию касания
    touchStart = { x: e.changedTouches[0].clientX, y: e.changedTouches[0].clientY };
    touchPosition = { x: touchStart.x, y: touchStart.y };

    Draw(touchPosition.x, touchPosition.y, 6, "blue"); //Рисуем точку начала касания
}

function TouchMove(e)
{
    //Получаем новую позицию
    touchPosition = { x: e.changedTouches[0].clientX, y: e.changedTouches[0].clientY };
    Draw(touchPosition.x, touchPosition.y, 2); //Рисуем точку текущей позиции
}

function TouchEnd(e, color)
{
    DrawLine(); //Рисуем линию между стартовой и конечной точками
    Draw(touchPosition.x, touchPosition.y, 6, color); //Рисуем конечную точку

    CheckAction(); //Определяем, какой жест совершил пользователь

    //Очищаем позиции
    touchStart = null;
    touchPosition = null;
}

function CheckAction()
{
    var d = //Получаем расстояния от начальной до конечной точек по обеим осям
    {
   	 x: touchStart.x - touchPosition.x,
   	 y: touchStart.y - touchPosition.y
    };

    var msg = ""; //Сообщение

    if(Math.abs(d.x) > Math.abs(d.y)) //Проверяем, движение по какой оси было длиннее
    {
   	 if(Math.abs(d.x) > sensitivity) //Проверяем, было ли движение достаточно длинным
   	 {
   		 if(d.x > 0) //Если значение больше нуля, значит пользователь двигал пальцем справа налево
   		 {
   			 msg = "Swipe Left";
   		 }
   		 else //Иначе он двигал им слева направо
   		 {
   			 msg = "Swipe Right";
   		 }
   	 }
    }
    else //Аналогичные проверки для вертикальной оси
    {
   	 if(Math.abs(d.y) > sensitivity)
   	 {
   		 if(d.y > 0) //Свайп вверх
   		 {
   			 msg = "Swipe up";
   		 }
   		 else //Свайп вниз
   		 {
   			 msg = "Swipe down";
   		 }
   	 }
    }

    msgBox.innerText = msg; //Выводим сообщение

}

function Draw(x, y, weight, color = "#000") //Функция рисования точки
{
    ctx.fillStyle = color;

    let weightHalf = weight / 2;

    ctx.fillRect(x - weightHalf, y - weightHalf, weight, weight);
}

function DrawLine() //Функция рисования линии
{
    ctx.strokeStyle = "#ccc";

    ctx.beginPath();

    ctx.moveTo(touchStart.x, touchStart.y);
    ctx.lineTo(touchPosition.x, touchPosition.y);

    ctx.stroke();
}

Проверяем, как это всё работает:

Теперь в ответ на какой-нибудь жест пользователя мы можем выполнять различные манипуляции с интерфейсом. Например, большинство пользователей привыкло, что свайп слева направо открывает меню сайта.

Заключение

С помощью JavaScript можно обрабатывать разнообразные жесты. Несмотря на то что по умолчанию есть только четыре основных события, мы можем вручную прописать и другие движения, по аналогии с этими свайпами.

Особенно хорошо это работает, если обрабатывать сразу несколько касаний. Так, например, для определённых жестов можно прописать логику изменения масштаба или вращения.

Всё это можно реализовать самостоятельно или использовать уже существующие фреймворки. Некоторые из них перечислены в этой статье.

Кроме того, научиться создавать интерфейсы не только для компьютеров, но и для мобильных устройств вы можете на нашем курсе «Frontend-разработчик».

Курс

Профессия
Frontend-разработчик


Вы научитесь верстать сайты и создавать интерфейсы, а также соберёте два проекта в портфолио и получите современную профессию. После прохождения обучения — гарантированное трудоустройство.

Хочешь получать крутые статьи по программированию?
Подпишись на рассылку Skillbox