Как отключить прокрутку внешних элементов?

У меня есть div с вертикальной прокруткой внутри страницы, которая также прокручивается по вертикали.

когда дочерний div прокручивается колесиком мыши и достигает верхней или нижней части полосы прокрутки, страница (тело) начинает прокручиваться. Пока мышь находится над дочерним div, я хотел бы, чтобы прокрутка страницы (тела) была заблокирована.

это сообщение SO (прокрутите вниз до выбранного ответа) демонстрирует проблему.

это так вопрос is по сути, то же самое, что и мой, но выбранный ответ заставляет содержимое моей страницы заметно смещаться по горизонтали, когда полоса прокрутки исчезает и появляется.

Я думал, что там может быть решение, которое использует событие.stopPropagation(), но ничего не смог заставить работать. В ActionScript такие проблемы решаются путем размещения обработчика mousewheel на дочернем div, который вызывает stopPropagation () на событии, прежде чем оно достигнет элемента body. Поскольку JS и AS оба ECMAScript языки, я думал, что концепция может перевести, но, похоже, это не сработало.

есть ли решение, которое удерживает содержимое моей страницы от перемещения? Скорее всего, используя stopPropagation, а не исправление CSS? Ответы JQuery приветствуются, как и чистый JS.

4 ответов


вот что я закончил. очень похоже на ответ @mrtsherman's здесь, только чистые события JS вместо jQuery. однако я все еще использовал jQuery для выбора и перемещения ребенка div.

// earlier, i have code that references my child div, as childDiv

function disableWindowScroll () {
    if (window.addEventListener) {
        window.addEventListener("DOMMouseScroll", onChildMouseWheel, false);
    }
    window.onmousewheel = document.onmousewheel = onChildMouseWheel;
}

function enableWindowScroll () {
    if (window.removeEventListener) {
        window.removeEventListener("DOMMouseScroll", onArticleMouseWheel, false);
    }
    window.onmousewheel = document.onmousewheel = null;
}

function onChildMouseWheel (event) {
    var scrollTgt = 0;
    event = window.event || event;
    if (event.detail) {
        scrollTgt = -40 * event.detail;
    } else {
        scrollTgt = event.wheelDeltaY;
    }

    if (scrollTgt) {
        preventDefault(event);
        $(childDiv).scrollTop($(childDiv).scrollTop() - scrollTgt);
    }
}

function preventDefault (event) {
    event = event || window.event;
    if (event.preventDefault) {
        event.preventDefault();
    }
    event.returnValue = false;
}

Я заметил, что прокрутка не соответствует нормальной прокрутке точно; кажется, прокрутка немного быстрее, чем без этого кода. я предполагаю, что могу исправить, сбив wheelDeltaY немного, но странно, что это будет сообщено иначе javascript, чем это фактически реализован браузером...


обычно я делаю это с помощью небольшого Хака, слушающего событие прокрутки в документе: он сбрасывает высоту прокрутки обратно в исходный - эффективно замораживает документ от прокрутки, но любой внутренний элемент с переполнением: auto все равно будет прокручиваться красиво:

var scrollTop = $(document).scrollTop();
$(document).on('scroll.scrollLock', function() {
  $(document).scrollTop(scrollTop);
});

а затем, когда я закончу с внутренней блокировкой прокрутки:

$(document).off('scroll.scrollLock');

the .пространство имен событий scrollLock гарантирует, что я не связываюсь с другими прослушивателями событий при прокрутке.


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

window.scrollLockHolder = null;
function lockScroll(id){
    if (window.scrollLockHolder == null){
        window.scrollLockHolder = $('#' + id).scrollTop();
    }
    $('#' + id).on('scroll', function(){
        $('#' + id).scrollTop(window.scrollLockHolder);
    });
}
function unlockScroll(id){
    $('#' + id).off('scroll');
    window.scrollLockHolder = null;
}

и вы можете использовать его как это:

<ul onmousemove="lockScroll('outer-scroller-id')" onmouseout="unlockScroll('outer-scroller-id')">
    <li>...</li>
    <li>...</li>
</ul>

Как насчет этого:

div.onmousemove = function() { // may be onmouseover also works fine
    document.body.style.overflow = "hidden";
    document.documentElement.style.overflow = "hidden";
};

div.onmouseout = function() {
    document.body.style.overflow = "auto";
    document.documentElement.style.overflow = "auto";
};