javascript 如何禁用外部元素的滚动?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9256213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to disable scrolling in outer elements?
提问by ericsoco
I have a vertically-scrolling div within a page that also scrolls vertically.
我在一个页面中有一个垂直滚动的 div,它也垂直滚动。
When the child div is scrolled with the mouse wheel and reaches the top or bottom of the scroll bar, the page (body) begins to scroll. While the mouse is over the child div, I'd like the page (body) scroll to be locked.
当用鼠标滚轮滚动子 div 并到达滚动条的顶部或底部时,页面(主体)开始滚动。当鼠标在子 div 上时,我希望页面(正文)滚动被锁定。
This SO post (scroll down to the selected answer)demonstrates the problem well.
这篇 SO 帖子(向下滚动到所选答案)很好地说明了这个问题。
This SO questionis essentially the same as mine, but the selected answer causes my page contents to noticeably shift horizontally as the scrollbar disappears and reappears.
这个 SO 问题与我的基本相同,但所选答案会导致我的页面内容随着滚动条的消失和重新出现而明显水平移动。
I thought there might be a solution that leverages event.stopPropagation(), but couldn't get anything to work. In ActionScript, this kind of thing would be solved by placing a mousewheel handler on the child div that calls stopPropagation() on the event before it reaches the body element. Since JS and AS are both ECMAScript languages, I thought the concept might translate, but it didn't seem to work.
我认为可能有一个利用 event.stopPropagation() 的解决方案,但无法获得任何工作。在 ActionScript 中,这种事情可以通过在子 div 上放置一个鼠标滚轮处理程序来解决,该处理程序在到达 body 元素之前对事件调用 stopPropagation()。由于 JS 和 AS 都是 ECMAScript 语言,我认为这个概念可能会翻译,但它似乎不起作用。
Is there a solution that keeps my page contents from shifting around? Most likely using stopPropagation rather than a CSS fix? JQuery answers are welcome as is pure JS.
是否有解决方案可以防止我的页面内容移动?最有可能使用 stopPropagation 而不是 CSS 修复?欢迎使用 JQuery 答案,就像纯 JS 一样。
采纳答案by ericsoco
here's what i ended up with. very similar to @mrtsherman's answer here, only pure JS events instead of jQuery. i still used jQuery for selecting and moving the child div around, though.
这就是我的结果。非常相似,@ mrtsherman的答案在这里,只有纯粹的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;
}
i've noticed the scrolling doesn't match normal scrolling exactly; it seems to scroll a bit faster than without this code. i assume i can fix by knocking down wheelDeltaY a bit, but it's odd that it would be reported differently by javascript than it's actually implemented by the browser...
我注意到滚动与正常滚动不完全匹配;它似乎比没有此代码的滚动速度要快一些。我想我可以通过稍微降低 wheelDeltaY 来修复,但奇怪的是,javascript 报告的结果与浏览器实际实现的结果不同......
回答by stefan
I usually do it with a small hack listening to the scroll event on the document: it resets the scroll height back to the original one - effectively freezing the document from scrolling but any inner element with overflow: auto will still scroll nicely:
我通常通过一个小技巧来监听文档上的滚动事件:它将滚动高度重置回原始高度 - 有效地冻结文档滚动但任何带有溢出的内部元素:auto 仍将很好地滚动:
var scrollTop = $(document).scrollTop();
$(document).on('scroll.scrollLock', function() {
$(document).scrollTop(scrollTop);
});
and then when I'm done with the inner scroll lock:
然后当我完成内部滚动锁时:
$(document).off('scroll.scrollLock');
the .scrollLock event namespace makes sure I'm not messing with any other event listeners on scroll.
.scrollLock 事件命名空间确保我不会在滚动时弄乱任何其他事件侦听器。
回答by NinjaBeetle
Although this is an old question, here is how I do it with jQuery. This allows you to scroll a list within an outer list, or you can change the outer list to the document to do what the OP asked.
虽然这是一个老问题,但这是我如何使用 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;
}
And you can use it like this:
你可以像这样使用它:
<ul onmousemove="lockScroll('outer-scroller-id')" onmouseout="unlockScroll('outer-scroller-id')">
<li>...</li>
<li>...</li>
</ul>
回答by Kevin
what about this:
那这个呢:
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";
};