Promo / wheel-indicator

Indicates when user makes swipe gesture on a trackpad or mouse wheel
http://promo.github.io/wheel-indicator/
272 stars 41 forks source link

Проблема с дублированием события при одиночном скроллинге #24

Open danilvalov opened 9 years ago

danilvalov commented 9 years ago

Я протестировал на многих Macbook'ах Pro эту проблему - на некоторых она проявляется (где-то с 1 из 20 Macbook Pro возникает данная проблема, и только в Chrome).

Приведу сразу результаты вывода обработки события mousewheel (формат вывода: скрипт: строка - Date().getTime() - event.wheelDelta):

wheel-indicator.js:127 - 1433329389274 - 9
wheel-indicator.js:127 - 1433329389351 - 422
wheel-indicator.js:127 - 1433329389370 - 279
wheel-indicator.js:127 - 1433329389625 - 273
wheel-indicator.js:127 - 1433329389631 - 225
wheel-indicator.js:127 - 1433329389667 - 2655
wheel-indicator.js:127 - 1433329389680 - 78
wheel-indicator.js:127 - 1433329389719 - 138
wheel-indicator.js:127 - 1433329389729 - 62
wheel-indicator.js:127 - 1433329389779 - 110
wheel-indicator.js:127 - 1433329389966 - 372
wheel-indicator.js:127 - 1433329389984 - 18
wheel-indicator.js:127 - 1433329390444 - 140
wheel-indicator.js:127 - 1433329390596 - 3

Как видно, максимальный разрыв между обработкой - 460ms (предпредпоследняя и предпоследняя сроки). Почему происходит такой рывок - не известно. Но он происходит постоянно (9 из 10 прокруток тачем приводят к такому или немного меньшим разрывам).

В примере представлен результат теста с самам длинным разрывом. В остальных случаях он не превышал 300ms (около 150-250 в среднем).

Исправил данную ситуацию, увеличим таймаут в setTimeout() с 150ms, прописанных в скрипте по-умолчанию, до 500ms. Понимаю, что 500ms в каких-то редких случаях может быть много, но до 300ms увеличить таймаут можно без проблем - тогда данная проблема будет возникать на проблемной связке Macbook Pro + Chrome только в каждом 20-м вызове, что делает скрипт намного стабильнее к данной проблеме.

ulitcos commented 9 years ago

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

danilvalov commented 8 years ago

Обычные мышки можно в исключение поставить, используя if (event.deltaMode) { (event.deltaMode имеет значение "0" при скроллинге тачпадом/magic mouse, значение "1" при скроллинге колёсиком мышки, значение "2" при скроллинге Page Up/Down).

И, кстати, прямо очень не хватает пересчёта deltaY на реальные пиксели перед проверкой. А то случайное касание тачпада уже приводило к callback'у. Есть хорошие примеры тут: http://phrogz.net/js/wheeldelta.html http://stackoverflow.com/a/30134826 (этот даже лучше)

Но в принципе можно для лёгкой правки использовать deltaMode просто по значению:

        if (!event.deltaMode && Math.abs(delta) < 30) {
            return;
        }

(этот кусок кода нужно вставить сюда https://github.com/Promo/wheel-indicator/blob/master/lib/wheel-indicator.js#L115 ).

Так при таче (в частности, использовании Magic Mouse) будет определяться направление только после значительного усилия, а не при случайном касании тачпада или Magic Mouse, а события колёсика мышки, Page Up/Down и остальные сразу будут пропускаться вперёд.

И лучше это значение ("30" из примера) перекинуть в параметры, чтобы сменить можно было в зависимости от нужд.

f0rmat1k commented 8 years ago

И, кстати, прямо очень не хватает пересчёта deltaY на реальные пиксели перед проверкой. А то случайное касание тачпада уже приводило к callback'у.

Ну в этом и идея, чтоб срабатывал на любое касание. Как отличить случайное от неслучайного? Вдруг юзер просто так мотает. Проверил работу функцию чуваков из ФБ, действительно работает, спасибо. Я думаю, мы сделаем опцию, позволяющую указать нужную чувствительность.

f0rmat1k commented 8 years ago

e.deltaMode работает только в FF, точнее только в нем возвращает единичку у обычных колес мыши.