如何确定拖放操作是否指向浏览器窗口之外的某个位置?

fra*_*ans 9 html javascript events drag-and-drop event-handling

我想dragend以不同的方式处理事件,具体取决于元素是否刚刚被拖动到浏览器窗口(或站点对应)内部或外部(例如外部文件管理器)。

在我没有找到实例的任何属性DragEvent来指示它是在站点上下文内部还是外部之后,我开始通过算术计算出相应的鼠标事件是否仍然发生在站点的几何结构内部。

最终我可能会成功使用这种方法(目前还没有工作),但它有一个主要缺点(先不说它的丑陋):放置目标窗口可能位于浏览器的顶部,因此几何图形根本不是真正的指示器。

那么..我如何找出dragend(或我可以用来存储某些状态的任何其他事件)是否指向浏览器窗口(或源站点)之外?

Jac*_*ler 4

我找不到任何超级简单的方法来做到这一点,但我可以通过少数听众来相当简洁地做到这一点。如果您同意使用变量来协助状态,那么您可以执行类似的操作。

首先,监听鼠标离开拖动事件。我发现最可靠的方法是使用dragleave侦听器,然后检查事件数据以确保它确实离开窗口。不过这个活动运行量很大,所以我们需要过滤掉我们需要的活动。

dragleave每次离开任何元素的放置区域时都会运行。为了确保拖动事件只是离开页面,我们可以检查目标以确保离开htmlbody标记并转到null解释了如何查看事件的正确目标。

就在dragend事件发生之前,dragleave就像它离开窗口一样运行。这是有问题的,因为它使每一滴水看起来都像是在窗外。规范中似乎没有明确定义此行为,并且 Firefox 和 Chrome 处理此问题的方式存在一些差异。

对于 Chrome,我们可以通过将代码包装在 0 秒的超时中,使代码在dragleave代码输入后运行一个周期。dragend

但这在 Firefox 中效果不佳,因为dragend事件来得不那么快。然而,Firefox 确实设置buttons为 0,因此我们知道这是事件的结束。

dragleave事件侦听器可能如下所示

window.addEventListener('dragleave', (e) => {
    window.setTimeout(() => {
        if ((e.target === document.documentElement || e.target === document.body) && e.relatedTarget == null && e.buttons != 0) {
            outside = true;
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

从这里我们只需要做类似的事情来查看拖动何时重新进入视口。这不会dragend像以前那样运行dragleave,所以更简单。

window.addEventListener('dragenter', (e) => {
    if ((e.target === document.documentElement || e.target === document.body) && e.relatedTarget == null) {
        outside = false;
    }
});
Run Code Online (Sandbox Code Playgroud)

outside每次拖动事件开始时重置也是一个好主意。

element.addEventListener('dragstart', (e) => {
    outside = false;
});
Run Code Online (Sandbox Code Playgroud)

现在可以在dragend事件侦听器中查看放置结束的位置。

element.addEventListener('dragend', (e) => {
    console.log('Ended ' + (outside ? 'Outside' : 'Inside'));
});
Run Code Online (Sandbox Code Playgroud)

这是一个将所有内容放在一起的片段(或小提琴

注意#1:您需要将元素拖出浏览器窗口,而不仅仅是演示窗口,才能使其显示为“外部”。

注意#2:必须有更好的方法来停止最后一个dragleave事件,但在尝试其他事情几个小时后,这似乎是最一致和可靠的。

window.addEventListener('dragleave', (e) => {
    window.setTimeout(() => {
        if ((e.target === document.documentElement || e.target === document.body) && e.relatedTarget == null && e.buttons != 0) {
            outside = true;
        }
    });
});
Run Code Online (Sandbox Code Playgroud)
window.addEventListener('dragenter', (e) => {
    if ((e.target === document.documentElement || e.target === document.body) && e.relatedTarget == null) {
        outside = false;
    }
});
Run Code Online (Sandbox Code Playgroud)
element.addEventListener('dragstart', (e) => {
    outside = false;
});
Run Code Online (Sandbox Code Playgroud)