事件冒泡与z指数

时间:2018-03-01 12:33:51

标签: javascript jquery html css

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>

3 个答案:

答案 0 :(得分: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');
});

当投币器收到点击时,它也触发了对未决画布的点击:$('#canvas').click();

请注意,当点击最终到达画布时,事件必须停止传播,否则它将冒泡并同时点击#other-div#container导致无限循环。这就是你e.stopImmediatePropagation();

的原因

请参阅Fiddle 2

答案 1 :(得分:1)

当您点击outer-div并让canvas听取此活动时,您可以触发custom event

&#13;
&#13;
$('#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");
});
&#13;
#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);
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

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

&#13;
&#13;
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'));
&#13;
#other-div {
  z-index: 1;
  position: absolute;
  top: 0;
  left: 0;
}

#canvas {
  z-index: 0;
  position: absolute;
  top: 0;
  left: 0;
}
&#13;
<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>
&#13;
&#13;
&#13;