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

问题描述 投票:9回答:4

我想在两个层上捕获鼠标事件: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上捕获的原始事件,并复制ans在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上处理。

更新和代码示例

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

javascript mouseevent pixi.js
4个回答
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
投票

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


1
投票

问题是DOM是分层的。 Here's an old issue about the exact same thing。事实证明,你不能轻易地将事件传播给兄弟姐妹,只有父母和孩子。我建议把你的canvas放在.overlay里,然后你可以捕捉它并在冒泡阶段抓住它,这取决于你是否想在画布之前或之后处理它们。

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

HTML:

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

示例JS:

(function() {
    let parent = document.getElementById('parent');
    let overlay = document.getElementById('overlay');
    let canvas = document.querySelector('canvas');

    parent.addEventListener('click', e => console.log('parent capture'), true);
    overlay.addEventListener('click', e => console.log('overlay capture'), true);
    canvas.addEventListener('click', e => console.log('canvas capture'), true);
    canvas.addEventListener('click', e => console.log('canvas bubble'), false);
    overlay.addEventListener('click', e => console.log('overlay bubble'), false);
    parent.addEventListener('click', e => console.log('parent bubble'), false);

})()

0
投票

我通过克隆事件和重建来自mouseovermouseout事件的mousedown事件让它为mouseupclickclickmousedownmouseup事件工作。当从事件层克隆事件时,除了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识别。

但是:ぁzxswい

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

© www.soinside.com 2019 - 2024. All rights reserved.