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

当前回答

M.K.在他的回答中提供了一个很棒的插件。插件可以在这里找到。然而,为了完整起见,我认为把它放在AngularJS的一个答案中是一个好主意。

Start by injecting the bower or npm (whichever is preferred) bower install jquery-scrollLock --save npm install jquery-scroll-lock --save Add the following directive. I am choosing to add it as an attribute (function() { 'use strict'; angular .module('app') .directive('isolateScrolling', isolateScrolling); function isolateScrolling() { return { restrict: 'A', link: function(sc, elem, attrs) { $('.scroll-container').scrollLock(); } } } })(); And the important piece the plugin fails to document in their website is the HTML structure that it must follow. <div class="scroll-container locked"> <div class="scrollable" isolate-scrolling> ... whatever ... </div> </div>

属性isolation -scrolling必须包含可滚动类,而且它都需要在滚动容器类或任何您选择的类中,并且锁定类必须级联。

其他回答

我也遇到过类似的情况,我是这样解决的: 所有可滚动的元素使类可滚动。

$(document).on('wheel', '.scrollable', function(evt) {
  var offsetTop = this.scrollTop + parseInt(evt.originalEvent.deltaY, 10);
  var offsetBottom = this.scrollHeight - this.getBoundingClientRect().height - offsetTop;

  if (offsetTop < 0 || offsetBottom < 0) {
    evt.preventDefault();
  } else {
    evt.stopImmediatePropagation();
  }
});

stopImmediatePropagation()确保不从可滚动的子区域滚动父可滚动区域。

下面是它的一个普通JS实现: http://jsbin.com/lugim/2/edit?js,output

M.K.在他的回答中提供了一个很棒的插件。插件可以在这里找到。然而,为了完整起见,我认为把它放在AngularJS的一个答案中是一个好主意。

Start by injecting the bower or npm (whichever is preferred) bower install jquery-scrollLock --save npm install jquery-scroll-lock --save Add the following directive. I am choosing to add it as an attribute (function() { 'use strict'; angular .module('app') .directive('isolateScrolling', isolateScrolling); function isolateScrolling() { return { restrict: 'A', link: function(sc, elem, attrs) { $('.scroll-container').scrollLock(); } } } })(); And the important piece the plugin fails to document in their website is the HTML structure that it must follow. <div class="scroll-container locked"> <div class="scrollable" isolate-scrolling> ... whatever ... </div> </div>

属性isolation -scrolling必须包含可滚动类,而且它都需要在滚动容器类或任何您选择的类中,并且锁定类必须级联。

我从所选的库中绑定了这个:https://github.com/harvesthq/chosen/blob/master/coffee/chosen.jquery.coffee

function preventParentScroll(evt) {
    var delta = evt.deltaY || -evt.wheelDelta || (evt && evt.detail)
    if (delta) {
        evt.preventDefault()
        if (evt.type ==  'DOMMouseScroll') {
            delta = delta * 40  
        }
        fakeTable.scrollTop = delta + fakeTable.scrollTop
    }
}
var el = document.getElementById('some-id')
el.addEventListener('mousewheel', preventParentScroll)
el.addEventListener('DOMMouseScroll', preventParentScroll)

这对我很有用。

值得一提的是,在像reactJS, AngularJS, VueJS等现代框架中,当处理固定位置元素时,这个问题有简单的解决方案。例如侧板或叠加元素。

这种技术被称为“传送门”,这意味着应用程序中使用的一个组件,不需要从你正在使用它的地方实际提取它,将在body元素的底部装载它的子元素,在你试图避免滚动的父元素之外。

注意,它不会避免滚动body元素本身。你可以结合这种技术,在滚动div中安装你的应用程序,以达到预期的结果。

React material-ui中的门户实现示例:https://material-ui-next.com/api/portal/

看看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;
  }
});