События указателя
Базовая линия Широко доступно *
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с июля 2020 года.
* Некоторые части этой функции могут иметь различный уровень поддержки.
Большая часть современной веб-контента предполагает, что указывающим устройством пользователя будет мышь. Однако, поскольку многие устройства поддерживают другие типы устройств ввода указателя, такие как ручка/стилус и сенсорные поверхности, необходимы расширения существующих моделей событий устройства ввода указателя. События указателя решают эту задачу.
События указателя — это события DOM, которые генерируются для устройства ввода указателя. Они предназначены для создания единой модели событий DOM для обработки устройств ввода указателя, таких как мышь, ручка/стилус или сенсорный ввод (например, один или несколько пальцев).
Указатель — это независимое от оборудования устройство, которое может указывать на определенный набор координат экрана. Наличие единой модели событий для указателей может упростить создание веб-сайтов и приложений и обеспечить хороший пользовательский опыт независимо от оборудования пользователя. Однако для случаев, когда требуется обработка, специфичная для устройства, события указателя определяют свойство pointerType для проверки типа устройства, которое сгенерировало событие.
Необходимые для обработки универсального ввода указателя события аналогичны событиям мыши (mousedown/pointerdown, mousemove/pointermove, и т.д.). Следовательно, типы событий указателя намеренно похожи на типы событий мыши.
Кроме того, событие указателя содержит обычные свойства, присутствующие в событиях мыши (координаты клиента, целевой элемент, состояния кнопок и т.д.), а также новые свойства для других типов ввода: давление, геометрия контакта, наклон и т.д. Фактически, интерфейс PointerEvent наследует все свойства MouseEvent, что облегчает миграцию контента из событий мыши в события указателя.
Терминология
Состояние активных кнопок
Состояние, когда у указателя есть ненулевое значение для свойства buttons. Например, в случае с ручкой, когда ручка находится в физическом контакте с дигитайзером или нажата хотя бы одна кнопка во время наведения.
Активный указатель
Любое устройство ввода указателя, которое может генерировать события. Указатель считается активным, если он может генерировать дальнейшие события. Например, ручка, находящаяся в состоянии нажатия, считается активной, поскольку она может генерировать дополнительные события при подъеме или перемещении ручки.
Дигитайзер
Устройство распознавания с поверхностью, способной обнаруживать контакт. Чаще всего это сенсорный экран, способный распознавать ввод от устройства ввода, такого как ручка, стилус или палец. Некоторые устройства распознавания могут обнаруживать близость устройства ввода, и состояние выражается как наведение, аналогично мыши.
Тестирование попадания
Процесс, используемый браузером для определения целевого элемента для события указателя. Обычно это определяется на основе местоположения указателя и визуального макета элементов в документе на экране.
Указатель
Независимое от оборудования представление устройств ввода, которые могут указывать на определенную координату (или набор координат) на экране. Примеры устройств ввода указателя — это мышь, ручка/стилус и прикосновения.
Захват указателя
Захват указателя позволяет перенаправить события для указателя на определенный элемент, отличный от результатов обычного тестирования попадания по местоположению указателя. См. захват указателя для примера.
Примечание: Захват указателя отличается от блокировки указателя, которая физически предотвращает выход указателя из области.
Событие указателя
Интерфейсы
Основной интерфейс — это интерфейс PointerEvent, который имеет интерфейс constructor плюс несколько типов событий и связанных глобальных обработчиков событий.
Стандарт также включает некоторые расширения интерфейсов Element и Navigator.
В следующих подразделах содержатся краткие описания каждого интерфейса и свойства.
Интерфейс PointerEvent
Интерфейс PointerEvent расширяет интерфейс MouseEvent и имеет следующие свойства.
-
altitudeAngleТолько для чтения -
Представляет угол между осью преобразователя (указателя или стилуса) и плоскостью X-Y экрана устройства.
-
azimuthAngleТолько для чтения -
Представляет угол между плоскостью Y-Z и плоскостью, содержащей ось преобразователя (указатель или стилус) и ось Y.
-
PointerEvent.persistentDeviceIdТолько для чтения Экспериментальный -
Уникальный идентификатор устройства ввода указателя, генерирующего
PointerEvent. -
pointerIdТолько для чтения -
Уникальный идентификатор указателя, вызвавшего событие.
-
widthТолько для чтения -
Ширина (величина по оси X) в пикселях CSS геометрии контакта указателя.
-
heightТолько для чтения -
Высота (величина по оси Y) в пикселях CSS геометрии контакта указателя.
-
pressureТолько для чтения -
Нормализованное давление ввода указателя в диапазоне от
0до1, где0и1представляют минимальное и максимальное давление, соответственно, которое способно обнаруживать оборудование. -
tangentialPressureТолько для чтения -
Нормализованное касательное давление ввода указателя (также известное как боковое давление или цилиндрическое напряжение) в диапазоне
-1до1, где0— это нейтральное положение управления. -
tiltXТолько для чтения -
Угол плоскости (в градусах, в диапазоне от
-90до90) между плоскостью Y-Z и плоскостью, содержащей ось указателя (например, стилуса пера) и ось Y. -
tiltYТолько для чтения -
Угол плоскости (в градусах, в диапазоне от
-90до90) между плоскостью X-Z и плоскостью, содержащей ось указателя (например, стилуса пера) и ось X. -
twistТолько для чтения -
Поворотная скорость указателя (например, стилуса пера) вокруг его главной оси в градусах, со значением в диапазоне
0до359. -
pointerTypeТолько для чтения -
Указывает тип устройства, вызвавшего событие (мышь, ручка, касание и т.д.).
-
isPrimaryТолько для чтения -
Указывает, представляет ли указатель первичный указатель данного типа указателя.
Типы событий и глобальные обработчики событий
События указателей имеют десять типов событий, семь из которых имеют семантику, аналогичную событиям мыши (down, up, move, over, out, enter, и leave).
Ниже приведено краткое описание каждого типа события.
| Событие | Описание |
|---|---|
pointerover | Срабатывает, когда указатель перемещается в границы области проверки элемента (hit test). |
pointerenter | Срабатывает, когда указатель перемещается в границы области проверки элемента или одного из его потомков, включая результат события pointerdown от устройства, не поддерживающего hover (см. pointerdown). |
pointerdown | Срабатывает, когда указатель становится активным состоянием кнопок. |
pointermove | Срабатывает, когда изменяются координаты указателя. Это событие также используется, если изменение состояния указателя не может быть сообщено другими событиями. |
pointerup | Срабатывает, когда указатель больше не находится в активном состоянии кнопок. |
pointercancel | Браузер вызывает это событие, если он приходит к выводу, что указатель больше не сможет генерировать события (например, если связанное устройство деактивировано или браузер решил интерпретировать взаимодействие как масштабирование/перемещение). Сведения о том, как контролировать это поведение, см. в разделе ниже о свойстве CSS touch-action. |
pointerout | Срабатывает по нескольким причинам, включая: указатель перемещается за пределы границ области проверки (hit test) элемента; срабатывание события pointerup для устройства, не поддерживающего hover (см. pointerup); после срабатывания события pointercancel (см. pointercancel); когда стилус пера покидает область наведения, определяемую цифровым планшетом. |
pointerleave | Срабатывает, когда указатель перемещается за пределы границ области проверки (hit test) элемента. Для устройств с пером это событие срабатывает, когда стилус пера покидает область наведения, определяемую цифровым планшетом. |
pointerrawupdate Экспериментально
| Срабатывает, когда указатель изменяет любые свойства, которые не вызывают событий pointerdown или pointerup. |
gotpointercapture | Срабатывает, когда элемент получает захват указателя. |
lostpointercapture | Срабатывает после отпуска захвата указателя для указателя. |
Расширения элементов
Существует три расширения интерфейса Element:
hasPointerCapture()-
Указывает, имеет ли элемент, на котором оно вызывается, захват указателя для указателя, идентифицированного заданным идентификатором указателя.
releasePointerCapture()-
Освобождает (останавливает) захват указателя, который был ранее установлен для определенного события указателя.
setPointerCapture()-
Определяет конкретный элемент как цель захвата будущих событий указателя.
Расширение Navigator
Свойство Navigator.maxTouchPoints используется для определения максимального количества одновременных точек касания, которые поддерживаются в любой конкретный момент времени.
Примеры
Этот раздел содержит примеры базового использования интерфейсов событий указателей.
Регистрация обработчиков событий
В этом примере регистрируется обработчик для каждого типа события для данного элемента.
<div id="target">Touch me…</div>
function over_handler(event) {}
function enter_handler(event) {}
function down_handler(event) {}
function move_handler(event) {}
function up_handler(event) {}
function cancel_handler(event) {}
function out_handler(event) {}
function leave_handler(event) {}
function rawUpdate_handler(event) {}
function gotCapture_handler(event) {}
function lostCapture_handler(event) {}
function init() {
const el = document.getElementById("target");
// Register pointer event handlers
el.onpointerover = over_handler;
el.onpointerenter = enter_handler;
el.onpointerdown = down_handler;
el.onpointermove = move_handler;
el.onpointerup = up_handler;
el.onpointercancel = cancel_handler;
el.onpointerout = out_handler;
el.onpointerleave = leave_handler;
el.onpointerrawupdate = rawUpdate_handler;
el.ongotpointercapture = gotCapture_handler;
el.onlostpointercapture = lostCapture_handler;
}
document.addEventListener("DOMContentLoaded", init);
Свойства события
В этом примере показано получение всех свойств события указателя.
<div id="target">Touch me…</div>
const id = -1;
function process_id(event) {
// Process this event based on the event's identifier
}
function process_mouse(event) {
// Process the mouse pointer event
}
function process_pen(event) {
// Process the pen pointer event
}
function process_touch(event) {
// Process the touch pointer event
}
function process_tilt(tiltX, tiltY) {
// Tilt data handler
}
function process_pressure(pressure) {
// Pressure handler
}
function process_non_primary(event) {
// Non primary handler
}
function down_handler(ev) {
// Calculate the touch point's contact area
const area = ev.width * ev.height;
// Compare cached id with this event's id and process accordingly
if (id === ev.identifier) process_id(ev);
// Call the appropriate pointer type handler
switch (ev.pointerType) {
case "mouse":
process_mouse(ev);
break;
case "pen":
process_pen(ev);
break;
case "touch":
process_touch(ev);
break;
default:
console.log(`pointerType ${ev.pointerType} is not supported`);
}
// Call the tilt handler
if (ev.tiltX !== 0 && ev.tiltY !== 0) process_tilt(ev.tiltX, ev.tiltY);
// Call the pressure handler
process_pressure(ev.pressure);
// If this event is not primary, call the non primary handler
if (!ev.isPrimary) process_non_primary(ev);
}
function init() {
const el = document.getElementById("target");
// Register pointerdown handler
el.onpointerdown = down_handler;
}
document.addEventListener("DOMContentLoaded", init);
Определение основного указателя
В некоторых сценариях может быть несколько указателей (например, устройство с сенсорным экраном и мышью) или указатель, поддерживающий несколько точек контакта (например, сенсорный экран, поддерживающий касание многими пальцами). Приложение может использовать свойство isPrimary, чтобы определить главный указатель среди набора активных указателей для каждого типа указателя. Если приложение хочет поддерживать только основной указатель, оно может игнорировать все события указателя, которые не являются основными.
Мышь имеет только один указатель, поэтому она всегда будет основным указателем. Для сенсорного ввода указатель считается основным, если пользователь коснулся экрана, когда не было других активных касаний. Для ввода пером и стилусом указатель считается основным, если перо пользователя первоначально контактировало с экраном, когда ни одно другое активное перо не контактировало с экраном.
Определение состояний кнопок
Некоторые устройства ввода указателя (такие как мышь и перо) поддерживают несколько кнопок, и нажатия кнопок могут быть комбинированными (т.е. нажатие дополнительной кнопки, в то время как другая кнопка на устройстве ввода указателя уже нажата).
Для определения состояния нажатий кнопок события указателя используют свойства button и buttons интерфейса MouseEvent (от которого PointerEvent унаследован).
В следующей таблице представлены значения button и buttons для различных состояний кнопок устройства.
| Состояние кнопки устройства | button | buttons |
|---|---|---|
| Ни одна кнопка, ни касание/контакт пера не изменились с момента последнего события | -1 | — |
| Движение мыши без нажатых кнопок, Движение пера во время наведения без нажатых кнопок | — | 0 |
| Левая кнопка мыши, Контакт сенсорного экрана, Контакт пера | 0 | 1 |
| Средняя кнопка мыши | 1 | 4 |
| Правая кнопка мыши, кнопка ствола пера | 2 | 2 |
| Кнопка X1 (назад) мыши | 3 | 8 |
| Кнопка X2 (вперед) мыши | 4 | 16 |
| Кнопка ластика пера | 5 | 32 |
Примечание: Свойство button указывает на изменение состояния кнопки. Однако, как и в случае с касаниями, когда происходят несколько событий с одним событием, все они имеют одинаковое значение.
Захват указателя
Захват указателя позволяет перенаправлять события для конкретного события указателя на конкретный элемент вместо обычной области проверки (hit test) в позиции указателя. Это может использоваться для обеспечения того, чтобы элемент продолжал получать события указателя, даже если контакт устройства ввода указателя перемещается вне элемента (например, при прокрутке или перемещении).
Захват указателя приведет к тому, что целевой элемент захватывает все последующие события указателя, как если бы они происходили над захватывающим целевым элементом. Соответственно, pointerover, pointerenter, pointerleave, и pointerout не будут срабатывать до тех пор, пока этот захват установлен. Для браузеров сенсорных экранов, которые позволяют прямое управление, вызов неявного захвата указателя будет выполнен для элемента, когда событие pointerdown сработает. Захват может быть вручную освобожден путем вызова element.releasePointerCapture для целевого элемента, или он будет неявно освобожден после события pointerup или pointercancel.
Примечание: Если вам необходимо переместить элемент в DOM, убедитесь, что вы вызываете setPointerCapture() после перемещения DOM, чтобы setPointerCapture() не потерял его. Например, если вам нужно использовать Element.append() для перемещения элемента в другое место, убедитесь, что вы вызываете setPointerCapture() для него только после вызова Element.append().
Следующий пример показывает, как устанавливается захват указателя для элемента.
<div id="target">Touch me…</div>
function downHandler(ev) {
const el = document.getElementById("target");
// Element 'target' will receive/capture further events
el.setPointerCapture(ev.pointerId);
}
function init() {
const el = document.getElementById("target");
el.onpointerdown = downHandler;
}
document.addEventListener("DOMContentLoaded", init);
Следующий пример показывает, как освобождается захват указателя (когда происходит событие pointercancel). Браузер делает это автоматически при возникновении событий pointerup или pointercancel.
<div id="target">Touch me…</div>
function downHandler(ev) {
const el = document.getElementById("target");
// Element "target" will receive/capture further events
el.setPointerCapture(ev.pointerId);
}
function cancelHandler(ev) {
const el = document.getElementById("target");
// Release the pointer capture
el.releasePointerCapture(ev.pointerId);
}
function init() {
const el = document.getElementById("target");
// Register pointerdown and pointercancel handlers
el.onpointerdown = downHandler;
el.onpointercancel = cancelHandler;
}
document.addEventListener("DOMContentLoaded", init);
Свойство CSS touch-action
Свойство touch-action CSS используется для указания того, следует ли браузеру применять свое поведение по умолчанию (встроенное) для касания (например, масштабирование или перемещение) в определенной области. Это свойство может быть применено ко всем элементам, кроме: не замещающих инлайновых элементов, строк таблиц, групп строк, столбцов таблиц и групп столбцов.
Значение auto означает, что браузер свободен применять свое поведение по умолчанию для касания (к указанной области), а значение none отключает поведение браузера по умолчанию для касания в этой области. Значения pan-x и pan-y, означают, что касания, начатые в указанной области, предназначены только для горизонтального и вертикального прокручивания, соответственно. Значение manipulation означает, что браузер может рассматривать касания, начатые на элементе, только для прокрутки и масштабирования.
В следующем примере поведение браузера по умолчанию для касания отключено для элемента div.
<html lang="en">
<body>
<div style="touch-action:none;">Can't touch this…</div>
</body>
</html>
В следующем примере поведение по умолчанию для касания отключено для некоторых элементов button.
button#tiny {
touch-action: none;
}
В следующем примере, при касании элемента target, он будет перемещаться только в горизонтальном направлении.
#target {
touch-action: pan-x;
}
Совместимость с событиями мыши
Хотя интерфейсы событий указателя позволяют приложениям создавать улучшенные пользовательские интерфейсы на устройствах с поддержкой указателей, на практике подавляющее большинство веб-контента сегодня разработано для работы только с вводом мыши. Следовательно, даже если браузер поддерживает события указателя, браузер должен обрабатывать события мыши, чтобы контент, предполагающий ввод только мышью, работал как есть без непосредственной модификации. В идеале, приложению с поддержкой указателя не нужно явно обрабатывать ввод мыши. Однако, поскольку браузер должен обрабатывать события мыши, могут возникнуть некоторые проблемы совместимости, которые необходимо решить. Этот раздел содержит информацию о взаимодействии событий указателя и событий мыши и последствиях для разработчиков приложений.
Браузер может сопоставлять общий ввод указателя с событиями мыши для совместимости с контентом, основанным на мыши. Это сопоставление событий называется совместимыми событиями мыши. Авторы могут предотвратить генерацию определенных совместимых событий мыши, отменив событие pointerdown, но обратите внимание, что:
- События мыши могут быть предотвращены только при нажатии указателя.
- Указатели наведения (например, мышь без нажатых кнопок) не могут предотвратить свои события мыши.
- События
mouseover,mouseout,mouseenter, иmouseleaveникогда не предотвращаются (даже если указатель нажат).
Рекомендации
Вот несколько рекомендаций, которые следует учитывать при использовании событий указателя:
- Сведите к минимуму объем работы, выполняемой в обработчиках событий.
- Добавляйте обработчики событий к конкретному целевому элементу (а не ко всему документу или узлам, расположенным выше в дереве документа).
- Целевой элемент (узел) должен быть достаточно большим, чтобы вместить самую большую площадь контакта (обычно палец). Если целевая область слишком мала, касание может привести к срабатыванию других событий для смежных элементов.
Спецификации
| Спецификация |
|---|
| События указателя |
Совместимость с браузерами
| Рабочий стол | Мобильный | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox для Android | Opera Android | Safari на IOS | Samsung Internet | WebView Android | |
PointerEvent |
55 | 12 | 59 | 42 | 13 | 55 | 79 | 42 | 13 | 6.0 | 55 |
Pointer_events |
55 | 12 | 59 | 42 | 13 | 55 | 79 | 42 | 13 | 6.0 | 55 |
altitudeAngle |
86 | 86 | 131 | 72 | 18.2 | 86 | 131 | 61 | 18.2 | 14.0 | 86 |
azimuthAngle |
86 | 86 | 131 | 72 | 18.2 | 86 | 131 | 61 | 18.2 | 14.0 | 86 |
getCoalescedEvents |
58 | 79 | 59 | 45 | 18.2 | 58 | 79Метод всегда возвращает пустой массив, независимо от действий пользователя. |
43 | 18.2 | 7.0 | 58 |
getPredictedEvents |
77 | 79 | 89 | 64 | 18.2 | 77 | 89 | 55 | 18.2 | 12.0 | 77 |
height |
55 | 12 | 59 | 42 | 13 | 55 | 79 | 42 | 13 | 6.0 | 55 |
isPrimary |
55 | 12 | 59 | 42 | 13 | 55 | 79 | 42 | 13 | 6.0 | 55 |
persistentDeviceId |
128 | 128 | Нет | 114 | Нет | 128 | Нет | 85 | Нет | Нет | 128 |
pointerId |
55 | 12 | 59 | 42 | 13 | 55 | 79 | 42 | 13 | 6.0 | 55 |
pointerType |
55 | 12 | 59 | 42 | 13 | 55 | 79 | 42 | 13 | 6.0 | 55 |
pressure |
55 | 12 | 59 | 42 | 13 | 55 | 79 | 42 | 13 | 6.0 | 55 |
tangentialPressure |
57 | 79 | 59 | 44 | 13 | 57 | 79 | 43 | 13 | 7.0 | 57 |
tiltX |
55 | 12 | 59 | 42 | 13 | 55 | 79 | 42 | 13 | 6.0 | 55 |
tiltY |
55 | 12 | 59 | 42 | 13 | 55 | 79 | 42 | 13 | 6.0 | 55 |
twist |
57 | 18 | 59 | 44 | 13 | 57 | 79 | 43 | 13 | 7.0 | 57 |
width |
55 | 12 | 59 | 42 | 13 | 55 | 79 | 42 | 13 | 6.0 | 55 |
Некоторые дополнительные значения были определены для свойства CSS touch-action в рамках спецификации Pointer Events, но в настоящее время поддержка этих значений ограничена.
См. также
Демонстрации и примеры
Сообщество
Связанные темы и ресурсы
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events