事件冒泡与z指数

问题描述 投票:6回答:3

的jsfiddle:https://jsfiddle.net/uLap7yeq/19/

问题

考虑两个元素,canvas和div,它们位于相同的树深度并具有相同的父级。它们都使用CSS放在相同的位置,但div具有更高的z-index。如何从div中捕获事件并将它们传递给较低的z-index?我必须在画布上执行.dispatchEvent()吗?

编辑:为了澄清,我希望div接收事件,做任何想做的事情,然后将它传递给下一个z-indexed元素。

JSFiddle在线粘贴:

/*
     How can I pass the event along to #canvas?
    */
$('#container').on('click', function(e) {
  console.log('#container click');
});
$('#canvas').on('click', function(e) {
  console.log('#canvas click');
});
$('#other-div').on('click', function(e) {
  console.log('#other-div click');
});
#other-div {
  z-index: 1;
  position: absolute;
  top: 0;
  left: 0;
}

#canvas {
  z-index: 0;
  position: absolute;
  top: 0;
  left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  <div id="other-div">
    <p>
      Something
    </p>
  </div>
  <canvas id="canvas" width="200" height="200"></canvas>
</div>
javascript jquery html css
3个回答
1
投票

将css属性pointer-events: none;添加到#other-div将允许点击或其他与指针相关的事件通过div并到达画布和容器

#other-div {
  z-index: 1;
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
}

Fiddle 1


如果这不合适,因为您需要other-div也捕获事件(根据您的评论),那么您可以在单击容器时以编程方式触发画布上的事件

$('#container').on('click', function(e) {
  console.log('#container click');
  $('#canvas').click(); // <------
});
$('#canvas').on('click', function(e) {
  e.stopImmediatePropagation(); // <------
  console.log('#canvas click');
});
$('#other-div').on('click', function(e) {
  console.log('#other-div click');
});

当投币器收到点击时,它也会触发对底层画布的点击:qazxsw poi

请注意,当点击最终击中画布时,事件必须停止传播,否则它将冒泡并击中$('#canvas').click();#other-div,导致无限循环。这就是为什么你有#container

e.stopImmediatePropagation();


1
投票

当你点击Fiddle 2并让custom event听这个事件时,你可以触发outer-div

canvas
$('#container').on('click', function(e) {
  console.log('#container click');
});
$('#canvas').on('click custom', function(e) {
  console.log('#canvas click');
});
$('#other-div').on('click', function(e) {
  console.log('#other-div click');
  $('#canvas').trigger( "custom");
});
#other-div {
  z-index: 1;
  position: absolute;
  top: 0;
  left: 0;
  background:rgba(255,0,0,0.2);
}

#canvas {
  z-index: 0;
  position: absolute;
  top: 0;
  left: 0;
  background:rgba(255,255,0,0.2);
}

0
投票

您可以通过修补Element原型来使用动态方法:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  <div id="other-div">
  <p>
   Something
  </p>
  </div>
  <canvas id="canvas" width="200" height="200"></canvas>
</div>
if (!document.elementsFromPoint) {
    document.elementsFromPoint = elementsFromPoint;
}

function elementsFromPoint(x, y) {
    var parents = [];
    var parent = void 0;
    do {
        if (parent !== document.elementFromPoint(x, y)) {
            parent = document.elementFromPoint(x, y);
            parents.push(parent);
            parent.style.pointerEvents = 'none';
        } else {
            parent = false;
        }
    } while (parent);
    parents.forEach(function (parent) {
        parent.style.pointerEvents = 'initial';
    });
    return parents;
}

Element.prototype.makeEventGoThrough = function(eventName) {
  $(this).on(eventName, (e) => {
    var elements = document.elementsFromPoint(e.clientX, e.clientY);
    var children = [].slice.call(this.children);
    elements = elements.filter(element => element !== this && !children.find(el => el === element));
    elements.forEach(element => $(element).trigger(eventName));
  });
}


/*
 How can I pass the event along to #canvas?
*/
document.getElementById('other-div').makeEventGoThrough('click');
$('#other-div').on('click', () => console.log('other-div clicked'));
$('#canvas').on('click', () => console.log('canvas clicked'));
#other-div {
  z-index: 1;
  position: absolute;
  top: 0;
  left: 0;
}

#canvas {
  z-index: 0;
  position: absolute;
  top: 0;
  left: 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.