在另一个 DOM 元素上调度鼠标滚轮事件

Posted

技术标签:

【中文标题】在另一个 DOM 元素上调度鼠标滚轮事件【英文标题】:Dispatch mouse wheel event on another DOM element 【发布时间】:2013-03-09 10:35:58 【问题描述】:

我有一个带有可滚动 div 的网页。 在可滚动 div 之上,我绝对定位了与可滚动 div 的一半重叠的 div。

当我将鼠标光标放在可滚动的 div 上时,我可以用鼠标滚轮滚动它。但是当我将光标移到重叠的 div 上时,鼠标滚轮会停止滚动该 div(这是正确的行为,因为绝对定位的 div 不在可滚动的 div 内)。

问题:如何将绝对定位的 div 接收到的滚动事件传递或分派给这个底层的可滚动 div,以使这个绝对定位的 div 对鼠标滚轮事件“透明”。

我可以让它在 Chrome 中运行,但不能在 IE 和 Firefox 中运行。 如何重写此代码以使其在 IE 和 Firefox 中运行?

if ($.browser.webkit)     
    $(".overlap-container").bind("mousewheel", function (e) 

        var origEvent = e.originalEvent;
        var evt = document.createEvent("WheelEvent");
        evt.initWebKitWheelEvent(
        origEvent.wheelDeltaX,
        origEvent.wheelDeltaY,
        window,
        0,
        0,
        0,
        0,
        origEvent.ctrlKey,
        origEvent.altKey,
        origEvent.shiftKey,
        origEvent.metaKey);

        $(".scroll-container").get(0).dispatchEvent(evt);
    );

请参见此处的示例: http://jsfiddle.net/HAc4K/5

已编辑:此问题最初来自 jqGrid - 冻结的列不会对鼠标滚轮滚动做出反应。

在 Chrome 和 Firefox 中支持很棒的 CSS 属性:pointer-events:none

【问题讨论】:

【参考方案1】:

看起来像是 jQuery 的一个已知问题:OriginalEvent not supported in IE

【讨论】:

这里jsfiddle.net/HAc4K/5是没有originalEvent的更新版本【参考方案2】:

简短的回答:在使用 Internet Explorer 的情况下,您在 the demo 中使用了错误的 initWheelEvent 参数。该方法应该有the documentation 中描述的16 个参数。你目前只使用了11个参数相同的initWebKitWheelEvent,但initWheelEvent的所有参数的含义绝对是另一回事。你必须修复initWheelEvent的参数。

【讨论】:

这里是更改版本jsfiddle.net/HAc4K/5,带有该文档中的参数,并且没有使用 originalEvent。我尝试了很多不同的参数集,但都没有成功。【参考方案3】:

使用RetargetMouseScroll(overlap container, scroll container)

【讨论】:

此库仅适用于window 目标,不适用于 htmlElement。但经过一些编辑后,它开始工作。这不是真正的重定向,而是接近它——至少这个库正确地计算了像素中的滚动移位量——所以滚动左右部分的外观没有区别。 顺便说一句,更改是:在第 34 行替换 targetWindow.scrollBy(0, scrollAmount); with if (targetWindow.scrollBy) targetWindow.scrollBy(0, scrollAmount); else if (targetWindow.scrollByLines) targetWindow.scrollByLines(scrollAmountLines);否则 targetWindow.scrollTop = targetWindow.scrollTop + scrollAmount; 谢谢,我会考虑将其添加到库中。【参考方案4】:

我意识到这不是您正在寻找的,但至少在 Chrome、IE7+ 和 Firefox 3.5+ 中,这可以满足您的要求 - 当覆盖它的 div 接收滚动事件时滚动底层 div:

http://jsfiddle.net/b9chris/yM3qs/

这样做只是因为重叠的 div 是它重叠的 div 的子级 - 没有 jquery 传递任何鼠标滚轮事件(尽管它正在监听滚动以确保重叠的 div 保持在需要的位置)。

然而,在 jqGrid 中实现这种解决方法可能需要在其中修改相当多的代码。

HTML:

<div id=under>
    (content goes here)
    <div id=over></div>
</div>

CSS:

#under 
    position: absolute;
    left: 0; top: 0;
    width: 220px; height: 200px;
    overflow-y: scroll;


#over 
    position: absolute;
    left: 1px; top: 100px;
    width: 200px; height: 100px;
    z-index: 2;

JS:

(function() 
    $('#under').on('scroll', function() 
        $('#over').css('top', $(this).scrollTop() + 100);
    );
)();

【讨论】:

【参考方案5】:

这是2019年重叠容器获取***事件的解决方案:

document.querySelector('.overlap').on('wheel', (e) => 
  const overlap = e.target

  overlap.style.pointerEvents = 'none'
  setTimeout(() => overlap.style.pointerEvents = 'auto', 0)
)

这样 overlapped 元素会从名为 .overlapoverlapping 元素获取***事件。

【讨论】:

以上是关于在另一个 DOM 元素上调度鼠标滚轮事件的主要内容,如果未能解决你的问题,请参考以下文章

事件:事件类型

JS怎么禁止鼠标滚轮的单击 IE下! 注意是滚轮去单击 而不是滚动!

浅谈JavaScript的事件(事件类型)

在jQuery中获取鼠标滚轮事件?

SVG 阻止触摸/鼠标滚轮事件

鼠标与滚轮事件