关于javascript:当鼠标悬停在Firefox中的嵌入式iframe上时,防止父页面滚动

Prevent parent page from scrolling when mouse is over embedded iframe in Firefox

...而不限制iframe内的滚动,也无需专门命名/标记所有可滚动元素。

想象一下嵌入在父页面中的google maps小部件。 放大小部件时,显然您不希望父页面滚动。

我以为对上一个问题的回答解决了这个问题:

While scrolling inside an iframe, the body doesn't know anything about
what happens there. But when iframe scroller reach the bottom or the
top, it pass scrolling to body.

Cancel the event that propagates from the iframe.

但是该解决方案在Firefox中不起作用,因为Firefox在设计上不会将iframe捕获的事件传播到父页面,但奇怪的是它将滚动父页面。 在这里看到jsfiddle。

1
2
3
4
5
6
7
$('body').bind('mousewheel DOMMouseScroll', onWheel);

function onWheel (e){
    if (e.target === iframe)
        e.preventDefault();
    console.log(e);
}

因此,当用户在Firefox中缩放嵌入式iframe中的内容时,如何防止页面滚动?


由于它是Firefox中的错误,因此解决方法是直接使用scroll事件,而不是mousewheel / DOMMouseScroll事件。

我的操作方式:当用户在iframe上输入鼠标时,我将标志设置为true,而当他将鼠标留在其中时,我将其设置回false

然后,当用户尝试滚动但鼠标箭头位于iframe中时,我将阻止父窗口滚动。但是,不幸的是,您不能使用常规的e.preventDefault()方法阻止窗口滚动,因此我们在这里仍然需要另一种解决方法,迫使窗口精确滚动到之前的X和Y位置。

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(function(w) {
    var s = { insideIframe: false }

    $(iframe).mouseenter(function() {
        s.insideIframe = true;
        s.scrollX = w.scrollX;
        s.scrollY = w.scrollY;
    }).mouseleave(function() {
        s.insideIframe = false;
    });

    $(document).scroll(function() {
        if (s.insideIframe)
            w.scrollTo(s.scrollX, s.scrollY);
    });
})(window);

我创建了一个立即执行的函数,以防止在全局范围内定义s变量。

小提琴作品:http://jsfiddle.net/qznujqjs/16/


编辑

由于您的问题没有用jQuery标记(尽管在其中,您已经使用该库显示了代码),所以使用Vanilla JS的解决方案与上述解决方案一样简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(function(w) {
    var s = { insideIframe: false }

    iframe.addEventListener('mouseenter', function() {
        s.insideIframe = true;
        s.scrollX = w.scrollX;
        s.scrollY = w.scrollY;
    });
   
    iframe.addEventListener('mouseleave', function() {
        s.insideIframe = false;
    });

    document.addEventListener('scroll', function() {
        if (s.insideIframe)
            w.scrollTo(s.scrollX, s.scrollY);
    });
})(window);


考虑到所有先决条件,我认为以下是在Firefox中实现此工作的最明智的方法。

div包装您的iframe,该div短一点,可以在其中进行垂直滚动:

1
2
  <iframe id="iframeid" height="200px" width="200px" src="about:blank">
  </iframe>

现在,您可以将iframe垂直居中并每次重新放置
包装器收到一个scroll事件(当用户尝试滚动到框架边缘时会发生):

1
2
3
4
5
6
7
var topOffset = 3;

wrapper.scrollTop(topOffset);

wrapper.on("scroll", function(e) {
    wrapper.scrollTop(topOffset);
});

将此与您先前针对Chrome的修复程序结合使用,它应该涵盖所有主要的浏览器。这是一个工作示例-http://jsfiddle.net/o2tk05ab/5/

唯一未解决的问题是包装div上可见的垂直滚动条。有几种解决方法,例如-隐藏滚动条,但仍然可以滚动


我认为这可以解决您的问题
它解决了我的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    var myElem=function(event){
  return $(event.toElement).closest('.slimScrollDiv')
}

$(document).mouseover(function(e){
     window.isOnSub=myElem(e).length>0



})

$(document).on('mousewheel',function(e){
  if(window.isOnSub){  
console.log(e.originalEvent.wheelDelta);      
    if( myElem(e).prop('scrollHeight')-myElem(e).scrollTop()<=myElem(e).height()&&(e.originalEvent.wheelDelta<0)){

      e.preventDefault()
    }


}

})

用您想要的元素选择器替换" .slimScrollDiv"
防止您的鼠标滚动时父滚动