我有一个小的“浮动工具箱”-一个div的位置:fixed;溢出:汽车。
工作得很好。
但是当滚动到盒子里面(用鼠标滚轮)并到达底部或顶部时,父元素“接管”“滚动请求”:工具箱后面的文档滚动。
-这是恼人的,而不是用户“要求”。
我正在使用jQuery,并认为我可以用event.stoppropagation()停止这种行为:
$(" #工具箱”)。Scroll (function(event){event.stoppropagation()});
它确实进入了函数,但传播仍然发生(文档滚动)
在SO(和谷歌)上搜索这个话题是非常困难的,所以我不得不问:
如何防止滚动事件的传播/冒泡?
编辑:
工作解决方案感谢amustill(和Brandon Aaron的鼠标轮插件在这里:
https://github.com/brandonaaron/jquery-mousewheel/raw/master/jquery.mousewheel.js
$(".ToolPage").bind('mousewheel', function(e, d)
var t = $(this);
if (d > 0 && t.scrollTop() === 0) {
e.preventDefault();
}
else {
if (d < 0 && (t.scrollTop() == t.get(0).scrollHeight - t.innerHeight())) {
e.preventDefault();
}
}
});
新的web开发人员在这里。这对我来说在IE和Chrome浏览器上都很有吸引力。
static preventScrollPropagation(e: HTMLElement) {
e.onmousewheel = (ev) => {
var preventScroll = false;
var isScrollingDown = ev.wheelDelta < 0;
if (isScrollingDown) {
var isAtBottom = e.scrollTop + e.clientHeight == e.scrollHeight;
if (isAtBottom) {
preventScroll = true;
}
} else {
var isAtTop = e.scrollTop == 0;
if (isAtTop) {
preventScroll = true;
}
}
if (preventScroll) {
ev.preventDefault();
}
}
}
不要被行数骗了,其实很简单——只是为了可读性有点啰嗦(自文档代码对吧?)
我还应该提到这里的语言是TypeScript,但和往常一样,将它转换为JS很简单。
我添加这个答案是为了完整性,因为@amustill接受的答案在Internet Explorer中不能正确解决问题。详情请参阅我原始帖子中的评论。另外,这个解决方案不需要任何插件——只需要jQuery。
本质上,代码通过处理鼠标滚轮事件来工作。每个这样的事件都包含一个wheelDelta,它等于它要将可滚动区域移动到的px的数量。如果这个值是>0,那么我们向上滚动。如果wheelDelta <0,则向下滚动。
FireFox: FireFox使用DOMMouseScroll作为事件,并填充originalEvent.detail,其+/-与上面描述的相反。它通常以3为间隔返回滚动,而其他浏览器则以120为间隔返回滚动(至少在我的机器上是这样)。为了纠正,我们只需检测它并乘以-40来归一化。
@amustill的答案是取消事件,如果<div>的滚动区域已经在顶部或底部的最大位置。但是,当增量大于剩余的可滚动空间时,Internet Explorer将忽略已取消的事件。
换句话说,如果你有一个200px高的<div>包含500px的可滚动内容,而当前的scrollTop是400,一个告诉浏览器再滚动120px的鼠标滚轮事件将导致<div>和<body>滚动,因为400 + 120 > 500。
因此,为了解决这个问题,我们必须做一些稍微不同的事情,如下所示:
必备的jQuery代码是:
$(document).on('DOMMouseScroll mousewheel', '.Scrollable', function(ev) {
var $this = $(this),
scrollTop = this.scrollTop,
scrollHeight = this.scrollHeight,
height = $this.innerHeight(),
delta = (ev.type == 'DOMMouseScroll' ?
ev.originalEvent.detail * -40 :
ev.originalEvent.wheelDelta),
up = delta > 0;
var prevent = function() {
ev.stopPropagation();
ev.preventDefault();
ev.returnValue = false;
return false;
}
if (!up && -delta > scrollHeight - height - scrollTop) {
// Scrolling down, but this will take us past the bottom.
$this.scrollTop(scrollHeight);
return prevent();
} else if (up && delta > scrollTop) {
// Scrolling up, but this will take us past the top.
$this.scrollTop(0);
return prevent();
}
});
从本质上讲,这段代码取消了任何会创建不需要的边缘条件的滚动事件,然后使用jQuery将<div>的scrollTop设置为最大值或最小值,这取决于鼠标滚轮事件请求的方向。
由于事件在任何一种情况下都被完全取消,因此它根本不会传播到主体,因此解决了IE以及所有其他浏览器中的问题。
我还在jsFiddle上提供了一个工作示例。
这在AngularJS中是有效的。
在Chrome和Firefox上测试。
.directive('stopScroll', function () {
return {
restrict: 'A',
link: function (scope, element, attr) {
element.bind('mousewheel', function (e) {
var $this = $(this),
scrollTop = this.scrollTop,
scrollHeight = this.scrollHeight,
height = $this.height(),
delta = (e.type == 'DOMMouseScroll' ?
e.originalEvent.detail * -40 :
e.originalEvent.wheelDelta),
up = delta > 0;
var prevent = function() {
e.stopPropagation();
e.preventDefault();
e.returnValue = false;
return false;
};
if (!up && -delta > scrollHeight - height - scrollTop) {
// Scrolling down, but this will take us past the bottom.
$this.scrollTop(scrollHeight);
return prevent();
} else if (up && delta > scrollTop) {
// Scrolling up, but this will take us past the top.
$this.scrollTop(0);
return prevent();
}
});
}
};
})
新的web开发人员在这里。这对我来说在IE和Chrome浏览器上都很有吸引力。
static preventScrollPropagation(e: HTMLElement) {
e.onmousewheel = (ev) => {
var preventScroll = false;
var isScrollingDown = ev.wheelDelta < 0;
if (isScrollingDown) {
var isAtBottom = e.scrollTop + e.clientHeight == e.scrollHeight;
if (isAtBottom) {
preventScroll = true;
}
} else {
var isAtTop = e.scrollTop == 0;
if (isAtTop) {
preventScroll = true;
}
}
if (preventScroll) {
ev.preventDefault();
}
}
}
不要被行数骗了,其实很简单——只是为了可读性有点啰嗦(自文档代码对吧?)
我还应该提到这里的语言是TypeScript,但和往常一样,将它转换为JS很简单。