从PIXI.js中的兄弟或父DOM元素捕获鼠标事件

时间:2017-12-01 01:58:15

标签: javascript mouseevent pixi.js

我想捕获两个图层上的鼠标事件:PIXI的画布和覆盖div。我有以下类型的HTML设置div.overlay高于canvas.pixi

<div class="parent">
  <canvas class="pixi"></canvas>
  <div class="overlay"></div>
</div>

canvas位于顶部时,PIXI交互工作正常,但当画布与div.overlay重叠时,我无法捕获任何事件。

我发现setTargetElement似乎让我们为捕获元素定义了DOM元素,我试图像这样使用它:

const renderer = PIXI.autoDetectRenderer(...);
renderer.plugins.interaction.setTargetElement(document.querySelector('.overlay'));

使用此技术,我可以捕获mousemove个事件,但遗憾的是clickmousedown等不起作用。

我还尝试复制div.overlay上捕获的原始事件,然后重复发送canvas上的事件,如下所示,但这也不起作用。

document.querySelector('.overlay').addEventListener('mousedown', (e) => {
  const eventCopy = document.createEvent('MouseEvents');
  eventCopy.initMouseEvent(
    e.type, e.bubbles, e.cancelable, e.view,
    e.detail, e.pageX || e.layerX,
    e.pageY || e.layerY, e.clientX,
    e.clientY, e.ctrlKey, e.altKey, e.shiftKey,
    e.metaKey, e.button, e.relatedTarget
  );

  document.querySelector('.pixi').dispatchEvent(eventCopy);
});

有没有办法在重叠的DOM元素上捕获鼠标事件并将事件传递给PIXI?

为什么吗

我想与PIXI元素进行交互,同时能够利用D3的缩放和画笔功能,目前正在重叠的div上进行处理。

更新&amp;代码示例

我设法转发事件,所有但是点击事件都是由PIXI注册的。可以通过重新触发pointerdownpointerup事件来手动触发点击事件。查看https://jsfiddle.net/v3chhhjk/1/

4 个答案:

答案 0 :(得分:3)

一种可能的解决方案是捕获父级的所有事件并将其遍历回子元素。像这样。这样做是为了点击,同样适用于mousemove。

function traverseEventToChild(e){
	if(e.type="click"){
  	const eventCopy = document.createEvent('MouseEvents');
  	eventCopy.initMouseEvent(
      e.type, e.bubbles, e.cancelable, e.view,
      e.detail, e.pageX || e.layerX,
      e.pageY || e.layerY, e.clientX,
      e.clientY, e.ctrlKey, e.altKey, e.shiftKey,
      e.metaKey, e.button, e.relatedTarget
  	);
    console.log('parent handler');
  	document.querySelector('.pixi').dispatchEvent(eventCopy);
  }
}

function piximousemove(e){
	console.log('pixi click');
  e.stopPropagation();
}

function overlaymousemove(e){
	console.log('overlay click');
}
document.querySelector('.pixi').onclick = piximousemove;
document.querySelector('.overlay').onclick = overlaymousemove;
<div class="parent" id='parent' onclick="traverseEventToChild(event);">
  <canvas class="pixi" id='canvas'>pixi</canvas>
  <div class="overlay" id='overlay'>overlay</div>
</div>

答案 1 :(得分:1)

如果您只需要通过叠加层传递事件,请使用css pointer-events: none; 更多详情:https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events

答案 2 :(得分:1)

问题在于DOM是分层的。 Here's an old issue about the exact same thing。事实证明,你可以通过简单的方式将事件传播给兄弟姐妹,只有父母和孩子。我建议将collection_def { key: "global_step" value { node_list { value: "global_step:0" } } } 放在w = tf.get_variable("foo_weights", dtype=tf.float32, shape=[1, 1], initializer=tf.zeros_initializer, use_resource=True) 内,然后你可以捕捉它并在冒泡阶段捕捉它,这取决于你是否想要在画布之前或之后处理它们。

我认为下面应该按预期工作。

HTML:

collection_def {
  key: "trainable_variables"
  value {
    bytes_list {
      value: "\n\rfoo_weights:0\022\022foo_weights/Assign(\001"
    }
  }
}

示例JS:

canvas

答案 3 :(得分:0)

我通过克隆事件并重建mouseover使其适用于mouseoutmousedownmouseupclickclick事件mousedownmouseup事件发生的事件。当从事件层克隆事件时,除click事件外的所有事件都可以开箱即用,但不会触发单击事件。

所以给出以下HTML结构:

<div id="parent">
  <canvas id="pixi"></canvas>
  <div id="overlay"></div>
</div>

我听了很多这样的事件:

const overlay = document.getElementById('overlay');

overlay.addEventListener('pointerdown', forwardDown);
overlay.addEventListener('pointerup', forwardUp);
overlay.addEventListener('pointermove', forward);
overlay.addEventListener('pointerover', forward);
overlay.addEventListener('pointerout', forward);

然后转发/克隆事件:

const canvas = document.getElementById('pixi');
let mousedown = false;

const clone = e => new e.constructor(e.type, e);
const forward = (e) => { canvas.dispatchEvent(clone(e)); };
const forwardDown = (e) => { mousedown = true; forward(e); };
const forwardUp = (e) => {
  forward(e);
  if (mousedown) console.log('It\'s a click!');
  mousedown = false;
};

事件也可以在其他地方调度,例如D3可以识别。

演示https://jsfiddle.net/v3chhhjk/3/

左上角演示了使用PIXI直接捕获事件时的工作原理。右上角显示克隆事件时的问题。左下角显示了一个奇怪的行为,其中重新触发相同的事件实际上使PIXI识别点击事件,最后,右下角。