当实际事件发生时,我很难让事件侦听器触发。我创建了一个拖放系统,它在目标的pointerover
上设置一个变量hoveringOverTarget = true
,监听图像上的pointerdown
,然后在pointerup
上调用一个函数来检查它是否被释放到目标上。
let hoveringOverTarget = false;
const target = document.querySelector('.dragtarget');
if(target) {
target.addEventListener('pointerover', ()=>{
hoveringOverTarget = true;
console.log(hoveringOverTarget);
});
target.addEventListener('pointerleave', ()=>{
hoveringOverTarget = false;
console.log(hoveringOverTarget);
});
}
function beginItemDrag(e) {
console.log('beginItemDrag called');
const item = e.target;
if(target) {
item.addEventListener('pointerup', ()=>{
console.log('pointerup');
releaseItem();
});
} else {
console.log('No .dragtarget on page');
}
}
function releaseItem(e) {
const item = e.target;
if(hoveringOverTarget) {
console.log('YES!!!');
readcard(item);
}
}
document.querySelectorAll('.item').forEach(item=>item.addEventListener('pointerdown', beginItemDrag));
但是,在拖动图像期间,没有其他事件侦听器响应。第4行和第8行中的pointerover
和pointerleave
事件侦听器不再触发当将图像拖入和拖出目标区域时(尽管在不拖动图像时工作良好),并且pointerup
函数不会在pointinterup上触发。相反,当我释放项目时,什么都不会发生,除非鼠标被移动,甚至移动一个像素,此时pointerover
事件最终触发(hoveringOverTarget
被记录为true),而pointerup
事件根本不会触发。
通过各种搜索,我看到一些人的问题通过添加e.preventDefault()
事件监听器来解决。当我这样做时,两个事件都不会被触发。
怎么回事?
你似乎找到了一个成功的解决方法。为了防止有人来这里寻找答案,我怀疑这就是最初问题的根源:对于允许直接操作的触摸屏浏览器(例如,使用手指平移或缩放当前页面),pointerdown
触发隐式指针捕获,这导致目标捕获所有后续指针事件,就好像它们发生在捕获目标上一样。所以pointerleave
,例如,永远不会开火。这个过程一直持续到在pointerup
之后隐式释放捕获。
要解决这个问题,您可以在pointerdown
事件侦听器中释放捕获——这里是beginItemDrag
——如果它已经设置:
if (e.target.hasPointerCapture(e.pointerId))
e.target.releasePointerCapture(e.pointerId);
由于没有其他人能够弄清楚这一点,我将发布我所做的最终工作的更改。我尝试了很多不同的事情,但我认为我最终的成功主要归功于:
- 将
pointerup
事件监听器附加到整个文档而不是单个项目 - 通过一个文档范围的变量标识被拖拽的项目,这样所有函数都可以可靠地访问它(而不是希望
e.target
是正确的项目时,从一个指针侦听器调用releaseItem(e)
对单个项目) - 添加
e.preventDefault()
到beginItemDrag()
,停止浏览器的默认图像拖动行为(不同于标准元素拖动行为!!),在拖动过程中自私地阻止其他事件侦听器。
tl:博士;我将变量提升到函数之外,并使事件侦听器更广泛,直到最终捕获正确的事件。
let hoveringOverTarget = false;
let draggedItem = null;
const target = document.querySelector('.dragtarget');
if(target) {
target.addEventListener('pointerover', ()=>{
hoveringOverTarget = true;
console.log(hoveringOverTarget);
});
target.addEventListener('pointerleave', ()=>{
hoveringOverTarget = false;
console.log(hoveringOverTarget);
});
}
function beginItemDrag(e) {
e.preventDefault(); // this is CRUCIAL! Disables default image "draggable" functionality
draggedItem = e.target;
document.addEventListener('pointerup', releaseItem);
if(target) target.style.boxShadow = '0 0 20px white, 0 0 40px white';
}
function releaseItem() {
if(target) target.style.boxShadow = 'none';
if(hoveringOverTarget) { readcard(draggedItem); }
document.removeEventListener('pointerup', releaseItem);
}
document.querySelectorAll('.toolboxitem').forEach(item=>item.addEventListener('pointerdown', beginItemDrag));