【问题标题】:Using jQuery .on() when selector element is obscured by another elementUsing jQuery .on() when selector element is obscured by another element
【发布时间】:2012-02-26 15:23:46
【问题描述】:

我正在尝试让我的 jQuery 事件回调正确触发,但我似乎无法解决我感兴趣的元素没有收到事件的事实,因为页面上的另一个元素覆盖了它。我可以将其总结如下(我对元素进行了样式设置,以便它们显示在 jsfiddle 中):

<div id='mydiv'>
    <div style="border: 1px solid; border-color: red; position: absolute; left: 0px; top: 0px; width: 200px; height: 200px; z-index: 100">Hello</div>
    <canvas style="border: 1px solid; border-color: yellow; position: absolute; left: 50px; top: 50px; width: 150px; height: 150px"></canvas>
</div>​

对于上面的片段,如果我尝试在 &lt;canvas&gt; 上监听鼠标点击,则永远不会调用该事件:

$('#mydiv').on('mousedown', 'canvas', this, function(ev) {
    console.log(ev.target);
});

但是,如果我修改我的事件处理程序以侦听 &lt;div&gt; 元素,则回调会按预期触发:

$('#mydiv').on('mousedown', 'div', this, function(ev) {
    console.log(ev.target);
});

如何强制我的 &lt;canvas&gt; 接收事件,同时将有问题的 &lt;div&gt; 块留在最前面?

【问题讨论】:

    标签: javascript jquery z-order


    【解决方案1】:

    正如已经提出的,这应该是最简单的解决方案:

    http://jsfiddle.net/CUJ68/4/

    $('canvas').on('mousedown', function(ev) {
        console.log(ev.target);
    });
    $('ul').on('mousedown', function(ev){
        $('canvas').mousedown();
    });
    

    如果您需要原始事件数据:

    $('canvas').bind('mousedown', function(ev, parentEV) {
        if(parentEV){
            console.log(parentEV);
            alert("Canvas INdirectly clicked!");
        }else{
            console.log(ev);
            alert("Canvas directly clicked!");
        }
    });
    $('ul').on('mousedown', function(ev){
        $('canvas').trigger('mousedown', ev);
    });
    

    【讨论】:

    • 这在您不需要事件数据的情况下有效。我在转发 ev 结果时遇到了麻烦(它导致了事件处理程序中的无限循环)或构建我自己的事件(我永远无法让它触发画布 mousedown 回调)。
    • jsfiddle.net/CUJ68/5 这对我有用。它将ev 传递给canvas-事件。
    • 太好了,父事件是拼图中缺失的部分。谢谢亚历克斯,这是我正在寻找的整洁的解决方案。
    【解决方案2】:

    你不能。顶部的对象获取点击事件。这就是 DOM 的工作原理。

    如果要处理该单击事件,则需要在顶部的对象中进行处理,或者使用冒泡并在父对象中进行处理。如果需要,您可以在顶部对象中处理它,并通过触发对另一个对象的点击或直接调用点击处理程序将其“转发”到另一个对象。

    或者,您可以通过将其z-index 设置为更高的值来移动ul 上方的canvas 元素,然后它将获得点击事件。

    或者,您可以在顶部创建一个新的透明画布对象以获取事件,而将其他两个对象留在原处以获得所需的视觉效果。

    【讨论】:

    • 太好了,感谢您的解释。我将首先尝试将事件转发到隐藏元素,因为我几乎无法控制此特定布局的呈现。
    • 我无法让事件转发工作,因为我需要 pageX/pageY 值,传递事件变量只是弄乱了事件处理程序。我将在这里尝试其他一些答案,以及您的透明画布建议......
    【解决方案3】:

    您可以将元素绑定到最近的公共父级,并检查鼠标的X和Y坐标是否在画布范围内。

    • 在下面的示例中,我已经缓存了画布的尺寸(高度和宽度),因为我假设它们是恒定的。如果尺寸不恒定,则将其移至函数内部。

    • 我使用.offset() 方法计算&lt;canvas&gt;s 左上角的真实X 和Y 坐标。我通过将outerWidth().outerHeight() 的值相加来计算右下角的坐标。

    基本演示:http://jsfiddle.net/75qbX/2/

    var $canvas = $('canvas'), /* jQuery reference to the <canvas> */
        $canvasWidth = $canvas.outerWidth(), /* assuming height and width to be constant */
        $canvasHeight = $canvas.outerHeight();
    function isCanvasClicked(x, y, target) {
        if (target.tagName === 'CANVAS') return true;
        var offset = $canvas.offset(),
            left = offset.left,
            top = offset.top;
    
        return x >= left && x <= left + $canvasWidth &&
               y >= top && y <= top + $canvasHeight;              
    }
    $('#mydiv').on('mousedown', '*', this, function(ev) {
        if (isCanvasClicked(ev.pageX, ev.pageY, ev.target)) {
            $canvas.fadeOut().fadeIn();
        }
    });
    

    【讨论】:

    • 这很好用,尽管您的 jsfiddle 链接中没有 Javascript。我用类似于您在此处发布的内容对其进行了修改:jsfiddle.net/75qbX/6。感谢分享!
    【解决方案4】:

    这里有一个解决方案,包括在上面的元素上捕获点击事件,并在另一个元素上触发事件:registering clicks on an element that is under another element

    【讨论】:

      猜你喜欢
      • 2013-10-31
      • 2019-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-01
      相关资源
      最近更新 更多