iOS 如果鼠标下的元素只有 "overflow-y: scroll" 并且水平滚动,Safari 似乎永远不会触发滚动事件

iOS Safari appears to never fire scroll event if the element under mouse has only "overflow-y: scroll" and scrolling horizontally

我有两个元素,一个 parent 节点和 child。 child 只能垂直滚动 (overflow: hidden; overflow-y: scroll;)。 parent 只能水平滚动 (overflow: hidden; overflow-x: scroll;)。当我在 child 节点上横向滑动时,尽管这样做也没有触发任何滚动事件:

//NEITHER of these are fired when swiping sideways on the child
child.addEventListener( "scroll", listener, true );
parent.addEventListener( "scroll", listener2, true );

如果我在 child 上垂直滚动,浏览器 触发滚动事件! listener listener2 都没有被调用!如果 child 元素只有一个方向滚动,我如何让它为 parent 元素触发水平滚动?

Fiddle 手机示例:https://jsfiddle.net/cn2hfLok/2/embedded/result/

HTML:

<div class="parent">
    <div class="child">
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
    </div>
    <div style="width: 5000px;">s</div>
</div>

CSS:

.parent
{
    position:relative;
    width: 600px;
    height: 100%;
    background-color: yellow;
    overflow: hidden;
    overflow-x: scroll;
}

.child
{
    position:relative;
    width: 50%;
    height: 200px;
    background-color: blue;
    overflow: hidden;
    overflow-y: scroll;
}

JavaScript:

function scrollC(e)
{
    console.log( "child" );
}

function scrollP(e)
{
    console.log( "parent" );
}

document.querySelector( ".child" ).addEventListener( "scroll", scrollC );
document.querySelector( ".parent" ).addEventListener( "scroll", scrollP );

编辑:即使在 child 上显示 overflow: scroll,如果没有可水平滚动的内容,它 仍然 不会'不要触发滚动事件! https://jsfiddle.net/cn2hfLok/4/embedded/result/

我认为你应该朝着以下方向前进:

  1. 为处理程序启用捕获阶段:document.querySelector( ".parent" ).addEventListener( "scroll", scrollP, true );

  2. 在父回调中停止传播:e.stopPropagation();

在这种情况下,父级的侦听器将拦截所有事件,包括 horizontal scroll。但实际上你可以通过 event.type 和一堆其他可访问的属性来过滤它们。

这是更新后的示例:https://jsfiddle.net/cn2hfLok/7/

如果 child 在您尝试移动的方向上没有可滚动的内容,或者它没有,则无法在 iOS Safari 上为 parent 捕获滚动事件听那个方向。为了克服这个问题,您需要监听 child 上的触摸事件,然后通过更改 parent 的 scrollLeft 或 [=11] 将该移动传递给 parent =] 这将触发 parent 的滚动事件处理程序。

收听:

touchstart

夺取起始位置

touchmove

根据开始检查当前位置,如果它水平移动(并且垂直移动足够小),然后通过 parent.scrollLeft += startX - e.clientX; 传递给 parent 然后调用 e.stopPropagation();e.preventDefault(); 所以它不会' 移动页面。 (同时将您的 startX 更新为 e.clientX

touchendtouchleave

设置一些变量来告诉您的 touchmove 处理程序停止监听,例如 notDragging = true;