Подтвердить что ты не робот

Динамическое отключение сенсорного действия (overcroll) для элементов SVG

У меня возникли проблемы с чрезмерным просмотром сенсорного экрана в Chrome.

У меня есть документ с элементом SVG в нем, который содержит некоторую форму, например прямоугольник:

введите описание изображения здесь

Теперь я хочу сделать перетаскиваемый прямоугольник, что означает, что я хочу отключить все виды сенсорных действий в соответствующем элементе <rect>, установив его свойство style touch-action: none.

Это отлично работает на всех настольных браузерах, кроме Chrome. В Chrome, когда я касаюсь и перемещаюсь по прямоугольнику, функция прокрутки браузера запускается. Это приводит к неудобному перемещению окна браузера, а также ко всем событиям указателя, которые я установил на прямоугольнике.

т.е. pointermove зарегистрирован на долю секунды, затем он просто останавливается, когда происходит прокрутка. pointerup никогда не вызывается даже при отпускании сенсорного экрана.

введите описание изображения здесь

Теперь, если бы у меня был элемент HTML вместо SVG-элемента, установка touch-action: none выполнила бы задание. То же самое происходит с элементом SVG.

Технически это можно решить, установив touch-action: none на document.body или обернув весь SVG в элемент <div> с помощью touch-action: none.

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

В качестве решения я попытался динамически установить touch-action: none на document: body, когда событие pointerdown происходит на прямоугольнике.

// Get element
var o = document.getElementById( "test" );

// disable touch action on press of the SVG element
o.addEventListener( "pointerdown", function(e) {
  document.body.style.touchAction = "none";
} );

// re-enable touch action when released
o.addEventListener( "pointerup", function(e) {
  document.body.style.touchAction = "auto";
} );

К сожалению, это не помогает. Стиль на теле устанавливается, и в следующий раз, когда я попробую перетащить прямоугольник, он работает как ожидалось (потому что событие pointerup никогда не выполняется), просто не в этот раз.

Добавление preventDefault() в обработчики событий также не влияет.

Я был бы признателен, если бы кто-то, у кого был подобный опыт, мог поделиться решением.

Вот живой пример выше.

// Get element
var o = document.getElementById( "test" );

// disable touch action on press of the SVG element
o.addEventListener( "pointerdown", function(e) {
  document.body.style.touchAction = "none";
} );

// re-enable touch action when released
o.addEventListener( "pointerup", function(e) {
  document.body.style.touchAction = "auto";
} );
<svg id="test" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="width: 300px; height: 300px; border: 1px solid #eee;">
  <g transform="translate(50,50)">
    <rect fill="#00fff0" width="200" height="200" style="touch-action: none;"></rect>
  </g>
</svg>
4b9b3361

Ответ 1

Я думаю, этого было бы достаточно, предотвратив touchstart:

window.addEventListener( "touchstart", function(e) {
  // Determine wether or not you are panning from rectangle:
  if (e.target ....)
      e.preventDefault();
} );