如何判断拖放操作是否指向浏览器之外的某个地方window?
How to decide whether a drag&drop operation points to somewhere outside the browser window?
我想以不同方式处理 dragend
事件,具体取决于元素是被拖到浏览器内部 window(或站点响应)还是外部,例如到外部文件管理器。
在我没有找到 DragEvent
实例的任何属性表明它是在站点上下文内部还是外部之后,我开始算术计算出相应的鼠标事件是否仍然发生在站点几何结构内.
最终我可能会用这种方法成功(目前还没有用)但是它有一个主要的缺点(撇开它的丑陋不谈):放置目标 window 可能在浏览器的顶部,所以几何根本不是真正的指标..
所以..我如何确定 dragend
(或我可以用来存储某些状态的任何其他事件)是否指向浏览器 window(或源站点)之外?
这可能会有所帮助。您可以点击'Run code snippet'查看效果
注意:增加偏移量有助于更快地检测拖出,但可能会影响精度(无论是实际拖出还是刚好在边缘)
/* events fired on the draggable target */
let offset = 2; // in case required
let width = window.innerWidth;
let height = window.innerHeight;
console.log('Starting screen width: ' + width);
console.log('Starting screen height: ' + height);
document.addEventListener("drag", function(event) {
let posX = event.pageX;
let posY = event.pageY;
console.log('X:' + posX + ' Y:' + posY)
let isExceedingWidth = posX >= (width - offset) || posX <= (0 + offset);
let isExceedingHeight = posY >= (height - offset) || posY <= (0 + offset);
if (isExceedingWidth || isExceedingHeight) {
console.log('dragged out');
} else {
console.log('in');
}
}, false);
#draggable {
width: fit-content;
padding: 1px;
height: fit-content;
text-align: center;
background: black;
color: white;
}
<div id="draggable" draggable="true">
Drag Me
</div>
我找不到任何超级直接的方法来做到这一点,但我可以通过少数听众相当简洁地做到这一点。如果您可以使用变量来协助状态,那么您可以做这样的事情。
首先,监听拖动事件中的鼠标离开。我发现最可靠的方法是使用 dragleave
侦听器,然后检查事件数据以确保它确实离开了 window。不过这个事件 运行 很多,所以我们需要过滤掉我们需要的那些。
每次离开任何元素的拖放区时 dragleave
运行s。为了确保拖动事件只是离开页面,我们可以检查目标以确保离开 html
或 body
标签并转到 null
。 This 解释了如何查看事件的正确目标。
就在 dragend
事件之前,dragleave
是 运行,就好像它离开了 window。这是有问题的,因为它让每一滴看起来都像是在 window 之外。规范中似乎没有很好地定义这种行为,并且 Firefox 和 Chrome 处理这种行为的方式存在一些差异。
对于Chrome,我们可以使dragleave
运行中的代码在dragend
中的代码之后循环,方法是将其包装在0秒的超时中。
这在 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;
}
});
});
从这里我们只需要做一些类似的事情来查看何时拖动 re-enters 视口。这不会像 dragleave
那样在 dragend
之前 运行,所以它更简单。
window.addEventListener('dragenter', (e) => {
if ((e.target === document.documentElement || e.target === document.body) && e.relatedTarget == null) {
outside = false;
}
});
每次拖动事件开始时重置 outside
也是一个好主意。
element.addEventListener('dragstart', (e) => {
outside = false;
});
现在可以在 dragend
事件侦听器中查看放置结束的位置。
element.addEventListener('dragend', (e) => {
console.log('Ended ' + (outside ? 'Outside' : 'Inside'));
});
这是将所有内容放在一起的片段(或 fiddle)
注意 #1:您需要将元素拖出浏览器 window,而不仅仅是演示 window 才能使其显示为“外部”。
注意#2:必须有更好的方法来停止最后一个 dragleave
事件,但在尝试其他方法几个小时后,这似乎是最一致和可靠的。
const element = document.querySelector('div');
var outside = false;
element.addEventListener('dragend', (e) => {
console.log('Ended ' + (outside ? 'Outside' : 'Inside'));
});
element.addEventListener('dragstart', (e) => {
outside = false;
});
window.addEventListener('dragleave', (e) => {
window.setTimeout(() => {
if ((e.target === document.documentElement || e.target === document.body) && e.relatedTarget == null && e.buttons != 0) {
outside = true;
}
});
});
window.addEventListener('dragenter', (e) => {
if ((e.target === document.documentElement || e.target === document.body) && e.relatedTarget == null) {
outside = false;
}
});
div[draggable] {
width: fit-content;
margin-bottom: 32px;
padding: 16px 32px;
background-color: black;
color: white;
}
<div draggable="true">Drag Me</div>
我想以不同方式处理 dragend
事件,具体取决于元素是被拖到浏览器内部 window(或站点响应)还是外部,例如到外部文件管理器。
在我没有找到 DragEvent
实例的任何属性表明它是在站点上下文内部还是外部之后,我开始算术计算出相应的鼠标事件是否仍然发生在站点几何结构内.
最终我可能会用这种方法成功(目前还没有用)但是它有一个主要的缺点(撇开它的丑陋不谈):放置目标 window 可能在浏览器的顶部,所以几何根本不是真正的指标..
所以..我如何确定 dragend
(或我可以用来存储某些状态的任何其他事件)是否指向浏览器 window(或源站点)之外?
这可能会有所帮助。您可以点击'Run code snippet'查看效果
注意:增加偏移量有助于更快地检测拖出,但可能会影响精度(无论是实际拖出还是刚好在边缘)
/* events fired on the draggable target */
let offset = 2; // in case required
let width = window.innerWidth;
let height = window.innerHeight;
console.log('Starting screen width: ' + width);
console.log('Starting screen height: ' + height);
document.addEventListener("drag", function(event) {
let posX = event.pageX;
let posY = event.pageY;
console.log('X:' + posX + ' Y:' + posY)
let isExceedingWidth = posX >= (width - offset) || posX <= (0 + offset);
let isExceedingHeight = posY >= (height - offset) || posY <= (0 + offset);
if (isExceedingWidth || isExceedingHeight) {
console.log('dragged out');
} else {
console.log('in');
}
}, false);
#draggable {
width: fit-content;
padding: 1px;
height: fit-content;
text-align: center;
background: black;
color: white;
}
<div id="draggable" draggable="true">
Drag Me
</div>
我找不到任何超级直接的方法来做到这一点,但我可以通过少数听众相当简洁地做到这一点。如果您可以使用变量来协助状态,那么您可以做这样的事情。
首先,监听拖动事件中的鼠标离开。我发现最可靠的方法是使用 dragleave
侦听器,然后检查事件数据以确保它确实离开了 window。不过这个事件 运行 很多,所以我们需要过滤掉我们需要的那些。
dragleave
运行s。为了确保拖动事件只是离开页面,我们可以检查目标以确保离开 html
或 body
标签并转到 null
。 This 解释了如何查看事件的正确目标。
就在 dragend
事件之前,dragleave
是 运行,就好像它离开了 window。这是有问题的,因为它让每一滴看起来都像是在 window 之外。规范中似乎没有很好地定义这种行为,并且 Firefox 和 Chrome 处理这种行为的方式存在一些差异。
对于Chrome,我们可以使dragleave
运行中的代码在dragend
中的代码之后循环,方法是将其包装在0秒的超时中。
这在 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;
}
});
});
从这里我们只需要做一些类似的事情来查看何时拖动 re-enters 视口。这不会像 dragleave
那样在 dragend
之前 运行,所以它更简单。
window.addEventListener('dragenter', (e) => {
if ((e.target === document.documentElement || e.target === document.body) && e.relatedTarget == null) {
outside = false;
}
});
每次拖动事件开始时重置 outside
也是一个好主意。
element.addEventListener('dragstart', (e) => {
outside = false;
});
现在可以在 dragend
事件侦听器中查看放置结束的位置。
element.addEventListener('dragend', (e) => {
console.log('Ended ' + (outside ? 'Outside' : 'Inside'));
});
这是将所有内容放在一起的片段(或 fiddle)
注意 #1:您需要将元素拖出浏览器 window,而不仅仅是演示 window 才能使其显示为“外部”。
注意#2:必须有更好的方法来停止最后一个 dragleave
事件,但在尝试其他方法几个小时后,这似乎是最一致和可靠的。
const element = document.querySelector('div');
var outside = false;
element.addEventListener('dragend', (e) => {
console.log('Ended ' + (outside ? 'Outside' : 'Inside'));
});
element.addEventListener('dragstart', (e) => {
outside = false;
});
window.addEventListener('dragleave', (e) => {
window.setTimeout(() => {
if ((e.target === document.documentElement || e.target === document.body) && e.relatedTarget == null && e.buttons != 0) {
outside = true;
}
});
});
window.addEventListener('dragenter', (e) => {
if ((e.target === document.documentElement || e.target === document.body) && e.relatedTarget == null) {
outside = false;
}
});
div[draggable] {
width: fit-content;
margin-bottom: 32px;
padding: 16px 32px;
background-color: black;
color: white;
}
<div draggable="true">Drag Me</div>