Виключіть затримку 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
Армель Ларсьє

Відповіді:


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 мс для виявлення другого натискання видалено, щоб створити відповідь швидкого натискання. Це включено для сторінок, які оголошують область перегляду з шириною = ширина пристрою або масштабованою користувачем = ні. Автори також можуть вибрати поведінку швидкого натискання на певні елементи, використовуючи CSS, touch-action: manipulationяк описано тут (прокрутіть вниз до заголовка "Стиль поведінки швидкого натискання") і тут .


Насправді у WP є сенсорні події: stackoverflow.com/questions/13396297/…
Седрік Райхенбах,

1
Так, який контролюється -ms-touch-action, як я писав у своєму дописі.
NoName Надано

1
Проблема все ще існує в iOS під час запуску програми з домашньої сторінки (автономно). Якщо хтось знайшов для цього гідне обхідне рішення, це було б дуже вітається
Мігель Гуардо,

1
Встановлення значень сенсорної дії для маніпуляції найближче до бажаної продуктивності, але, як раніше зазначав @MiguelGuardo, ефект втрачається, коли ви додаєте веб-сторінку на домашній екран у iOS як самостійну програму.
Т. Стіл,

Може бути хто - то може зламати 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 () - саме тому я спочатку перейшов на цю сторінку. Працює ідеально, дякую!
Лукас

@Jonathan fastclickробить свою магію лише на сенсорних пристроях, у яких є проблема із затримкою (інакше це автоматично обходить ). Однак просто додавання stopPropagation& preventDefaultпісля кожного натискання події може мати небажаний побічний вплив на всі обробники подій у всіх браузерах.
користувач

17

я знаю, що це старе, але чи не можете ви просто перевірити, чи підтримується у браузері "дотик"? Потім створіть змінну, яка є або “touchend”, або “клацніть” і використовувати цю змінну як подію, яка прив’язується до вашого елемента?

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

Таким чином, зразок коду перевіряє, чи підтримується у браузері подія "touchend", а якщо ні, то ми використовуємо подію "click".

(Редагувати: змінено "touchend" на "ontouchend")


Дякую, мені подобається простота цього. Я хотів би, щоб інші пересмикували можливі підводні камені.
tim peterson

4
Подія touchend не може замінити подію натискання, через те, що пояснює @Andreas Köberle у своїй відповіді. Як, наприклад, якщо ви прокручуєте і пальцем зупиняєтеся на кнопці, це викликає посилання ...
adriendenat

Це дивовижне легке рішення, без необхідності включати велику додаткову бібліотеку речей, щоб просто позбутися затримки. Бажаю, щоб я міг 5 разів проголосувати за цей! (поки вас не турбує сценарій прокрутки!)
tonejac

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

Так чи інакше, вимкнення масштабування, здається, відключає цю невелику затримку. Це має сенс, оскільки тоді подвійне натискання більше не потрібно.

Як я можу "вимкнути" масштабування на мобільній веб-сторінці?

Але, будь ласка, пам’ятайте про вплив цього на зручність використання. Це може бути корисно для веб-сторінок, розроблених як програми, але не повинно використовуватися для більш загальних "статичних" сторінок IMHO. Я використовую його для проекту з домашніми тваринами, який потребує низької затримки.


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 Köberle 02

- @ Andreas, дякую за вашу відповідь, багато клікових подій є AJAX, тому подію за замовчуванням уже запобігається. Чи не могли б Ви оновити свою відповідь, щоб також обробити це? Здавалося б, моє загальне tapрішення в цьому випадку буде виглядати так само, як ваше?
tim peterson 02

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 / замінити click на touchstart, все не вдалося.

ОНОВЛЕННЯ: здається, причина полягає в тому, що кнопка знаходиться занадто близько до краю! перенесіть його поблизу центру і відставайте!


0

Ви повинні явно оголосити пасивний режим :

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

    alert('fast touch');

}, { passive : true});

0

У jQuery ви можете прив'язати подію "touchend", код запуску відьми одразу після натискання (як клавіатура). Перевірено на поточних версіях планшетів Chrome і Firefox. Не забувайте також натискати на ноутбуки та настільні пристрої з сенсорним екраном.

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

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

	// everything else
});

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.