Запрет scrollTop от вызова события прокрутки

Я пытаюсь создать такое поведение: когда пользователь прокручивает колесо мыши (или нажимает ), веб-страница прокручивается вниз по высоте окна.

Я получил следующий код:

var newScrollTop,
    oldScrollTop = $(window).scrollTop(),
    preventScroll = false;
$(window).scroll(function() {
    if (!preventScroll) {
        preventScroll = true;
        newScrollTop = $(this).scrollTop();
        if (newScrollTop > oldScrollTop) {
            $(this).scrollTop( oldScrollTop + $(window).height() );
        }
        else {
            $(this).scrollTop( oldScrollTop - $(window).height() );
        }
        oldScrollTop = newScrollTop;
        preventScroll = false;
    }
});

Но это работает не так, как я ожидаю: на странице события прокрутки прокручивается до самого края (внизу или вверху). Что мне не хватает?

2 ответа

Решение

Нет простого способа переопределить функцию прокрутки браузера по умолчанию. Вот один из способов сделать то, что вы хотите, но для управления колесом прокрутки мыши требуется плагин jquery- mousewheel Брэндона Аарона:

$(function() {
    // Ugly hack to disable browser scrolling (downside: hides scrollbar!!!)
    $('html').css('overflow', 'hidden');

    // Get viewport height by which to scroll (up or down)
    var viewportHeight = $(window).height();

    // Recache viewport height on browser resize
    $(window).on('resize', function() {
        viewportHeight = $(window).height();
    });

    // Scroll on mousewheel
    $('html').on('mousewheel', function(event, delta, deltaX, deltaY) {
        // scroll down
        if (deltaY < 0)
            window.scrollBy(0, viewportHeight);
        // scroll up
        else
            window.scrollBy(0, -viewportHeight);
    });

    // Disable document keypress event
    // which would scroll the content even with "overlow: hidden"
    $(document).on('keypress', function(){
        return false;
    });

    // Scroll on arrow up/down keys
    $(document).on('keydown', function(event){
        // arrow down key
        if (event.which == 40)
            window.scrollBy(0, viewportHeight);
        // arrow up key
        if (event.which == 38)
            window.scrollBy(0, -viewportHeight);
    });
});

Вот скрипка для демонстрации кода. Все это работает очень хорошо, за исключением одного неприятного недостатка моего решения. $('html').css('overflow', 'hidden'); удаляет полосу прокрутки браузера.

Проблема в том, что вы используете scrollTop() которые запускают событие прокрутки внутри самого события прокрутки окна.

Таким образом, в основном, с кодом, который вы написали, вы запускаете бесконечный цикл, потому что как только первое событие прокрутки запускается, другое запускается scrollTop() в то время как ваш preventScroll переменная все еще не установлена ​​в ложь и так далее.

Чтобы ваш код работал, вам нужно установить preventScroll переменная к false внутри функции setTimeout вот так:

var newScrollTop,
    oldScrollTop = $(window).scrollTop(),
    preventScroll = false;

$(window).scroll(function() {
    if (!preventScroll) {
        preventScroll = true;
        newScrollTop = $(this).scrollTop();
        if (newScrollTop > oldScrollTop) {
            $(this).scrollTop( oldScrollTop + $(window).height() );
        }
        else {
            $(this).scrollTop( oldScrollTop - $(window).height() );
        }
        oldScrollTop = newScrollTop;

        setTimeout(function(){ preventScroll = false; }, 0);
    }
});

Мы добавляем некоторую "задержку", прежде чем мы установим preventScroll в false, Таким образом, когда вы звоните scrollTop()preventScroll переменная по-прежнему будет иметь значение true!

Вот рабочая скрипка: http://jsfiddle.net/J6Fcm/ (я немного изменил ваш код, чтобы позволить шагам прокрутки работать как положено)

Другие вопросы по тегам