Pointer Lock — это браузерный API, позволяющий создавать интерфейсы для работы с мышкой на основе ее относительных перемещений, а не только абсолютной позиции курсора.
Давайте разберем на примере. Допустим, мы хотим сделать браузерный шутер от первого лица, а-ля Quake. Герой будет видеть перед собой часть игровой сцены, при этом иметь возможность вращаться на 360 градусов и стрелять из пулемета по всей нечисти вокруг. Классически в таких играх горизонтальное перемещение мыши отвечает за поворот героя (обзор игровой сцены).
Так вот до недавнего времени было невозможно качественно организовать такой способ управления вращением героя в браузере. Вы спросите: «В чем же проблема? Вешаем обработчик на mousemove, рассчитываем относительное перемещение и все заработает«.
Дело в том, что если вы попробуете провести мышью горизонтально по столу слева направо, то наступит момент, когда абсолютная позиция указателя мыши достигнет правого края окна и больше не будет увеличиваться. И так во всех направлениях. В итоге поворот героя будет ограничен размером браузерного окна.
Для таких случаев Pointer Lock будет являться идеальным решением. Его основная особенность — предоставление информации об относительных перемещениях мыши, абстрагируясь от абсолютного положения курсора.
Чтобы лучше понять это, давайте попробуем поиграться с демкой, а потом перейдем к коду.
Вот несколько особенностей, которые отличают 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 ;)
Добавить комментарий