滚动DIV元素时如何防止页面滚动?

Rob*_*ght 90 jquery mousewheel

我已经审查并测试了各种功能,以防止身体在div内部滚动,并结合了应该起作用的功能.

$('.scrollable').mouseenter(function() {
    $('body').bind('mousewheel DOMMouseScroll', function() {
        return false;
    });
    $(this).bind('mousewheel DOMMouseScroll', function() {
        return true;
    });
});
$('.scrollable').mouseleave(function() {
    $('body').bind('mousewheel DOMMouseScroll', function() {
        return true;
    });
});
Run Code Online (Sandbox Code Playgroud)
  • 这是停止所有滚动,因为我想在容器内仍然可以滚动
  • 鼠标离开时也不会停用此功能

这样做有什么想法或更好的方法吗?

Šim*_*das 162

更新2:我的解决方案基于完全禁用浏览器的本机滚动(当光标在DIV内时),然后使用JavaScript手动滚动DIV(通过设置其.scrollTop属性).替代和IMO更好的方法是仅选择性地禁用浏览器的滚动以防止页面滚动,而不是DIV滚动.查看下面的Rudie的答案,该答案演示了此解决方案.


干得好:

$( '.scrollable' ).on( 'mousewheel DOMMouseScroll', function ( e ) {
    var e0 = e.originalEvent,
        delta = e0.wheelDelta || -e0.detail;

    this.scrollTop += ( delta < 0 ? 1 : -1 ) * 30;
    e.preventDefault();
});
Run Code Online (Sandbox Code Playgroud)

现场演示: https ://jsbin.com/howojuq/edit?js,output

因此,您手动设置滚动位置,然后只是阻止默认行为(可以滚动DIV或整个网页).

更新1:正如Chris在下面的评论中指出的,在较新版本的jQuery中,delta信息嵌套在.originalEvent对象中,即jQuery不再将其暴露在其自定义Event对象中,我们必须从本机Event对象中检索它.

  • 我用过这个,谢谢!我需要添加这个:`if(e.originalEvent)e = e.originalEvent;` (8认同)
  • @RobinKnight不,似乎不是这样.这是工作演示:http://jsfiddle.net/XNwbt/1/,这里是删除这些行的演示:http://jsfiddle.net/XNwbt/2/ (2认同)
  • @ŠimeVidas我在软件中实现后对此进行了调整.并不重要,但可能会为scroll属性添加一个健全性检查,以防止在元素没有滚动时死锁滚动.`if($(this)[0] .scrollHeight!== $(this).outerHeight()){// yourcode}`只有在有滚动条时才会执行. (2认同)

woj*_*fan 29

如果你不关心与旧的IE版本(<8)的兼容性,你可以制作一个自定义的jQuery插件,然后在溢出的元素上调用它.

这个解决方案优于一个提出的ŠimeVidas,因为它不会覆盖滚动行为 - 它只是在适当时阻止它.

$.fn.isolatedScroll = function() {
    this.bind('mousewheel DOMMouseScroll', function (e) {
        var delta = e.wheelDelta || (e.originalEvent && e.originalEvent.wheelDelta) || -e.detail,
            bottomOverflow = this.scrollTop + $(this).outerHeight() - this.scrollHeight >= 0,
            topOverflow = this.scrollTop <= 0;

        if ((delta < 0 && bottomOverflow) || (delta > 0 && topOverflow)) {
            e.preventDefault();
        }
    });
    return this;
};

$('.scrollable').isolatedScroll();
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!我认为更适合不覆盖默认行为.要跨浏览器支持,可以使用[jQuery Mouse Wheel](https://github.com/brandonaaron/jquery-mousewheel)插件. (2认同)

Rud*_*die 21

我认为有时可以取消mousescroll事件:http://jsfiddle.net/rudiedirkx/F8qSq/show/

$elem.on('wheel', function(e) {
    var d = e.originalEvent.deltaY,
        dir = d < 0 ? 'up' : 'down',
        stop = (dir == 'up' && this.scrollTop == 0) || 
               (dir == 'down' && this.scrollTop == this.scrollHeight-this.offsetHeight);
    stop && e.preventDefault();
});
Run Code Online (Sandbox Code Playgroud)

在事件处理程序中,您需要知道:

  • 滚动方向,
    d = e.originalEvent.deltaY, dir = d < 0 ? 'up' : 'down' 因为正数表示向下滚动
  • 滚动位置
    scrollTop为顶部,scrollHeight - scrollTop - offsetHeight底部

如果你是

  • 向上滚动,和top = 0,或
  • 向下滚动bottom = 0,

取消活动:( e.preventDefault()甚至可能e.stopPropagation()).

我认为最好不要覆盖浏览器的滚动行为.仅在适用时取消.

这可能不是完美的xbrowser,但它不是很难.也许Mac的双滚动方向虽然很棘手......

  • 我如何为设备(平板电脑/手机)实现相同的功能我猜touchmove是绑定事件 (2认同)

小智 18

将下面的 CSS 属性 overscroll-behavior: contain;用于子元素

  • 与这个原生 CSS 规则相比,所有其他解决方案都太过分了。做得很好。 (3认同)