当选择器元素被另一个元素遮挡时使用jQuery.on()

Using jQuery .on() when selector element is obscured by another element

本文关键字:元素 jQuery on 选择器 另一个 遮挡      更新时间:2023-09-26

我正试图让我的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>​

对于上面的片段,如果我试图听鼠标点击<canvas>,则该事件永远不会被调用:

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

但是,如果我修改我的事件处理程序,改为侦听<div>元素,则会按预期触发回调:

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

如何强制我的<canvas>接收事件,同时将有问题的<div>块保留在前面?

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

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);
});

你不能。顶部的对象将获得单击事件。DOM就是这样工作的。

如果你想处理点击事件,你需要在顶部的对象中处理,或者使用冒泡并在父对象中处理。如果需要,您可以在顶部对象中处理它,并通过触发对其他对象的单击或直接调用单击处理程序将它"转发"到其他对象。

或者,您可以将画布元素移动到ul上方,方法是将其z-index设置为更高的值,然后它将获得单击事件。

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

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

  • 在下面的示例中,我缓存了画布的尺寸(高度和宽度),因为我假设这些尺寸是恒定的。如果尺寸不是恒定的,请将其移动到函数内部。

  • 我使用.offset()方法来计算<canvas>左上角的实际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();
    }
});

这里有一个解决方案,它包括在上面的元素上捕获点击事件,并在另一个元素上触发事件:在另一元素下的元素上注册点击