Событие pointerup не срабатывает для действий мыши по ссылке, когда было обнаружено pointermove

Я не могу заставить событие pointerup запускаться по ссылке (тег A с установленным атрибутом href) для event.pointerType == 'mouse', если мышь была перемещена между pointerdown и pointerup.

У меня есть следующий сценарий:

var lastEvent = false;
var handler = function (e) {
  if (lastEvent != e.type) {
    e.target.innerHTML += e.type + ' with ' + e.pointerType + '<br/>';
    e.target.scrollTo(0, e.target.scrollHeight);
  }
  lastEvent = e.type;
}
document.querySelector('a').addEventListener('pointerdown', handler);
document.querySelector('a').addEventListener('pointermove', handler);
document.querySelector('a').addEventListener('pointerup', handler);
div {
  height: 100vh;
  display: flex;
}
a {
  height: 60vh;
  width: 75vw;
  margin: auto;
  background-color: red;
  display: inline-block;
  user-select: none;
  touch-action: none;
  overflow-y: scroll;
}
<div>
    <a href="#"></a>
</div>

Если я нажимаю кнопку мыши, держу ее некоторое время нажатой, а затем отпускаю, я получаю следующую последовательность:

  1. указатель вниз с помощью мыши
  2. указатель вверх с помощью мыши

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

  1. указатель вниз с помощью мыши
  2. указатель двигать мышью

Проблема: pointerup никогда не срабатывает.

Я предполагаю, что это встроенные функции щелчка или перетаскивания в браузере (я тестировал в Chrome), которые блокируют запуск события pointerup, потому что если сделать это на span или удалить href из ссылки привязки, с которой он работает. эта последовательность:

  1. указатель вниз с помощью мыши
  2. указатель двигать мышью
  3. указатель вверх с помощью мыши

Кроме того, он безупречно работает для сенсорного управления PointerEvents:

  1. указатель вниз с касанием
  2. pointermove с прикосновением
  3. указатель вверх с касанием

Я предполагаю, что есть умное свойство css, которое можно установить для элемента, чтобы отключить это предотвращение pointerup. Что-то вроде a { pointer-actions: click; }, но я не смог найти что.


person Aron Cederholm    schedule 12.09.2018    source источник


Ответы (1)


О! Я изложил ответ в вопросе, в основном. Именно действие перетаскивания предотвратило запуск события pointerup. Простое добавление атрибута draggable="false" к элементу ссылки решило эту проблему.

<a href="#" draggable="false"></a>

Доказательство концепции:

var lastEvent = false;
var handler = function (e) {
  if (lastEvent != e.type) {
    e.target.innerHTML += e.type + ' with ' + e.pointerType + '<br/>';
    e.target.scrollTo(0, e.target.scrollHeight);
  }
  lastEvent = e.type;
}
document.querySelector('a').addEventListener('pointerdown', handler);
document.querySelector('a').addEventListener('pointermove', handler);
document.querySelector('a').addEventListener('pointerup', handler);
div {
  height: 100vh;
  display: flex;
}
a {
  height: 60vh;
  width: 75vw;
  margin: auto;
  background-color: red;
  display: inline-block;
  user-select: none;
  touch-action: none;
  overflow-y: scroll;
}
<div>
    <a href="#" draggable="false"></a>
</div>

Единственным недостатком является то, что если draggable установлено на false, все mousedown-mousemove-mouseup вызовут событие click. Но этого можно избежать, проверив, превышает ли разница для clientX/clientY между событиями pointerdown и pointerup определенное количество пикселей, сохраните это в переменной и добавьте обработчик события click, который в этом случае запускает e.preventDefault(); e.stopPropagation();.

person Aron Cederholm    schedule 12.09.2018