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

http://www.html5rocks.com/mobile/touch.html
  • Перевод
Мобильные устройства такие как сматрфоны или планшеты обычно имеют емкостный экран, чувствительный к прикосновениям для расширенного взаимодействия с пользователем.

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

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

События


Эти три основных события представлены в спецификации и поддерживаются многими устройствами:
touchstart: прикосновение к DOM element (аналог mousedown).
touchmove: движение пальца по DOM element (аналог mousemove).
touchend: палец убран с DOM element (аналог mouseup).

Каждое событие включает в себя три списка точек прикосновения (списки пальцев):
touches: список всех точек прикосновения на экране.
targetTouches: список точек на текущем элементе.
changedTouches: список пальцев, участвующих в текущем событии. Например, в событии touchend это тот палец, который был убран.

Каждый элемент списка представляет из себя объект формата:
identifier: уникальный идентификатор пальца, который сейчас на течскрине
target: DOM element, который является целью события
координаты client/page/screen: точка возникновения события на экране
radius и rotationAngle: эллипс, который описывает форму пальца

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


События touchstart, touchmove и touchend предоставляют достаточно мощный API для создания любых взаимодействий, основанных на прикосновении включая все обычные мультитач жесты — зум, вращение и так далее.

Этот пример позволяет вам перетаскивать DOM element, используя одноточечное прикосновение:
var obj = document.getElementById('id');
obj.addEventListener('touchmove', function(event) {
  // Если 1 палец внутри элемента
  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);

Ниже есть пример, который отображает все прикосновения на экране.
image
Картинка кликабильна
Вот его код:
// Выше мы создали canvas
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);

Демки

Появилось уже большое количество приложений с поддержкой мультитач, одно из них рисовалка, основанная на canvas, созданная Paul Irish
image

И демка Browser Ninja — клон Fruit Ninja, использующая CSS3 transforms, transitions и canvas:
image

Важные Моменты


Предотвращение зума

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

Для отключения зума вам необходимо приписать следующий мета-тег:
<meta name="viewport" 
  content="width=device-width, initial-scale=1.0, user-scalable=no">

Для более точной настройки посмотрите вот эту статью www.html5rocks.com/mobile/mobifying.html#toc-meta-viewport

Предотвращение скролла

Некоторые мобильные устройства имеют поведение по умолчанию для жеста «скролл» (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);

// Таймер 60fps
timer = setInterval(function() {
  renderTouches(touches);
}, 15);

Таймеры на setInterval — это не очень хороший способ для создания анимаций, т.к. он не синхронизируется с циклом перерисовки браузера. Современные десктопные браузеры предоставляют функцию requestAnimationFrame, которая лучше подходит для цикличных анимаций — она производительней и тратит меньше батареи. Как только она будет поддерживаться всеми современными браузерами использование setInterval будет плохим тоном.

Использование targetTouches и changedTouches

Важно понять, что event.touches это массив всех пальцев, которые контактируют с экраном, не только те, что касаются DOM element'а. Наиболее подходящим обычно является event.targetTouches или event.changedTouches.

Наконец, если вы разрабатываете под мобильные устройства, вы должны знать важные моменты, которые описаны в статье Eric Bidelman и в документе W3C.

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


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

В двух словах, все эти браузеры поддерживают touchstart, touchend, и touchmove.
В спецификации описаны ещё 3 события, но ни один из браузеров не поддерживает их:
touchenter: палец входи в DOM element.
touchleave: палец покидает DOM element.
touchcancel: касание прервано (зависит от реализации).

Все протестированные браузеры также предоставляют списки прикосновений — touches, targetTouches и changedTouches. Однако, ни один из браузеров не поддерживает ни radiusX ни radiusY ни rotationAngle, которые определяют форму пальца.

Событие touchmove, срабатывает порядка 60 раз в секунду на всех протестированных устройствах.

Android 2.3.3 (Nexus)

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

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 в полной мере поддерживают Touch API.

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


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

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

Решение этой проблемы — симулирование события прикосновения на вашем ПК. Одноточечное прикосновение можно симулировать мышкой. Мультитач может быть симулирован на устройствах с поддержкой мулититач, например на новых Apple MacBook.

Одноточечные события

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

Также существует плагин Touchable для jQuery, который обединяет события мыши и прикосновения.

Мультитач события (решение только для MAC)

Для того, чтобы включить возможность обработки мультитач событий в вашем браузере, используя мультитач устройства (Apple MacBook или MagicPad). Я создал MagicTouch.js он отлавливает события от вашего trackpad и конвертирует их в события совместимые со стандартом.
Для начала работы:
1. Скачайте и установите плагин npTuioClient NPAPI в ~/Library/Internet Plug-Ins/.
2. Скачайте приложение TongSeng TUIO для MagicPad и запустите сервер.
3. Скачайте JavaScript библиотеку MagicTouch.js для симуляции событий прикосновения, совместимых со стандартом.
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. На OS X вы можете настроить системные события в System Preferences > Trackpad

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

От переводчика
В комментариях к оригинальной статье также проскакивала ссылка: Touching and Gesturing on the iPhone
Предложения, пожелания, критика приветствуется!
Поделиться публикацией
Комментарии 14
    0
    Было бы интересно услышать сравнение библиотек для создания «пальце-ориентированных» веб-приложений.
      0
      Навскидку из известных вспоминается только Sencha Touch.
        +2
        jQuery Mobile поддерживает только однопальцевые события tap, taphold, swipe, swipeleft, swiperight
        Sencha Touch поддерживает любые жесты tap, tapstart, tapmove, doubletab, drag, pinch (мультитач).

        Сейчас Sencha Touch имеет более качественное оформление внешнего вида, но тяжелее и стоит денег. У jQuery Mobile за плечами огромное комунити и все фичи это вопрос времени, сейчас jQuery Mobile прилично лагает (альфа дает о себе знать). Впринципе, других альтернатив и нет.
          +1
          Sencha Touch не стоит ни копейки. www.sencha.com/products/touch/license/
            0
            Был не прав, по аналогии с Ext JS подумал, что денег стоит. Стоит денег только Sencha Touch Standard Support — 299$: Telephone Support, Emergency Bug Fixes (по сути ничем не отличается от стандартного тарифного плана)
              0
              А должен ли я выкладывать все исходники своего сайта под GPL в таком случае?
          +1
          «Apple ввел свое touch events API» и видимо запатентовал его. Чую скоро ждать очередную серию патентных срачей. Хотя если тут W3C присутствует, то видимо не все так плохо…
            +1
            Меня не оставляют равнодушным блоги, которые отключают зум, что пальцами, что кнопочками. Читать невозможно — иногда хочется сделать текст покрупнее — фиг вам, не работает. С поддержкой тач-событий жду что всё станет ещё хуже. Хочу кнопку в настройках, которая отключает возможность отключения стандартных реакций браузера. ;)
              0
              Еще пару лет и полный мультитач будет везде.
                0
                А как убрать активацию элемента в android-браузере? Например, когда нажимаешь на Canvas он выделяется зеленым прямоугольником.
                  0
                  event.preventDefault()?
                  0
                  А как на мультитачах работают обычные события (mousedown, mousemove, mouseup, click)? Есть ли отличия от десктопа? Будет ли разработанный для десктопа сайт нормально работать на тачскрине, без использования touch events?
                    0
                    Эти события эмулируются, но есть тонкости (например клик срабатывает через 100-250мс после touchstart) о которых на прошедшем в субботу Web Standards Days говорил Patrick H.Lauke слайды. Видео пока нет.
                    0
                    Для эмуляции одноточечного события можно использовать к примеру iPad эмулятор хрома. И никаких либ сторонних не нужно.

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое