Устранение задержки 300 мс при кликах в мобильном Safari

89

Я читал, что мобильное Safari имеет задержку 300 мс для событий щелчка с момента нажатия ссылки / кнопки до момента срабатывания события. Причина задержки заключается в том, чтобы дождаться, чтобы увидеть, собирается ли пользователь дважды щелкнуть мышью, но с точки зрения UX ожидание 300 мс часто нежелательно.

Одним из решений для устранения этой задержки в 300 мс является использование обработки «касанием» jQuery Mobile. К сожалению, я не знаком с этим фреймворком и не хочу загружать какой-то большой фреймворк, если все, что мне нужно, это одна или две строки кода, применяемых touchendправильным образом.

Как и на многих других сайтах, на моем сайте много таких событий кликов:

$("button.submitBtn").on('click', function (e) {   
  $.ajaxSubmit({... //ajax form submisssion
});

$("a.ajax").on('click', function (e) {   
  $.ajax({... //ajax page loading
});

$("button.modal").on('click', function (e) {   
      //show/hide modal dialog
});

и что я хотел бы сделать, так это избавиться от задержки в 300 мс для ВСЕХ этих событий щелчка, используя один фрагмент кода, например:

$("a, button").on('tap', function (e) {
 $(this).trigger('click');
 e.preventDefault();
});

Это плохая / хорошая идея?

Тим Петерсон
источник
@Pointy, спасибо, это может сработать ...
Тим Петерсон
«… очевидно, что это не очень хорошо с точки зрения UX». Я бы с осторожностью отнесся к этому предположению.
Оливер Моран,
1
@OliverMoran, спасибо за исправление, я только что отредактировал это предложение, см. Вопрос выше ..
Тим Петерсон
1
может быть решением: stackoverflow.com/a/12969739/1491212
Armel Larcier

Ответы:

73

Теперь некоторые мобильные браузеры устраняют задержку нажатия 300 мс, если вы устанавливаете область просмотра. Вам больше не нужно использовать обходные пути.

<meta name="viewport" content="width=device-width, user-scalable=no">

В настоящее время поддерживается Chrome для Android , Firefox для Android и Safari для iOS.

Однако в iOS Safari двойное касание - это жест прокрутки на не масштабируемых страницах. По этой причине они не могут убрать задержку в 300 мс . Если они не могут удалить задержку на не масштабируемых страницах, они вряд ли удалят ее на масштабируемых страницах.

Телефоны Windows также сохраняют задержку 300 мс на не масштабируемых страницах, но у них нет альтернативного жеста, такого как iOS, поэтому они могут удалить эту задержку, как это имеет Chrome.Вы можете удалить задержку на Windows Phone, используя:

html {
-ms-touch-action: manipulation;
touch-action: manipulation;
}

Источник: http://updates.html5rocks.com/2013/12/300ms-tap-delay-gone-away

ОБНОВЛЕНИЕ 2015 Декабрь

До сих пор WebKit и Safari на iOS имели задержку в 350 мс перед тем, как одно касание активирует ссылки или кнопки, чтобы люди могли увеличивать страницы двойным касанием. Chrome изменил это уже пару месяцев назад, используя более умный алгоритм для обнаружения этого, и WebKit будет следовать аналогичному подходу . В статье дается отличное понимание того, как браузеры работают с сенсорными жестами и как браузеры могут стать намного умнее, чем сегодня.

ОБНОВЛЕНИЕ 2016 Март

В Safari для iOS время ожидания 350 мс для обнаружения второго касания было удалено, чтобы создать ответ «быстрое касание». Это включено для страниц, объявляющих область просмотра с шириной = ширина устройства или масштабируемой пользователем = no. Авторы также могут выбрать поведение быстрого касания для определенных элементов с помощью CSS, touch-action: manipulationкак описано здесь (прокрутите вниз до заголовка «Стилизация поведения при быстром касании») и здесь .

NoNameProvided
источник
На самом деле, для WP есть сенсорные события: stackoverflow.com/questions/13396297/…
Седрик Райхенбах
1
Да, который управляется -ms-touch-action, как я написал в своем сообщении.
NoNameProvided
1
Проблема все еще существует в iOS при запуске приложения с домашней страницы (автономно). Если бы кто-нибудь нашел достойное решение для этого, он был бы очень рад
Мигель Гуардо
1
Установка значений сенсорного действия для манипуляции ближе всего к желаемой производительности, но, как ранее заявлял @MiguelGuardo, эффект теряется, когда вы добавляете веб-страницу на свой домашний экран в iOS в качестве отдельного приложения.
T. Steele
Может быть, кто-то может взломать UIWebView - stackoverflow.com/questions/55155560/…
Eazy
43

Этот плагин -FastClick, разработанный Financial Times, сделает это за вас!

Обязательно добавьте event.stopPropagation();и / или event.preventDefault();сразу после функции щелчка, иначе она может работать дважды, как для меня, то есть:

$("#buttonId").on('click',function(event){
    event.stopPropagation(); event.preventDefault();
   //do your magic

});
Джонатан
источник
3
Это не идеально, если вы используете jquery mobile (в любом случае версия 1.3.2), он нарушает закрытие виджета панели github.com/jquery/jquery-mobile/issues/6440
ryan0
именно поэтому event.stopPropagation () я и пришел на эту страницу. Отлично работает, спасибо!
Lukas
@Jonathan fastclickтворит свое волшебство только на сенсорных устройствах, у которых есть проблема с задержкой (иначе она автоматически игнорируется ). Однако простое добавление stopPropagation& preventDefaultпосле каждого события щелчка может иметь нежелательные побочные эффекты для всех обработчиков событий во всех браузерах.
пользователь
17

Я знаю, что это устарело, но не могли бы вы просто проверить, поддерживается ли сенсорный ввод в браузере? Затем создайте переменную "touchend" или "click" и используйте эту переменную в качестве события, связанного с вашим элементом?

var clickOrTouch = (('ontouchend' in window)) ? 'touchend' : 'click';
$('#element').on(clickOrTouch, function() {
    // do something
});

Итак, этот пример кода проверяет, поддерживается ли в браузере событие «touchhend», а если нет, то мы используем событие «click».

(Редактировать: изменено "touchend" на "ontouchend")

Майкл Тернуолл
источник
Спасибо, мне нравится простота этого. Я хотел бы, чтобы другие говорили о его возможных ловушках.
Тим Петерсон
4
Событие touchend не может заменить событие щелчка, потому что @Andreas Köberle объясняет в своем ответе. Например, если вы прокручиваете и ваш палец останавливается на кнопке, ссылка активируется ...
Адриенденат
Это отличное легкое решение без необходимости включать большую жирную дополнительную библиотеку, чтобы избавиться от задержки. Хотел бы я проголосовать 5 раз за это! (при условии, что вас не беспокоит сценарий прокрутки!)
tonjac
2
Для компьютеров / браузеров с поддержкой событий касания и щелчка это плохое решение.
Александр О'Мара
1
Некоторые устройства поддерживают события касания и щелчка, и вы хотите, чтобы они оба срабатывали в разных ситуациях. Мы сталкивались с ситуациями, когда некоторые окна или планшеты Android с мышью, очевидно, запускают событие щелчка, когда вы нажимаете на объект, но оно также запускает события касания при нажатии. Это означало, что вам нужно было слушать оба события. В качестве дополнительного усложняющего фактора некоторые устройства будут синтезировать событие щелчка при нажатии, поэтому прослушивание обоих на этих устройствах может привести к двойному срабатыванию обработчика событий, если вы не будете осторожны.
1800 ИНФОРМАЦИЯ
12

Я столкнулся с чрезвычайно популярной альтернативой под названием Hammer.js (страница Github), которая, на мой взгляд, является лучшим подходом.

Hammer.js - это более полнофункциональная сенсорная библиотека (имеет много команд смахивания), чем Fastclick.js (ответ, получивший наибольшее количество голосов).

Однако будьте осторожны : быстрая прокрутка на мобильных устройствах действительно приводит к блокировке пользовательского интерфейса при использовании Hammer.js или Fastclick.js. Это серьезная проблема, если на вашем сайте есть лента новостей или интерфейс, в котором пользователи будут много прокручивать (это похоже на большинство веб-приложений). По этой причине я на данный момент не использую ни один из этих плагинов.

Тим Петерсон
источник
2
Не используйте Hammerjs. У него есть некоторые серьезные проблемы, например: github.com/EightMedia/hammer.js/issues/388 github.com/EightMedia/hammer.js/issues/366 По крайней мере, не используйте его, пока они не будут исправлены
Адонис К. Kakoulidis
2

Почему-то отключение масштабирования, кажется, отключает эту небольшую задержку. Имеет смысл, поскольку в этом случае двойное нажатие больше не требуется.

Как я могу «отключить» масштабирование мобильной веб-страницы?

Но имейте в виду, какое влияние это окажет на удобство использования. Это может быть полезно для веб-страниц, разработанных как приложения, но не должно использоваться для более общих «статических» страниц. ИМХО. Я использую его для домашнего проекта, которому нужна низкая задержка.

айке
источник
1

К сожалению, нет простого способа сделать это. Таким образом, простое использование touchstartили touchendоставит у вас другие проблемы, например, при нажатии на кнопку кто-то начинает прокрутку. Некоторое время мы пользуемся zepto , и даже с этим действительно хорошим фреймворком со временем возникли некоторые проблемы. Многие из них закрыты , но это не область простого решения.

У нас есть это решение для глобальной обработки кликов по ссылкам:

   $(document.body).
    on('tap', 'a',function (e) {
      var href = this.getAttribute('href');
      if (e.defaultPrevented || !href) { return; }
      e.preventDefault();
      location.href= href;
    }).
    on('click', 'a', function (e) {
      e.preventDefault();
    });
Андреас Кёберле
источник
- @ Андреас, спасибо, что бы вы выступили за то, чтобы не использовать общее tapрешение, которое я опубликовал, и факторизовать tapсобытия по элементам?
Тим Петерсон
Нет, дело не в этом. Дело не в том, чтобы пытаться найти tapрешение самостоятельно. Я обновлю свой ответ.
Андреас Кёберле
- @ Andreas, спасибо за ваш ответ, многие события кликов являются AJAX, поэтому событие по умолчанию уже предотвращено. Не могли бы вы обновить свой ответ, чтобы справиться с этим? Казалось бы, мое общее tapрешение в этом случае будет выглядеть так же, как ваше?
Тим Петерсон
1

Я искал простой способ без jquery и без библиотеки fastclick. Это работает для меня:

var keyboard = document.getElementById("keyboard");
var buttons = keyboard.children;
var isTouch = ("ontouchstart" in window);
for (var i=0;i<buttons.length;i++) {
    if ( isTouch ) {
        buttons[i].addEventListener('touchstart', clickHandler, false);         
    } else {
        buttons[i].addEventListener('click', clickHandler, false);          
    }
}
Ярда Павличек
источник
0

Просто чтобы предоставить дополнительную информацию.

В iOS 10 <button>не удавалось запускать s на моей странице постоянно. Всегда было отставание.

Я попробовал fastclick / Hammer / tapjs / заменить щелчок на touchstart, все не удалось.

ОБНОВЛЕНИЕ: причина вроде в том, что кнопка слишком близко к краю! переместите его ближе к центру и отставание исчезнет!

theaws.blog
источник
0

Вы должны явно объявить пассивный режим :

window.addEventListener('touchstart', (e) => {

    alert('fast touch');

}, { passive : true});
Бруно Андраде
источник
0

В jQuery вы можете привязать событие «touchhend», запускающий код сразу после нажатия (это похоже на нажатие клавиши на клавиатуре). Проверено на текущих версиях планшетов Chrome и Firefox. Не забудьте также "щелкнуть" для ваших ноутбуков с сенсорным экраном и настольных устройств.

jQuery('.yourElements').bind('click touchend',function(event){

    event.stopPropagation();
    event.preventDefault();

	// everything else
});

Бенджамин
источник