Мультитач веб-разработка

Введение

Мобильные устройства, такие как смартфоны и планшеты, обычно имеют емкостный сенсорный экран, позволяющий фиксировать взаимодействие пальцев пользователя. Поскольку мобильный Интернет развивается и позволяет использовать все более сложные приложения, веб-разработчикам нужен способ обработки этих событий. Например, практически любая динамичная игра требует от игрока одновременного нажатия нескольких кнопок, что в контексте сенсорного экрана подразумевает мультитач.

Apple представила свой API событий касания в iOS 2.0. Android догоняет этот де-факто стандарт и сокращает разрыв. Недавно рабочая группа W3C собралась вместе для работы над этой спецификацией событий касания .

В этой статье я расскажу об API событий касания, предоставляемом устройствами iOS и Android, а также настольным Chrome на оборудовании, поддерживающем сенсорный ввод, и рассмотрю, какие приложения вы можете создавать, представлю некоторые лучшие практики и расскажу о полезных методах, которые упростить разработку приложений с сенсорным управлением.

Сенсорные события

В спецификации описаны три основных события касания, которые широко реализованы на мобильных устройствах:

  • touchstart : палец помещается на элемент DOM.
  • touchmove : палец перетаскивается по элементу DOM.
  • touchend : палец удаляется из элемента DOM.

Каждое событие касания включает в себя три списка касаний:

  • касания : список всех пальцев, находящихся на экране в данный момент.
  • targetTouches : список пальцев на текущем элементе DOM.
  • измененоTouches : список пальцев, участвующих в текущем событии. Например, в событии касания это будет палец, который был удален.

Эти списки состоят из объектов, содержащих сенсорную информацию:

  • идентификатор : число, которое однозначно идентифицирует текущий палец в сеансе касания.
  • target : элемент DOM, который был целью действия.
  • Координаты клиента/страницы/экрана : где на экране произошло действие.
  • Координаты радиуса и RotationAngle : описывают эллипс, который приблизительно соответствует форме пальца.

Приложения с сенсорной поддержкой

События touchstart , touchmove и touchend предоставляют достаточно богатый набор функций для поддержки практически любого вида сенсорного взаимодействия, включая все обычные мультитач-жесты, такие как масштабирование, вращение и т. д.

Этот фрагмент позволяет перетаскивать элемент DOM одним касанием:

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

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

Отслеживание пальцев.
// 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);

Демо

Ряд интересных демонстраций мультитач уже существует, например, эта демонстрация рисования на холсте Пола Айриша и других.

Скриншот рисования

И Browser Ninja , техническая демонстрация, представляющая собой клон Fruit Ninja, использующая преобразования и переходы CSS3, а также холст:

Браузерный ниндзя

Лучшие практики

Запретить масштабирование

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

Чтобы отключить масштабирование, настройте область просмотра так, чтобы она не масштабировалась пользователем, используя следующий метатег:

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

Прочтите эту статью о мобильном HTML5 для получения дополнительной информации о настройке области просмотра.

Запретить прокрутку

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

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

Тщательно визуализируйте

Если вы пишете мультитач-приложение, включающее сложные жесты несколькими пальцами, будьте осторожны с реакцией на события касания, поскольку вам придется обрабатывать очень много событий одновременно. Рассмотрим пример из предыдущего раздела, в котором отрисовываются все касания на экране. Вы можете рисовать, как только произойдет сенсорный ввод:

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

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

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

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

Используйте targetTouches и ChangeTouches.

Помните, что event.touches — это массив ВСЕХ пальцев, соприкасающихся с экраном, а не только тех, которые находятся на цели элемента DOM. Возможно, вам будет гораздо полезнее использовать вместо этого event.targetTouches или event.changedTouches.

Наконец, поскольку вы занимаетесь разработкой для мобильных устройств, вам следует знать общие передовые методы работы с мобильными устройствами, которые описаны в статье Эрика Бидельмана , а также в этом документе W3C .

Поддержка устройств

К сожалению, реализации сенсорных событий сильно различаются по полноте и качеству. Я написал диагностический скрипт , который отображает некоторую базовую информацию о реализации сенсорного API, включая поддерживаемые события и разрешение срабатывания сенсорного перемещения. Я тестировал Android 2.3.3 на устройствах Nexus One и Nexus S, Android 3.0.1 на Xoom и iOS 4.2 на iPad и iPhone.

Короче говоря, все протестированные браузеры поддерживают события touchstart , touchend и touchmove .

Спецификация предоставляет три дополнительных события касания, но ни один протестированный браузер их не поддерживает:

  • touchenter : движущийся палец входит в элемент DOM.
  • touchleave : движущийся палец покидает элемент DOM.
  • touchcancel : касание прерывается (зависит от реализации).

В каждом списке касаний протестированные браузеры также предоставляют списки касаний touches , targetTouches и измененныеTouches . Однако ни один из протестированных браузеров не поддерживает radiusX, radiusY или RotationAngle, которые определяют форму пальца, касающегося экрана.

Во время касания события возникают примерно 60 раз в секунду на всех протестированных устройствах.

Андроид 2.3.3 (Нексус)

В браузере Android Gingerbread (проверено на Nexus One и Nexus S) поддержка мультитач отсутствует. Это известная проблема .

Андроид 3.0.1 (Xoom)

В браузере Xoom есть базовая поддержка мультитач, но она работает только с одним элементом DOM. Браузер некорректно реагирует на два одновременных касания разных элементов DOM. Другими словами, на два одновременных касания будет реагировать следующее:

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

Но не будет следующего:

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)

Устройства iOS полностью поддерживают мультитач, способны отслеживать несколько пальцев и обеспечивают очень отзывчивый сенсорный интерфейс в браузере.

Инструменты разработчика

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

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

Решением этой проблемы является имитация событий касания на вашей машине разработки. Для одиночных касаний события касания можно моделировать на основе событий мыши. События мультитач можно моделировать, если у вас есть устройство с сенсорным вводом, например современный Apple MacBook.

События в одно касание

Если вы хотите имитировать события одного касания на рабочем столе, Chrome предоставляет эмуляцию событий касания с помощью инструментов разработчика. Откройте инструменты разработчика, затем выберите шестеренку «Настройки», затем «Переопределения» или «Эмуляция» и включите «Эмулировать события касания».

Для других браузеров вы можете попробовать Phantom Limb , который имитирует события касания на страницах, а также упрощает загрузку.

Существует также плагин Touchable jQuery, который унифицирует события касания и мыши на разных платформах.

Мультисенсорные события

Чтобы ваше мультитач-веб-приложение могло работать в браузере на мультитач-трекпаде (например, Apple MacBook или MagicPad), я создал полифил MagicTouch.js . Он захватывает события касания с трекпада и превращает их в стандартно-совместимые события касания.

  1. Загрузите и установите плагин npTuioClient NPAPI в ~/Library/Internet Plug-Ins/.
  2. Загрузите приложение TongSeng TUIO для Mac MagicPad и запустите сервер.
  3. Загрузите MagicTouch.js — библиотеку JavaScript для имитации совместимых со спецификациями событий касания на основе обратных вызовов npTuioClient.
  4. Включите скрипт Magictouch.js и плагин npTuioClient в свое приложение следующим образом:
<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>

Возможно, вам придется включить плагин.

Живая демо-версия Magictouch.js доступна по адресу paulirish.com/demo/multi :

Я тестировал этот подход только с Chrome 10, но с небольшими изменениями он должен работать и в других современных браузерах.

Если ваш компьютер не поддерживает мультитач-вход, вы можете имитировать события касания с помощью других трекеров TUIO, таких как reacTIVision . Более подробную информацию можно найти на странице проекта TUIO .

Обратите внимание, что ваши жесты могут быть идентичны мультитач-жестам на уровне ОС. В OS X вы можете настроить общесистемные события, перейдя на панель настроек трекпада в Системных настройках.

Поскольку функции мультитач все более широко поддерживаются в мобильных браузерах, я очень рад видеть, что новые веб-приложения в полной мере используют преимущества этого богатого API.