2016-12-20 9 views
6

На сенсорных устройствах наблюдается странное поведение касательно зоны контакта, если вы переключаете высоту элемента, расположенного выше. Если вы запустите следующий фрагмент (например, сохраните его локально и используйте хром для эмуляции событий касания), вы заметите, что хеш #mylink добавлен в URL-адрес, в некоторых случаях вы не нажимали на область красной ссылки. И иногда вы щелкали по красной области, ее не добавляли.Неверная область щелчка из-за переключения класса/изменения высоты при событии касания

E.g.

  • Если вы нажмете верхнюю зону серого (первые 200 пикселей), серая область переключит высоту. => Хорошо.
  • Если вы нажмете увеличенную, более низкую серость (200px - 400px), то добавьте в URL-адрес #mylink, как если бы вы нажали на область красной ссылки. => Почему?
  • Если вы нажмете верхнюю красную область (сначала 200px, сведенная серая область), #mylink не добавляется к URL. => Почему?
  • Если вы нажмете нижнюю красную область (последние 200 пикселей, увеличен серый участок), #mylink не добавлен к URL. => Почему?

<html> 
 
<head> 
 
\t <style type="text/css"> 
 
\t \t .test { 
 
\t \t \t background: grey; 
 
\t \t \t height: 200px; 
 
\t \t } 
 

 
\t \t .test.is-visible { 
 
\t \t \t height: 400px; 
 
\t \t } 
 

 
\t \t .link { 
 
\t \t \t height: 600px; 
 
\t \t \t display: block; 
 
\t \t \t background: red; 
 
\t \t } 
 
\t </style> 
 
\t <script type="text/javascript"> 
 
\t (function() { 
 
\t  window.addEventListener('touchstart' , function() { 
 
\t  \t document.getElementsByClassName("test")[0].classList.toggle('is-visible'); 
 
\t  }); \t 
 
\t \t })(); 
 
\t </script> 
 
</head> 
 

 
<body> 
 
\t <div class="test"> 
 
\t \t Click the grey area. Element enhances and minimizes itself. Now click on the lower half of the enhanced grey area (if grey = enhanced) or on the white area up to 200px below of the red area (if grey = minimized). #mylink is added to the url as if you had clicked on the red area. Why? 
 
\t </div> 
 
\t <a href="#mylink" class="link">The red area is the "normal" click area.</a> 
 
</body> 
 

 
</html>

Я попробовал это на IOS, Android и эмулировать события касания как в Chrome и Firefox. Они все ведут себя одинаково.

Если я слушаю click вместо touchstart или touchend событие, оно работает должным образом.

В чем причина этого несоответствия? Почему область ссылок отличается/неуместна, если я слушаю события касания вместо события click?

ответ

2

TL; DR

Браузеров выполнить событие щелчка после сенсорных событий на месте расположения touchend, независимо от того, если содержание не изменилось из-за функции, возложенных на событие прикосновения.


После рытья ри Touch Events specification Я думаю, что я могу ответить на мой вопрос:

Section 8 описывает взаимодействие сенсорных событий с событиями мышей и нажмите кнопку. Он говорит, что:

Агент пользователя может отправить оба события прикосновения и (...) события мыши в ответ на тот же ввод данных пользователем.

и

Если агент пользователя интерпретирует последовательность событий прикосновения как водопроводная жест, то он должен направить MouseMove, MouseDown, MouseUp и нажмите события (в указанном порядке) на месте события касания для соответствующего сенсорного ввода.

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

и наиболее важный

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

1.) touchstart

2.) Ноль или более TouchMove события, в зависимости от движения пальца

3.) touchend

4.) MouseMove (для совместимости с унаследованной мыши конкретным кодом)

5.) MouseDown

6.) MouseUp

7.)

для нашего примера выше, это означает, что:

1.) touchstart или touchend.

2.) Пользовательская функция обрабатывается сначала, которая переключает класс и изменяет высоту/положение элементов.

3.) Впоследствии событие click выполнено в том же месте, где произошло событие touch, но теперь охватывает другую цель.

спецификация обеспечивает способ предотвратить это тоже:

Если touchstart, TouchMove или touchend отменяются, агент пользователя не должен отправлять какие-либо события мыши, который был бы косвенный результат предотвращенного сенсорного события ,

Так что я думаю, самый простой способ «исправить» это поведение, чтобы предотвратить событие с `preventDefault()», а затем нажмите вручную на цели мероприятия и переключить класс наконец:

 window.addEventListener('touchstart' , function(event) { 
     event.preventDefault(); 

     event.target.click(); 

     document.getElementsByClassName("test")[0].classList.toggle('is-visible'); 
    }); 

В хромовом трекере Chromium есть statement, что также подтверждает это.

4

Это то, что происходит, когда вы повысили серую область и прикосновение к нижней половине:

  • При прикосновении к нижней половине серой области, ваше touchstart события инициируются
  • Ваших прогонов функции и переключает (удаляет) is-visible класса на сером элемент
  • высота серого элемента становится меньше
  • красный элемент перемещается вверх 200px
  • Вашего прикосновения не продвинулось, но элементы на странице есть - теперь вы прикасаясь красным элементом
  • Когда вы отпустите ваши прикосновения, то touchend события срабатывают на красном элементе, который это событие, которое определяет если ссылка была затронута или не

То же самое происходит, когда вы нажимаете на область 200px под красным элементом:

  • когда вы касаетесь область под красным элементом, ваше touchstart событие Trigg ERed
  • Ваша функция работает и переключает (добавляет) is-visible класс на сером элемент
  • Высота серого элемента становится больше
  • красный элемент перемещается 200px вниз
  • Ваше прикосновение не продвинулось, но элементы на странице есть - теперь вы прикасаясь красный элемент
  • Когда вы отпустите ваши прикосновения, то touchend событие срабатывает на красный элемент, который является событием, которое определяет, является ли ссылка была затронута или не
+0

Благодарим вас за подробное описание деятельности. Я не уверен, что это окончательное объяснение этого поведения, поскольку происходит то же самое, если я слушаю «touchhend» или «touchstart». Если я правильно вас пойму, это будет означать, что если я выполню переключение только на коснуться, это не должно произойти, правильно? Но это ... – chaenu

+0

Также, если мы предположим, что для 'touchhend' порядок события тот же (сначала переключить, затем вызвать ссылку). Почему это отличается от события 'click', где кажется, что порядок отличается (сначала запускается ссылка, затем переключается)? – chaenu