Как обнаружить / отключить инерционную прокрутку в Mac Safari? - PullRequest
19 голосов
/ 02 декабря 2010

Есть ли способ отключить или обнаружить, что события колеса происходят из настройки "инерция" на Mac?

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

Ответы [ 7 ]

4 голосов
/ 09 декабря 2011

Да и нет.

Вы можете использовать касание / вверх и прокручивать как события для поиска движущейся страницы, но они не сработают, если ОС выполняет инерционную прокрутку. Веселье, верно?

Одна вещь, которую вы можете постоянно обнаруживать, это window.pageYOffset. Это значение будет изменяться, пока происходит инерционная прокрутка, но не генерирует событие. Таким образом, вы можете придумать набор таймеров для проверки инерционной прокрутки и продолжения работы до тех пор, пока страница не перестанет двигаться.

Хитрый материал, но он должен работать.

3 голосов
/ 16 марта 2012

О, как этот вопрос убивает меня: /

Я нахожусь в процессе создания "бесконечной" прокрутки для просмотра больших файлов.

Что еще хуже, этот редактор встроен в страницу, которая имеет собственную полосу прокрутки, потому что она больше, чем один экран.

U использует прокрутку overflow-x для горизонтальной прокрутки, но для вертикальной прокрутки мне нужна текущая подсветка строки (как видно в большинстве современных IDE), поэтому я использую плагин jquery mousewheel и прокручиваю движущийся контент для высоты строки вверх или вниз.

Он отлично работает на Ubuntu / Chrome, но иногда на MacOS Lion / Chrome, а иногда и просто, когда вы прокручиваете, это не мешает прокрутке по умолчанию на элементе редактора, и событие распространяется «вверх», и страница сама начинает прокручиваться.

Я даже не могу описать, насколько это раздражает.

Что касается инерциальной прокрутки, я успешно уменьшил ее с двумя таймерами

var self = this;
// mouse wheel events
    $('#editorWrapper').mousewheel(function (event, delta, deltax, deltay) {

        self._thisScroll = new Date().getTime();


        //
        //this is entirely because of Inertial scrolling feature on mac os :(
        //
        if((self._thisScroll - self._lastScroll) > 5){
            //
            //
            // NOW i do actual moving of content
            //
            //

            self._lastScroll = new Date().getTime(); 
        }

5 мс - это значение, которое, как мне показалось, наиболее естественно на моем MacBook Pro, и вам нужно очень быстро прокрутить колесо мыши, чтобы поймать одного из них ..

Тем не менее, иногда на слушателе Mac на оболочке Mac не предотвращается использование по умолчанию, и страница прокручивается вниз.

2 голосов
/ 31 октября 2017

Есть библиотека, которая решает эту проблему.

https://github.com/d4nyll/lethargy

После установки используйте его так:

var lethargy = new Lethargy();

$(window).bind('mousewheel DOMMouseScroll wheel MozMousePixelScroll', function(e){
  if(lethargy.check(e) === false) {
    console.log('stopping zoom event from inertia')
    e.preventDefault()
    e.stopPropagation();
  }
  console.log('Continue with zoom event from intent')
});
2 голосов
/ 17 апреля 2015

Я не уверен насчет других браузеров, но во время инерционной прокрутки на моем Chrome, FF, Safari (mac) возникает следующее событие:

var mousewheelevt=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel";
function scrollEE (e) {
    console.log(e);
}
window.addEventListener(mousewheelevt, scrollEE, false);
2 голосов
/ 10 декабря 2010

Ну, (я могу ошибаться), я думаю, что настройки "инерции" на Mac все вычисляются самой системой, браузером или любой другой программой, которая просто думает, что пользователь быстро прокручивает,вместо того, чтобы замедляться.

1 голос
/ 22 марта 2018

Я нашел решение, которое действительно хорошо для этого работает. Ниже приведен некоторый вставленный код из моего проекта. Это в основном сводится к этой логике:

Событие прокрутки происходит от человека, когда ЛЮБОЕ из этих условий выполняется:

  • Направление противоположное предыдущему
  • Прошло более 50 миллисекунд с момента последнего события прокрутки (выбрано 100 мс, чтобы быть уверенным)
  • Значение дельты, по крайней мере, такое же, как и предыдущее

Так как спам в Mac прокручивает события с уменьшением дельты в браузер каждые 20 мс, когда включена инерционная прокрутка, это довольно надежный способ. У меня никогда не было неудачи по крайней мере. Просто проверка времени с момента последней прокрутки не сработает, потому что пользователь не сможет снова прокрутить, если «виртуальное свободное колесо» все еще работает, даже если они не прокручивались в течение 3 секунд.

this.minScrollWheelInterval = 100; // minimum milliseconds between scrolls
this.animSpeed = 300;

this.lastScrollWheelTimestamp = 0;
this.lastScrollWheelDelta = 0;
this.animating = false;

document.addEventListener('wheel',
    (e) => {

        const now = Date.now();

        const rapidSuccession = now - this.lastScrollWheelTimestamp < this.minScrollWheelInterval;
        const otherDirection = (this.lastScrollWheelDelta > 0) !== (e.deltaY > 0);
        const speedDecrease = Math.abs(e.deltaY) < Math.abs(this.lastScrollWheelDelta);

        const isHuman = otherDirection || !rapidSuccession || !speedDecrease;

        if (isHuman && !this.animating) {
            this.animating = true; // current animation starting: future animations blocked
            $('.something').stop().animate( // perform some animation like moving to the next/previous page
                {property: value},
                this.animSpeed,
                () => {this.animating = false} // animation finished: ready for next animation
            )
        }

        this.lastScrollWheelTimestamp = now;
        this.lastScrollWheelDelta = e.deltaY;

    },
    {passive: true}
);

Кстати, есть одна оговорка: у Mac также есть ускорение при прокрутке, т. Е. Сначала значение дельты выше для каждого последующего события. Кажется, что это не длится более 100 мс или около того, хотя. Так что, если какое-либо действие / анимация, которую вы запускаете в результате события прокрутки, длится не менее 100 мс и блокирует все другие действия / анимации за это время, это никогда не будет проблемой .

1 голос
/ 16 мая 2014

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

var currentY = 0;
var previousY = 0;
var lastKnownVelocity = 0;
var velocityRating = 1;
function calculateVelocity() {
    previousY = currentY;
    currentY = $('#content').scrollTop();
    lastKnownVelocity = previousY - currentY;
    if (lastKnownVelocity > 20 || lastKnownVelocity < -20) {
        velocityRating = 5;
    } else {
        velocityRating = 1;
    }
}

$('#content').scroll(function () {
    // get velocity while scrolling...
    calculateVelocity();
    // wait until finished scrolling...
    clearTimeout($.data(this, 'scrollTimer'));
    $.data(this, 'scrollTimer', setTimeout(function() {
        // do your animation
        $('#content').animate({scrollTop: snapPoint}, 300);
    }, 300*velocityRating)); // short or long duration...
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...