Pointer Lock API в html5. Зачем он нужен и как с ним работать?

pointer-lock

Pointer Lock – это браузерный API, позволяющий создавать интерфейсы для работы с мышкой на основе ее относительных перемещений, а не только абсолютной позиции курсора.

Давайте разберем на примере. Допустим, мы хотим сделать браузерный шутер от первого лица, а-ля Quake. Герой будет видеть перед собой часть игровой сцены, при этом иметь возможность вращаться на 360 градусов и стрелять из пулемета по всей нечисти вокруг. Классически в таких играх горизонтальное перемещение мыши отвечает за поворот героя (обзор игровой сцены).

Так вот до недавнего времени было невозможно качественно организовать такой способ управления вращением героя в браузере. Вы спросите: “В чем же проблема? Вешаем обработчик на mousemove, рассчитываем относительное перемещение и все заработает“.

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

Для таких случаев Pointer Lock будет являться идеальным решением. Его основная особенность – предоставление информации об относительных перемещениях мыши, абстрагируясь от абсолютного положения курсора.

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

Pointer lock api demo

Вот несколько особенностей, которые отличают pointerLock. Прежде всего – это режим работы c мышью, который:

  • Включается и выключается с помощью API.
  • Не ограничивается границами браузера или экрана.
  • Скрывает курсор
  • Обеспечивает информацию об относительных перемещениях мыши

Методы, свойства, события Pointer Lock API

API очень прост в освоении и применении.

Включение режима pointerLock

JS

element.requestPointerLock();

Выключение режима pointerLock

JS

document.exitPointerLock();

Для какого элемента включен pointerLock?

JS

document.pointerLockElement

Событие о включении/выключении режима pointerLock

JS

document.addEventListener('pointerlockchange', function(e){
  // делаем что-то при включении/выключении режима pointerLock
}

Событие об ошибках режима pointerLock

JS

document.addEventListener('pointerlockerror', function(e){
  // делаем что-то при ошибках режима pointerLock
}

Спецификация уже перешла в статус W3C Candidate Recommendation и находится тут
Так, как API еще очень молод, нужно не забывать добавлять вендорные префиксы. Как это делать можно посмотреть в коде демки.


Код демки

JS

// определяем, поддерживается ли pointerLock
var havePointerLock = 'pointerLockElement' in document ||
    'mozPointerLockElement' in document ||
    'webkitPointerLockElement' in document;

// Элемент, для которого будем включать pointerLock
var requestedElement = document.getElementById('pointer-lock-demo');

// Танцы с префиксами для методов включения/выключения pointerLock
requestedElement.requestPointerLock = requestedElement.requestPointerLock ||
                                      requestedElement.mozRequestPointerLock ||
                                      requestedElement.webkitRequestPointerLock;
document.exitPointerLock =            document.exitPointerLock ||
                                      document.mozExitPointerLock ||
                                      document.webkitExitPointerLock;

Далее включаем/выключаем pointerLock по клику

JS

var isLocked = function(){
  return requestedElement === document.pointerLockElement ||
         requestedElement === document.mozPointerLockElement ||
         requestedElement === document.webkitPointerLockElement;
}

requestedElement.addEventListener('click', function(){
  if(!isLocked()){
    requestedElement.requestPointerLock();
  } else {
    document.exitPointerLock();
  }
}, false);

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

JS

var changeCallback = function() {
  if(!havePointerLock){
    alert('Ваш браузер не поддерживает pointer-lock');
    return;
  }
  if (isLocked()) {
    document.addEventListener("mousemove", moveCallback, false);
    document.body.classList.add('locked');
  } else {
    document.removeEventListener("mousemove", moveCallback, false);
    document.body.classList.remove('locked');
  }
}

document.addEventListener('pointerlockchange', changeCallback, false);
document.addEventListener('mozpointerlockchange', changeCallback, false);
document.addEventListener('webkitpointerlockchange', changeCallback, false);

И, наконец, добавляем немного кода для перемещения взгляда героя. После включения режима pointerlock указатель мыши пропадет, а в обработчике mousemove появятся 2 новых свойства: e.movementX и e.movementY

JS

var moveCallback = function(e) {
  var x = e.movementX ||
          e.mozMovementX ||
          e.webkitMovementX ||
          0;

  var y = e.movementY ||
          e.mozMovementY ||
          e.webkitMovementY ||
          0;

  var bgPos = window.getComputedStyle(requestedElement)
          .getPropertyValue('background-position')
          .split(' ')
          .map(function(v){
            return parseInt(v,10);
          });

  requestedElement.style.backgroundPosition = (bgPos[0] - x) + 'px ' + (bgPos[1] - y) + 'px';
}

Проблемы

По большому счету проблема только одна – неполная поддержка браузерами. На данный момент (12.2013) API поддерживают только десктопные chrome и firefox. Стоит ли из за этого отказывать от его использования? Решать Вам. В любом случае, я бы сначала изучил, какие браузеры будет использовать Ваша целевая аудитория. Мне кажется, что геймеры и люди, увлеченные веб приложениями с десктопным функционалом, врядли пользуются Internet Explorer ;)

Tagged with: , , ,

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

*

* Copy This Password *

* Type Or Paste Password Here *

Проект создан в GanttPRO
Спасибо за лайк в FACEBOOK
Подписывайтесь на новости вконтакте
Последние статьи от html5.by