JS事件监听器在拖拽项目时停止工作,只在指针指向和随后的鼠标移动后触发



当实际事件发生时,我很难让事件侦听器触发。我创建了一个拖放系统,它在目标的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行中的pointeroverpointerleave事件侦听器不再触发当将图像拖入和拖出目标区域时(尽管在不拖动图像时工作良好),并且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));

相关内容

  • 没有找到相关文章