我有一个小的“浮动工具箱”-一个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();
        }
    }
});

当前回答

看看Leland Kwong的代码。

基本思路是将wheeleling事件绑定到子元素上,然后使用子元素的原生javascript属性scrollHeight和jquery属性outerHeight来检测滚动的结束,在此基础上返回false以阻止任何滚动。

var scrollableDist,curScrollPos,wheelEvent,dY;
$('#child-element').on('wheel', function(e){
  scrollableDist = $(this)[0].scrollHeight - $(this).outerHeight();
  curScrollPos = $(this).scrollTop();
  wheelEvent = e.originalEvent;
  dY = wheelEvent.deltaY;
  if ((dY>0 && curScrollPos >= scrollableDist) ||
      (dY<0 && curScrollPos <= 0)) {
    return false;
  }
});

其他回答

不要使用overflow: hidden;在身体。它会自动将所有内容滚动到顶部。也不需要JavaScript。利用overflow: auto;:

HTML结构

<div class="overlay">
    <div class="overlay-content"></div>
</div>

<div class="background-content">
    lengthy content here
</div>

样式

.overlay{
    position: fixed;
    top: 0px;
    left: 0px;
    right: 0px;
    bottom: 0px;
    background-color: rgba(0, 0, 0, 0.8);

    .overlay-content {
        height: 100%;
        overflow: scroll;
    }
}

.background-content{
    height: 100%;
    overflow: auto;
}

在这里玩演示。

我添加这个答案是为了完整性,因为@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上提供了一个工作示例。

使用Brandon Aaron的Mousewheel插件,这是可能的。

这里是一个演示:http://jsbin.com/jivutakama/edit?html,js,output

$(function() {

  var toolbox = $('#toolbox'),
      height = toolbox.height(),
      scrollHeight = toolbox.get(0).scrollHeight;

  toolbox.bind('mousewheel', function(e, d) {
    if((this.scrollTop === (scrollHeight - height) && d < 0) || (this.scrollTop === 0 && d > 0)) {
      e.preventDefault();
    }
  });

});

我能找到的最佳解决方案是监听窗口上的滚动事件,并在子div可见时将scrollTop设置为前一个scrollTop。

prevScrollPos = 0
$(window).scroll (ev) ->
    if $('#mydiv').is(':visible')
        document.body.scrollTop = prevScrollPos
    else
        prevScrollPos = document.body.scrollTop

如果触发大量滚动事件,子div的背景中会有闪烁,所以这可以进行调整,但它几乎不会被注意到,对于我的用例来说已经足够了。

还有一个有趣的技巧,当鼠标悬停在可滚动元素上时,锁定父元素的scrollTop。这样你就不必实现自己的滚轮。

下面是一个防止文档滚动的示例,但它可以针对任何元素进行调整。

scrollable.mouseenter(function ()
{
  var scroll = $(document).scrollTop();
  $(document).on('scroll.trap', function ()
  {
    if ($(document).scrollTop() != scroll) $(document).scrollTop(scroll);
  });
});

scrollable.mouseleave(function ()
{
  $(document).off('scroll.trap');
});