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

时间:2012-02-26 15:23:47

标签: javascript jquery z-order

我正在尝试让我的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>阻止留在前线?

4 个答案:

答案 0 :(得分:1)

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

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

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

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

答案 1 :(得分:1)

您可以将元素绑定到最近的公共父级,并检查鼠标的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();
    }
});

答案 2 :(得分:1)

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

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

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

如果您需要原始eventdata:

$('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);
});

答案 3 :(得分:0)

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