我想在两层上捕获鼠标事件: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
事件,但不幸的是click
、mousedown
等不起作用。
我还尝试复制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 上处理。
更新和代码示例
我设法转发了事件,除了点击事件之外,所有事件都由 PIXI 注册。点击事件可以通过重新触发pointerdown
和pointerup
事件来手动触发。退房 https://jsfiddle.net/v3chhhjk/1/
一种可能的解决方案是捕获父元素的所有事件并将其遍历回子元素。喜欢这个。这是为点击完成的,同样适用于鼠标移动。
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>
对于访问此页面但希望 PIXI 成为叠加层的用户,覆盖在仍然交互式的底层之上。然后,您仍然可以使用@F Lekschas中的示例,并进行一些修改。
设置指针事件:父级上无,然后设置指针事件:全部在底层图上,然后将事件从底层转发到 PIXI 画布,如示例中所示。
我把头发拉到这个上面。我在将事件从父层转发到底层时遇到了各种问题,但是将事件从底层转发到 PIXI 画布就像一个魅力。
如果你只需要通过覆盖层传递事件 - 使用 csspointer-events: none;
.
更多详情请见:https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
问题是 DOM 是分层的。这是一个关于完全相同的事情的旧问题。事实证明,你不能简单地将事件传播给兄弟姐妹,只能将父母和孩子传播。我建议把你的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);
})()
我通过克隆事件并从mousedown
和mouseup
事件中重建click
事件,让它适用于mouseover
、mouseout
、mousedown
、mouseup
和click
事件。从事件层克隆事件时,除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识别点击事件,最后是右下角。