Разработка мультисенсорных веб-приложений

HTML5 Rocks

Введение

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

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

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

События касания

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

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

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

  • touches: список всех точек соприкосновения пальцев с экраном.
  • targetTouches: список всех точек соприкосновения с текущим элементом DOM.
  • changedTouches: список всех точек соприкосновения, участвующих в текущем событии. Например, в случае события touchend это будет точка, в которой пользователь убрал палец с экрана.
Эти списки состоят из объектов, содержащих сведения о касании.
  • identifier: уникальное число, определяющее текущую точку в рамках сеанса касания.
  • 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 и элемент canvas:

Рекомендации

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

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

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

<meta name="viewport" 
  content="width=device-width, initial-scale=1.0, user-scalable=no">
В этой статье о HTML5 для мобильных приложений можно найти дополнительную информацию о настройке области просмотра.

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

В некоторых мобильных устройствах для события touchmove задано поведение по умолчанию. Примером является известный эффект прокрутки в 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);

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

Эффективное использование списков targetTouches и changedTouches

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

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

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

К сожалению, реализация событий касания существенно различается от устройства к устройству. Я написал диагностический скрипт, который выводит основную информацию о реализации API касаний, в том числе о поддерживаемых событиях и обработке события touchmove. Я тестировал браузеры на следующих платформах: 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 и changedTouches, однако ни один из них не поддерживает координаты radiusX, radiusY и rotationAngle, которые определяют форму пальца, касающегося экрана.

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

Android 2.3.3 (Nexus)

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

Android 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 поддерживают технологию мультисенсорного ввода в полном объеме. Они способны отслеживать касания сразу нескольких пальцев, а браузер обрабатывает такие события очень качественно.

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

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

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

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

Имитация одного касания

Чтобы имитировать единое касание на настольном ПК, можно воспользоваться приложением Phantom Limb, которое имитирует события касания на страницах и отображает вместо указателя мыши огромную руку.

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

Имитация мультисенсорного ввода

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

  1. Загрузите и установите подключаемый модуль npTuioClient NPAPI в каталог ~/Library/Internet Plug-Ins/.
  2. Загрузите приложение TongSeng TUIO для устройства 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>

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

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

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

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

Comments

0