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

当前回答

Angular JS指令

我必须封装一个角度指令。以下是其他答案的混搭。在Chrome和Internet Explorer 11上进行了测试。

var app = angular.module('myApp');

app.directive("preventParentScroll", function () {
    return {
        restrict: "A",
        scope: false,
        link: function (scope, elm, attr) {
            elm.bind('mousewheel', onMouseWheel);
            function onMouseWheel(e) {
                elm[0].scrollTop -= (e.wheelDeltaY || (e.originalEvent && (e.originalEvent.wheelDeltaY || e.originalEvent.wheelDelta)) || e.wheelDelta || 0);
                e.stopPropagation();
                e.preventDefault();
                e.returnValue = false;
            }
        }
    }
});

使用

<div prevent-parent-scroll>
    ...
</div>

希望这能帮助下一个从谷歌搜索到这里的人。

其他回答

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

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

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

使用本地元素滚动属性和mousewheel插件的delta值:

$elem.on('mousewheel', function (e, delta) {
    // Restricts mouse scrolling to the scrolling range of this element.
    if (
        this.scrollTop < 1 && delta > 0 ||
        (this.clientHeight + this.scrollTop) === this.scrollHeight && delta < 0
    ) {
        e.preventDefault();
    }
});

jQuery插件模拟自然滚动的Internet Explorer

  $.fn.mousewheelStopPropagation = function(options) {
    options = $.extend({
        // defaults
        wheelstop: null // Function
        }, options);

    // Compatibilities
    var isMsIE = ('Microsoft Internet Explorer' === navigator.appName);
    var docElt = document.documentElement,
        mousewheelEventName = 'mousewheel';
    if('onmousewheel' in docElt) {
        mousewheelEventName = 'mousewheel';
    } else if('onwheel' in docElt) {
        mousewheelEventName = 'wheel';
    } else if('DOMMouseScroll' in docElt) {
        mousewheelEventName = 'DOMMouseScroll';
    }
    if(!mousewheelEventName) { return this; }

    function mousewheelPrevent(event) {
        event.preventDefault();
        event.stopPropagation();
        if('function' === typeof options.wheelstop) {
            options.wheelstop(event);
        }
    }

    return this.each(function() {
        var _this = this,
            $this = $(_this);
        $this.on(mousewheelEventName, function(event) {
            var origiEvent = event.originalEvent;
            var scrollTop = _this.scrollTop,
                scrollMax = _this.scrollHeight - $this.outerHeight(),
                delta = -origiEvent.wheelDelta;
            if(isNaN(delta)) {
                delta = origiEvent.deltaY;
            }
            var scrollUp = delta < 0;
            if((scrollUp && scrollTop <= 0) || (!scrollUp && scrollTop >= scrollMax)) {
                mousewheelPrevent(event);
            } else if(isMsIE) {
                // Fix Internet Explorer and emulate natural scrolling
                var animOpt = { duration:200, easing:'linear' };
                if(scrollUp && -delta > scrollTop) {
                    $this.stop(true).animate({ scrollTop:0 }, animOpt);
                    mousewheelPrevent(event);
                } else if(!scrollUp && delta > scrollMax - scrollTop) {
                    $this.stop(true).animate({ scrollTop:scrollMax }, animOpt);
                    mousewheelPrevent(event);
                }
            }
        });
    });
};

https://github.com/basselin/jquery-mousewheel-stop-propagation/blob/master/mousewheelStopPropagation.js

上面的方法不是那么自然,经过一些谷歌我找到了一个更好的解决方案,不需要jQuery。参见[1]和演示[2]。

var element = document.getElementById('uf-notice-ul'); var isMacWebkit = (navigator.userAgent.indexOf("Macintosh") !== -1 && navigator.userAgent.indexOf("WebKit") !== -1); var isFirefox = (navigator.userAgent.indexOf("firefox") !== -1); element.onwheel = wheelHandler; // Future browsers element.onmousewheel = wheelHandler; // Most current browsers if (isFirefox) { element.scrollTop = 0; element.addEventListener("DOMMouseScroll", wheelHandler, false); } // prevent from scrolling parrent elements function wheelHandler(event) { var e = event || window.event; // Standard or IE event object // Extract the amount of rotation from the event object, looking // for properties of a wheel event object, a mousewheel event object // (in both its 2D and 1D forms), and the Firefox DOMMouseScroll event. // Scale the deltas so that one "click" toward the screen is 30 pixels. // If future browsers fire both "wheel" and "mousewheel" for the same // event, we'll end up double-counting it here. Hopefully, however, // cancelling the wheel event will prevent generation of mousewheel. var deltaX = e.deltaX * -30 || // wheel event e.wheelDeltaX / 4 || // mousewheel 0; // property not defined var deltaY = e.deltaY * -30 || // wheel event e.wheelDeltaY / 4 || // mousewheel event in Webkit (e.wheelDeltaY === undefined && // if there is no 2D property then e.wheelDelta / 4) || // use the 1D wheel property e.detail * -10 || // Firefox DOMMouseScroll event 0; // property not defined // Most browsers generate one event with delta 120 per mousewheel click. // On Macs, however, the mousewheels seem to be velocity-sensitive and // the delta values are often larger multiples of 120, at // least with the Apple Mouse. Use browser-testing to defeat this. if (isMacWebkit) { deltaX /= 30; deltaY /= 30; } e.currentTarget.scrollTop -= deltaY; // If we ever get a mousewheel or wheel event in (a future version of) // Firefox, then we don't need DOMMouseScroll anymore. if (isFirefox && e.type !== "DOMMouseScroll") { element.removeEventListener("DOMMouseScroll", wheelHandler, false); } // Don't let this event bubble. Prevent any default action. // This stops the browser from using the mousewheel event to scroll // the document. Hopefully calling preventDefault() on a wheel event // will also prevent the generation of a mousewheel event for the // same rotation. if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); e.cancelBubble = true; // IE events e.returnValue = false; // IE events return false; }

[1] https://dimakuzmich.wordpress.com/2013/07/16/prevent-scrolling-of-parent-element-with-javascript/

[2] http://jsfiddle.net/dima_k/5mPkB/1/

不要使用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;
}

在这里玩演示。