【问题标题】:How to disable scrolling in outer elements?如何禁用外部元素的滚动?
【发布时间】:2012-03-04 14:24:54
【问题描述】:

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

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

This SO post (scroll down to the selected answer) 很好地说明了这个问题。

This SO question 与我的基本相同,但选择的答案会导致我的页面内容随着滚动条的消失和重新出现而明显水平移动。

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

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

【问题讨论】:

  • 我实际上独立地遇到了与您相同的解决方案(但略有不同 - 您使用 jQuery 事件,我使用纯 JS 事件。无论如何,看起来您的解决方案效果很好,谢谢@ Mrtsherman。

标签: javascript html scroll stoppropagation


【解决方案1】:

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

【讨论】:

【解决方案2】:

我通常通过监听文档上的滚动事件的小技巧来做到这一点:它将滚动高度重置为原始高度 - 有效地冻结文档滚动,但任何内部元素溢出:auto 仍然可以很好地滚动:

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

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

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

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

【讨论】:

  • 不错的解决方案。我尝试了它的细微差别,它工作得很好,除了 IE 10,它在文档上执行两个滚动事件 - 鼠标一个和“重置”一个。这是一个工作示例的链接 - codepen.io/rommguy/pen/EarVwv
  • 陀螺仪,您的代码在 IE11 中无法正常工作 - 使用 div 滚动时,页面(文档)会上下跳跃。丑陋。
【解决方案3】:

这就是我最终的结果。与@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 报告的方式与浏览器实际实现的方式不同......

【讨论】:

  • 您能否详细说明您的答案并解释发生了什么。我对 -40 的部分特别困惑
【解决方案4】:

这个呢:

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";
};

【讨论】:

  • 谢谢,但这正是我所说的我想要避免的...... css 移动我的内容。
  • 对不起我的错误......我有另一个想法,设置div.style.overflow = "hidden";div.onmousewheel = function(event) { event.preventDefault(); // control the scroll offset by setting div.scrollTop dynamically }。这只是我的想法,我还没有实现,你可以试试。
猜你喜欢
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-14
  • 1970-01-01
相关资源
最近更新 更多