问题 iframe阻止了移动Safari上的iScroll滚动


我在我的移动启用网站上使用iScroll(在这里使用iPhone)在div内滚动。

在这个div中,我有一个像这样固定高度的iframe:

<body>
  <div id="iscroller">
    <iframe id="theIframe"></iframe>
    Other stuff
  </div>
</body>

现在,在div内滚动时,一切都按预期工作,但滚动手势时我无法滚动 从iframe开始

这个问题在这里描述得很好: https://github.com/cubiq/iscroll/issues/41

所以,我通过申请使用了该帖子中的css解决方法 pointer-events:none 到iframe。

现在滚动效果很好  我无法点击iframe中定义的任何链接,因为iframe上的所有点击/触摸事件似乎都被阻止了 pointer-events: none

所以我认为:

“好的,当用户滚动时,我需要 pointer-events:none。如果是的话   不滚动(而是点击),我必须设置 pointer-events:auto   为了让点击/触摸事件通过。“

所以我这样做了:

CSS

#theIframe{pointer-events:none}

JavaScript的

$("#theIframe").bind("touchstart", function(){
  // Enable click before click is triggered
  $(this).css("pointer-events", "auto");
});

$("#theIframe").bind("touchmove", function(){
  // Disable click/touch events while scrolling
  $(this).css("pointer-events", "none");
});

即使添加这个也行不通:

$("#theIframe").bind("touchend", function(){
  // Re-enable click/touch events after releasing
  $(this).css("pointer-events", "auto");
});

无论我做什么:滚动不起作用或点击iframe内的链接不起作用。

不起作用。有任何想法吗?


8198
2018-03-06 13:43


起源



答案:


我找到了完美的解决方案。适用于iOS和Android。

基本思想是在iframe的顶部放置一个div层。这样滚动工作顺利。

如果用户想要点击/点击该iframe上的元素,我只需点击图层上的点击,保存x和y坐标并在这些坐标上触发iframe内容上的点击事件:

HTML:

<div id="wrapper">
    <div id="layer"></div>
    <iframe id="theIframe"></iframe>
</div>
Other stuff

CSS:

#layer{
    position:absolute;
    opacity:0;
    width:100%;
    height:100%;
    top:0;
    left:0;
    right:0;
    bottom:0;
    z-index:2
}

JavaScript的:

$('#layer').click(function(event){
    var iframe = $('#theIframe').get(0);
    var iframeDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;

    // Find click position (coordinates)
    var x = event.offsetX;
    var y = event.offsetY;

    // Trigger click inside iframe
    var link = iframeDoc.elementFromPoint(x, y);
    var newEvent = iframeDoc.createEvent('HTMLEvents');
    newEvent.initEvent('click', true, true);
    link.dispatchEvent(newEvent);
});

10
2018-03-18 11:10



没有其他办法可以做到这一点?这是一个聪明的方法来做到这一点,但我没有控制iframe,如果它确实改变了我的螺丝,感谢队友:) - jycr753
@ jycr753如果您的用户不需要单击iframe中的链接,则可以使用css属性 pointer-events:none 代替。 - Timo
谢谢,我很感激 - jycr753
如果用户需要能够在iFrame中进行滑动或捏合,该怎么办? - Simon Arnold
@SimonArnold嗯,在iframe中它可以工作,但是所有的触摸事件都被“吸”到了iframe中,所以如果你期望触摸事件(比如滑动和东西)在iframe之外触发(比如在它上面),它不行。 - Timo


答案:


我找到了完美的解决方案。适用于iOS和Android。

基本思想是在iframe的顶部放置一个div层。这样滚动工作顺利。

如果用户想要点击/点击该iframe上的元素,我只需点击图层上的点击,保存x和y坐标并在这些坐标上触发iframe内容上的点击事件:

HTML:

<div id="wrapper">
    <div id="layer"></div>
    <iframe id="theIframe"></iframe>
</div>
Other stuff

CSS:

#layer{
    position:absolute;
    opacity:0;
    width:100%;
    height:100%;
    top:0;
    left:0;
    right:0;
    bottom:0;
    z-index:2
}

JavaScript的:

$('#layer').click(function(event){
    var iframe = $('#theIframe').get(0);
    var iframeDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;

    // Find click position (coordinates)
    var x = event.offsetX;
    var y = event.offsetY;

    // Trigger click inside iframe
    var link = iframeDoc.elementFromPoint(x, y);
    var newEvent = iframeDoc.createEvent('HTMLEvents');
    newEvent.initEvent('click', true, true);
    link.dispatchEvent(newEvent);
});

10
2018-03-18 11:10



没有其他办法可以做到这一点?这是一个聪明的方法来做到这一点,但我没有控制iframe,如果它确实改变了我的螺丝,感谢队友:) - jycr753
@ jycr753如果您的用户不需要单击iframe中的链接,则可以使用css属性 pointer-events:none 代替。 - Timo
谢谢,我很感激 - jycr753
如果用户需要能够在iFrame中进行滑动或捏合,该怎么办? - Simon Arnold
@SimonArnold嗯,在iframe中它可以工作,但是所有的触摸事件都被“吸”到了iframe中,所以如果你期望触摸事件(比如滑动和东西)在iframe之外触发(比如在它上面),它不行。 - Timo


我找到了一个解决方案,它碰巧接近github上已经提到过的其他人,但这对于想要找到这个问题的快速工作分辨率的人来说可能是有用的。

我假设了一些东西,比如只有一个iscroll容器,这里表示为ID。这没有经过适当的测试,需要重构。它在我的项目中工作,但我在这里稍微改变了一下这个例子,但我想你很容易理解你需要做什么:

var $iscroll = $('#iscroll');

document.addEventListener('touchstart', function(e) {

if ($iscroll.find('iframe').length > 0){

    $.each($iscroll.find('iframe'), function(k,v){

        var $parent = $(v).parent().first();

        if ($parent.find('.preventTouch').length == 0){

            $('<div class="preventTouch" style="position:absolute; z-index:2; width:100%; height:100%;"></div>')
                .prependTo($parent);

        };

        $parent
            .css('position', 'relative').css('z-index', 1);

    });

    $iscroll.find('.preventTouch').on('click', function(e){
        e.preventDefault();
        e.stopPropagation();
        return false;
    });

};

};

document.addEventListener('touchend', function(e) {

if ($iscroll.find('iframe').length > 0){

    setTimeout(function(){

        var $iscroll = $('#iscroll');

        $iscroll.find('.preventTouch').remove();
        $iscroll.find('iframe').css('z-index', '');
        $iscroll.find('.preventTouch').off('click');

    }, 400);

};

};

谢谢你的期待!


1
2017-11-08 16:34