Это не авторское творение, собранная информация удобна для изучения и накопления знаний
Происхождение задержки клика 300 мс на мобильном терминале:
история:Начало 2007 года. Накануне запуска первого iPhone Apple столкнулась с проблемой: сайт в то время был рассчитан на устройства с большим экраном. Поэтому инженеры Apple приняли некоторые соглашения, чтобы решить проблему просмотра сайтов на настольных компьютерах на маленьком экране, таком как iPhone.
Самый известный из них — двойное касание для увеличения, что является основной причиной вышеупомянутой задержки в 300 мс.
Двойное касание для масштабирования, как следует из названия, — это быстрое двойное касание экрана пальцем, и браузер Safari, поставляемый с iOS, увеличит веб-страницу до исходного соотношения. Так какое это имеет отношение к задержке в 300 мс? Предположим такой сценарий. Пользователь щелкает ссылку в iOS Safari. Поскольку пользователь может дважды щелкнуть для увеличения или дважды щелкнуть для прокрутки, после того, как пользователь один раз коснется экрана, браузер не может сразу определить, действительно ли пользователь хочет открыть ссылку или хочет дважды щелкнуть. Таким образом, iOS Safari ждет 300 мс, чтобы увидеть, коснется ли пользователь экрана снова. Учитывая успех iPhone, другие мобильные браузеры скопировали большинство соглашений браузера iPhone Safari, включая двойное касание для увеличения, которое теперь доступно почти во всех мобильных браузерах. Если раньше люди просто соприкасались с мобильными страницами и часто не обращали внимания на задержку в 300 мс, когда были счастливы, то сейчас сенсорный интерфейс растет как грибы, а пользователи предъявляют повышенные требования к опыту, что неприемлемо.
Другими словами, мобильные браузеры будут иметь некоторые поведения по умолчанию, такие как двойной щелчок для масштабирования и двойной щелчок для прокрутки. Эти действия, особенно двойное касание для увеличения, в первую очередь предназначены для мобильного просмотра сайтов на настольных компьютерах. Когда пользователь работает со страницей, мобильный браузер сначала определяет, хочет ли пользователь активировать поведение по умолчанию.
Важно: Поскольку мобильный терминал имеет операцию масштабирования двойным щелчком, браузер должен ждать 300 мс после щелчка, чтобы увидеть, есть ли у пользователя следующий щелчок, то есть является ли операция двойным щелчком.
Решения для разработчиков браузеров
Вариант 1: отключить масштабирование
Когда заголовок HTML-документа содержит следующееmeta
При маркировке:
<meta name="viewport" content="user-scalable=no">
<meta name="viewport" content="initial-scale=1,maximum-scale=1">
Указывает, что страница не масштабируется, тогда функция двойного касания для увеличения не имеет смысла, и в этом случае браузер может отключить поведение масштабирования двойным нажатием по умолчанию и удалить задержку клика в 300 мс.
Решение 2. Измените ширину области просмотра по умолчанию
В начале, чтобы обеспечить нормальное отображение настольных сайтов в мобильных браузерах, ширина области просмотра мобильных браузеров по умолчанию не равна ширине окна браузера устройства, а больше, чем ширина окна браузера устройства, обычно 980 пикселей. Мы можем установить ширину области просмотра равной ширине устройства с помощью следующих тегов.
<meta name="viewport" content="width=device-width">
Поскольку масштабирование двойным щелчком в основном используется для улучшения просмотра настольных сайтов на мобильном терминале, а с популяризацией адаптивного дизайна многие сайты были адаптированы и оптимизированы для мобильного терминала. чтобы дважды щелкнуть, чтобы увеличить. Если он может распознать, что веб-сайт отзывчив, то мобильные браузеры могут автоматически отключить поведение двойного нажатия для увеличения по умолчанию и удалить задержку клика 300 мс. Если установлено вышеmeta
тег, то браузер может думать, что веб-сайт был адаптирован и оптимизирован для мобильного терминала, поэтому нет необходимости дважды щелкать для увеличения.
Преимущество этой схемы по сравнению со схемой 1 заключается в том, что она не полностью отключает масштабирование, а только отключает поведение двойного касания браузера по умолчанию для масштабирования, но пользователь по-прежнему может масштабировать страницу с помощью операции масштабирования.
touch-action
это свойство CSS. Этот атрибут определяет поведение пользовательского агента (то есть браузера) по умолчанию, которое может быть запущено для соответствующего элемента. Если значение свойства установлено вtouch-action: none
, то это означает, что операция над этим элементом не вызовет поведения пользовательского агента по умолчанию, поэтому нет необходимости оценивать задержку в 300 мс.
существующие решения
Решение 1. Polyfill для событий указателя
За исключением IE, большинство других браузеров не поддерживают события указателя. Есть некоторые библиотеки JS, которые позволяют нам использовать события указателя заранее, например
- GooglePolymer
- МайкрософтHandJS
- @Rich-HarrisизPoints
Однако сейчас нас интересуют не события указателя, а свойства CSS, связанные с задержкой в 300 мс.touch-action
. Поскольку большинство браузеров, кроме IE, не поддерживают это новое свойство CSS, полифилы для этих событий указателя должны каким-то образом эмулировать поддержку этого свойства. Одно решение состоит в том, чтобы JS запрашивал синтаксический анализ всех таблиц стилей, другое решение —touch-action
как атрибут тега html.
Вариант 2: FastClick
FastClickдаFT LabsОблегченная библиотека, специально разработанная для решения проблемы задержки клика в 300 мс в мобильных браузерах. Принцип реализации FastClick заключается в том, что при обнаружении события касания он немедленно имитирует событие щелчка через пользовательское событие DOM и блокирует событие щелчка браузера через 300 мс.
2. Проблема с кликами
После разговора о задержке в 300 мс в мобильных кликах я должен упомянуть о проблеме проникновения кликов на мобильный терминал. Некоторые люди могут подумать, что, поскольку щелчок имеет задержку в 300 мс, для сенсорного экрана мы не можем просто напрямую прослушивать событие touchstart?
Есть два недостатка в использовании touchstart вместо событий click.
Первый: touchstart срабатывает, когда палец касается экрана, иногда пользователь просто хочет провести пальцем по экрану, но вызывает событие touchstart, а это не тот результат, который нам нужен;
Во-вторых: в некоторых сценариях использование события touchstart может привести к проникновению щелчка.
чтоПролистать?
Предположим, что на странице есть два элемента A и B. Элемент B находится над элементом A. Мы зарегистрировали функцию обратного вызова на событие touchstart элемента B, а функция функции обратного вызова — скрыть элемент B. Мы обнаружили, что когда мы нажимаем на элемент B, элемент B скрывается, а затем элемент A вызывает событие щелчка.
Это связано с тем, что в мобильных браузерах порядок выполнения событий таков: touchstart > touchend > click. Событие щелчка имеет задержку 300 мс.После того, как событие touchstart скрывает элемент B, браузер запускает событие щелчка через 300 мс, но элемент B в это время отсутствует, поэтому событие отправляется элементу A. Если элемент A является ссылкой, страница будет неожиданно переходить.
Примечание. Порядок, в котором запускаются события браузера.
touchstart --> mouseover (не реализовано в некоторых браузерах) --> mousemove (один раз) --> mousedown --> mouseup --> щелчок --> touchend
Среди сенсорных событий обычно используются touchstart, touchmove и touchend. В дополнение к touchcancel. Обратите внимание, что в нативных событиях нет события касания. Далее объясняется, как генерируется событие касания.
Описание события следующее:
мероприятие | описывать | Время запуска |
---|---|---|
touchstart | начать трогать | Срабатывает, как только палец касается экрана |
touchmove | переместить или перетащить | Зависит от системы и браузера |
touchend | сенсорный конец | Начните, как только ваш палец покинет экран |
Событие касания обычно запускается пальцами, а также бывают такие ситуации, как мультитач, направление перетаскивания и т. д. Несколько важных параметров перечислены ниже:
параметр | имея в виду |
---|---|
touches | Список информации для каждого пальца на экране |
targetTouches | Подобно касаниям, отфильтруйте информацию о пальцах того же узла. |
changedTouches | Список информации для каждого пальца, реагирующего на текущее событие |
Код получается следующим образом:
elemenrRef.addEventListener('touchstart', function(e) {
console.log(e.touches, e.targetTouches, e.changedTouches);}
);
Процесс запуска сенсорного события пальцем выглядит следующим образом:
touchstart --> mouseover(有的浏览器没有实现) --> mousemove(一次) -->mousedown -->
mouseup --> click -->touchend
Исходя из этого, мы можем записать начало касания в событии онтачстарт, а ontouchend записать информацию о завершении касания. С помощью приведенных выше параметров легко рассчитать время призрачного щелчка, а также соответствующую информацию о проникновении щелчка, включая координаты отклика.
Феномен:
1) Проблема проникновения щелчка: нажмите кнопку закрытия на маске, и после того, как маска исчезнет, обнаружено, что событие щелчка элемента под кнопкой срабатывает,
Кнопка закрытия маски привязана к событию касания, а элемент под кнопкой привязан к событию щелчка. После срабатывания события касания маска исчезает. Через 300 мс событие щелчка в этой точке срабатывает, и цель события естественно ниже элемента button., потому что кнопка исчезает вместе с маской2) Проблема проникновения межстраничных кликов: если кнопка является тегом с атрибутом href, страница перепрыгнет
Поскольку переход по тегу по умолчанию запускается событием клика, принцип точно такой же, как и выше.
3) Еще одна проблема проникновения межстраничных кликов: на этот раз маски нет, просто нажмите кнопку на странице, чтобы перейти на новую страницу, а затем обнаружите, что событие щелчка соответствующего элемента позиции на новой странице запускается
Как и в случае с маскирующим слоем, если логика js, управляющая переходом на страницу, привязана к событию касания, а элемент в соответствующей позиции на новой странице привязан к событию щелчка, и страница завершает переход в течение 300 мс, три Если условия выполняются одновременно, это происходит
Если приходится подразделять, есть четвертый тип, но вероятность очень мала, то есть соответствующий элемент позиции на новой странице оказывается тегом a, и тогда происходят непрерывные скачки. . . И так далее, это все проблемы с кликами
решение:
-
просто прикоснись
Самое простое решение для идеального решения проблемы кликабельности
Заменить все клики на странице событиями касания (
touchstart
, «прикоснуться», «нажать»)особое вниманиетег, href тега a также является щелчком, вам нужно удалить прыжок, управляемый js, или напрямую изменить его на span + tap для управления переходом. Если требования невысокие и вас не волнует скольжение или скольжение для срабатывания событий, то span + touchend вполне подойдет, ведь для tap нужна сторонняя библиотекаНет ничего плохого без тега a. При разработке мобильных приложений не нужно учитывать SEO. Даже если используется тег a, все стили по умолчанию, как правило, удаляются. Лучше использовать span напрямую.
-
просто нажмите
Крайнее средство, потому что это приведет к задержке в 300 мс, любое пользовательское взаимодействие на странице добавит задержку в 300 мс, о которой сложно думать.Без тача не будет проблемы срабатывания клика через 300 мс после касания.Если требования к интерактивности не высокие, то можно сделать и это.
настоятельно не рекомендуется, быстрее всегда лучше -
Задержка 350 мс после касания, а затем скрытие маски
Изменение минимальное, недостатком является то, что скрытая маска становится медленнее, и 350 мс все еще могут показаться медленными.
Только нужно иметь дело с маской, изменения очень маленькие, если требования не высоки, использовать это более экономно
-
pointer-events
громоздкий и несовершенный,
Не рекомендуется для использованияПосле того, как маска будет скрыта, добавьте ее к элементу под кнопкой
pointer-events: none;
Стиль, пропустите клик, удалите этот стиль через 350 мс и восстановите ответНедостаток в том, что в течение 350мс после исчезновения маски пользователь видит, что элемент под кнопкой нажат и не реагирует, если у пользователя быстрая рука, он обязательно обнаружит.
-
Делать обнаружение в обработчике событий следующего элемента (с мировым флагом)
вроде тяжело,
Не рекомендуется использовать:Глобальный флаг записывает положение (координатную точку) нажатия кнопки и оценивает координатную точку события в обработчике событий следующего элемента.Если это то же самое, это отвратительный щелчок и он отказывается реагировать.
Это всего лишь идея. Я не проверял. Если это не сработает, просто используйте записанную метку времени для оценки, подождите 350 мс, и тогда будет то же самое, что и
pointer-events
почти -
fastclick
Полезное решение, если вы не против загрузить еще несколько КБ,
Не рекомендуется использовать:, Поскольку кто-то столкнулся с ошибкой, сначала введите библиотеку fastclick, а затем замените все сенсорные события на странице на клик, что на самом деле немного хлопотно. Рекомендуется ввести эти несколько КБ, чтобы решить проблему точечного проникновения. не стоит, лучше воспользоваться первым способом.
Примечание. Предложения по обработке кода следующие:
Вызов preventDefault() при событии touchendЕще одна справочная идея (библиотека с открытым исходным кодом fastclick), отменить событие щелчка и использовать touchend для имитации поведения быстрого щелчка.
Why
Вопрос в том, когда запускается событие клика?
Браузер будет ждать около 300 мс после касания, и если поведение касания отсутствует, будет запущено событие клика. Причина, по которой браузер ожидает около 300 мс, заключается в том, чтобы определить, является ли пользователь двойным нажатием, и не подходит для запуска события щелчка во время двойного нажатия. Можно видеть, что триггер события щелчка представляет собой конец раунда событий касания.
Как было сказано выше, в нативном событии нет тапа, можно сослаться на классическую zepto.js обработку события singleTap (к сожалению, в некоторых браузерах до сих пор существует проблема проникновения по клику). Видно, что время срабатывания события singleTap — после того, как событие touchend не отвечает на отсутствие операций в течение 250 мс, запускается singleTap. Таким образом, феномен проникновения щелчка легко понять.В течение 300 мс, поскольку верхний элемент скрыт или исчез из-за задержки события щелчка, элемент DOM в той же позиции вызывает событие щелчка (если это вход , срабатывает событие фокуса ). В коде это дает нам ощущение, что цель сместилась.
Как справиться с кликами (идеи)
1. PreventDefault(), когда событие touchstart срабатывает при запуске касания. Без сомнения, об этом легко думать, и это также решает проблему в корне. Однако у него есть неизбежный или большой недостаток: элементы DOM на странице больше нельзя прокручивать. Этот метод явно не может удовлетворить наши потребности, но эта идея на самом деле может дать нам больше вдохновения.Например, iscroll позволяет реализовать только горизонтальную прокрутку, а соответствующая реализация здесь не указана.
2. Когда событие touchend срабатывает при завершении касания, preventDefault(). Вроде проблем нет, но к сожалению не все браузеры это поддерживают.
3. Запретить масштабирование страницы. Установив метатеги, можно запретить масштабирование страницы, а некоторым браузерам больше не нужно ждать 300 мс, что приводит к проникновению кликов. Событие щелчка по-прежнему срабатывает, но относительно быстро, поэтому событие щелчка может в некотором смысле заменить событие щелчка за счет опыта для нескольких пользователей (событие щелчка по-прежнему срабатывает медленнее).
<meta name="viewport" content="width=device-width, user-scalable=no">
Мобильный хромиун и iOS 9.3+ могут использовать свойства CSS, чтобы предотвратить масштабирование элементов двойным касанием и отменить задержку перехода по клику:
html { -ms-touch-action: manipulation; touch-action: manipulation;}
4. Подход CSS3 Хотя в основном мы говорим о событиях, необходимо ввести свойство CSS3 — указатели-события.
pointer-events: auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit;
Атрибут pointer-events имеет много значений, наиболее полезными являются auto и none, остальные обслуживают SVG.
Видно, что развитие мобильных терминалов все еще можно использовать.
Атрибуты | имея в виду |
---|---|
auto | По умолчанию события мыши или касания не будут проникать в текущий слой. |
none | Элемент больше не является целевым, а прослушивающий элемент становится нижним элементом (если для дочернего элемента установлено значение auto, нажатие на дочерний элемент продолжит прослушивание событий) |
5. Обработка событий щелчка — наиболее надежное решение для Touch to Click — решить проблему с корнем события щелчка. Используйте js, чтобы оценить призрачный щелчок, а затем предотвратите проникновение щелчка. Этот метод, очевидно, может быть достигнут, но недостатком является то, что вам нужно быть осторожным при предотвращении проникновения кликов, чтобы не привести к тому, что нативные элементы HTML (такие как ссылки, флажки, переключатели) не будут работать должным образом.
С помощью введенных выше параметров touches, targetTouches,changedTouches мы можем построить такойтестовая страница, можно посчитать время проникновения клика и ситуацию, на которую отреагировали.
preventDefault() | Нажмите сквозь время | Нажмите через область | ||||
---|---|---|---|---|---|---|
touchstart | touchend | увеличить страницу | Отключить масштабирование страниц | увеличить страницу | Отключить масштабирование страниц | |
Safari Mobile iOS 5.1.1 | Yes | Yes | 370ms after end | 370msafter end | touchstart | touchstart |
Safari Mobile iOS 6.1.3 | Yes | Yes | 370ms after end | 370msafter end | touchstart | touchstart |
Safari Mobile iOS 7.1.1 | Yes | Yes | 370ms after end | 370msafter end | touchstart | touchstart |
Android 2.3.7 | Yes | No | 410ms after end | 410msafter end | touchstart | touchstart |
Android 4.0.4 | Yes | No | 300ms after end | 10ms after end | touchstart | touchstart |
Android 4.1.2 | Yes | No | 300ms after end | 300msafter end | touchstart | touchstart |
Android 4.2.2 | Yes | No | 300ms after start | 10ms after end | touchstart | touchend |
IE10 Windows Phone 8 | No | No | 310ms after end | 10ms after end | touchend | touchend |
Blackberry 10 | Yes | Yes | 260ms after end | 10ms after end | touchstart | touchstart |
Chrome for iOS | Yes | Yes | 360ms after end | 360msafter end | touchstart | touchstart |
Chrome for Android | Yes | Yes | 300ms after start | 10ms after end | touchstart | touchend |
Firefox for Android | Yes | No | 300ms after end | 10ms after end | touchstart | touchend |
Из этого видно: 1. На проникновение кликов влияет браузер и масштабирование страницы 2. Есть два случая проникновения кликов: 10 мс в быстром случае и 300 мс в медленном случае 3. Вызов preventDefault() во время касания может предотвратить переход по клику в большинстве случаев.