如何禁用外部元素的滚动?

问题描述 投票:0回答:5

我的页面中有一个垂直滚动的 div,它也可以垂直滚动。

当子div用鼠标滚轮滚动并到达滚动条的顶部或底部时,页面(body)开始滚动。当鼠标悬停在子 div 上时,我希望页面(主体)滚动被锁定。

这篇SO帖子(向下滚动到所选答案)很好地演示了这个问题。

这个问题本质上与我的相同,但是所选答案会导致我的页面内容随着滚动条消失和重新出现而明显水平移动。

我认为可能有一个利用 event.stopPropagation() 的解决方案,但无法让任何东西发挥作用。在 ActionScript 中,这种问题可以通过在子 div 上放置一个鼠标滚轮处理程序来解决,该处理程序在事件到达 body 元素之前调用 stopPropagation() 。由于 JS 和 AS 都是 ECMAScript 语言,我认为这个概念可以翻译,但似乎行不通。

是否有解决方案可以防止我的页面内容移动?最有可能使用 stopPropagation 而不是 CSS 修复?欢迎使用 JQuery 答案,就像纯 JS 一样。

javascript html scroll stoppropagation
5个回答
4
投票

这就是我最终得到的结果。与 @mrtsherman 的答案here非常相似,只有纯 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的报告与浏览器实际实现的不同......


1
投票

我通常用一个小技巧来监听文档上的滚动事件:它将滚动高度重置回原始高度 - 有效地冻结文档滚动,但任何带有溢出的内部元素:auto仍然会很好地滚动:

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

然后当我完成内部滚动锁时:

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

.scrollLock 事件命名空间确保我不会干扰滚动上的任何其他事件侦听器。


0
投票

虽然这是一个老问题,但这是我如何使用 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>

0
投票

根据@Wildhoney的评论,现在执行此操作的方法是使用

overscroll-behavior: contain

.overscroll-contain {
  overscroll-behavior: contain;
}

#outerScroll {
  height: 150px;
  width: 200px;
  overflow: auto;
  background: red;
}

#innerScroll {
  height: 100px;
  width: 100px;
  background: blue;
  overflow: auto;
}

.large-child {
  height: 500px;
}
<div id="outerScroll">
  <div id="innerScroll" class="overscroll-contain">
    <div class="large-child"></div>
  </div>
  <div class="large-child"></div>
</div>


-2
投票

这个怎么样:

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";
};
© www.soinside.com 2019 - 2024. All rights reserved.