Drag and Drop API问题还是? [英] Issue with Drag and Drop API or?
问题描述
我遇到了HTML5拖放API的问题。
I'm encountering an issue with the HTML5 Drag and Drop API.
长话短说,除了 dragstart <之外还有三个事件/ code>,
dragover
和 drop
,这对我的目标至关重要。这三个事件是 mousedown
, mouseup
和 mouseleave
。
Long story short, there are three events other than dragstart
, dragover
, and drop
, which are critical to my objective. Those three events are mousedown
, mouseup
, and mouseleave
.
当用户在给定元素上触发 mousedown
事件,以下函数将属性和侦听器应用于自身和目标元素。
When the user triggers a mousedown
event on a given element, the following function applies attributes and listeners to itself and the target element.
function doThis() {
d.setAttribute('draggable', true)
d.addEventListener('dragstart', dragStart)
t.style.background = 'black'
t.addEventListener('dragover', dragOver)
t.addEventListener('drop', drop)
}
当用户触发 mouseup
或 mouseleave
事件,这些属性和侦听器被删除。
When the user triggers a mouseup
or mouseleave
event, those attributes and listeners are removed.
function thenThis(){
d.setAttribute('draggable', false)
d.removeEventListener('dragstart', dragStart)
t.style.background = 'none'
t.removeEventListener('dragover', dragOver)
t.removeEventListener('drop', drop)
}
我必须添加 mouseleave
侦听器,因为 mouseup
事件必须发生在绑定它的元素上才能被触发。如果不应用 mouseleave
事件,用户可以触发 mousedown
事件,同时避免 mouseup
事件完全(由于浏览器本机检测到 dblclick
事件),双击元素,然后将光标滑出元素,同时不要放开鼠标按钮,直到它超出元素的周长。
I've had to add the mouseleave
listener since the mouseup
event must occur over the element to which it is binded for it to be triggered. Without applying the mouseleave
event, the user is able to trigger the mousedown
event while avoiding the mouseup
event altogether (due to the browser's native detection of the dblclick
event) by double clicking the element and then sliding the cursor off of the element while not letting go of the mouse button until it is beyond the element's perimeter.
如果用户点击可拖动元素太靠近其边缘,尽管 mousedown
事件被触发。
If the user clicks the draggable element too close to its edge, the element becomes undraggable despite the mousedown
event being triggered.
为什么会出现这种情况?甚至触发了 mousedown
,但该元素仍然无法分割...
Why does this occur? The mousedown
even is triggered, but the element is still undraggable...
有谁知道如何我可以解决这个问题或者首先防止它发生吗?
var d = document.getElementById('draggable')
var t = document.getElementById('target')
d.addEventListener('mousedown', doThis)
d.addEventListener('mouseup', thenThis)
d.addEventListener('mouseleave', thenThis)
d.addEventListener('mouseleave', alertLeave)
function doThis(){
d.setAttribute('draggable', true)
d.addEventListener('dragstart', dragStart)
t.style.background = 'black'
t.addEventListener('dragover', dragOver)
t.addEventListener('drop', drop)
}
function thenThis(){
d.setAttribute('draggable', false)
d.removeEventListener('dragstart', dragStart)
t.style.background = 'none'
t.removeEventListener('dragover', dragOver)
t.removeEventListener('drop', drop)
}
function dragStart(e){
e.dataTransfer.setData('text/plain', e.target.id);
e.dataTransfer.effectAllowed = 'move';
}
function dragOver(e){
e.preventDefault();
}
function drop(e){
var data = e.dataTransfer.getData('text/plain');
e.preventDefault();
e.target.parentElement.appendChild(document.getElementById(data));
}
function alertLeave(){
//alert('mouseleave')
}
body {
display: flex;
justify-content: space-around;
}
div {
width: 50px;
height: 50px;
}
#draggable {
background: purple;
}
#target {
border: solid 3px black;
}
<div id="draggable"></div>
<div id="target"></div>
推荐答案
问题,当你试图抓住左边元素关闭在 dragstart
之前,只要你将鼠标移到右边,就会触发 mouseleave
。有机会被触发。您可以在此代码段中看到事件:
The problem, when you try to grab the left element close to its right edge, is that mouseleave
is triggered as soon as you move the mouse to the right, before dragstart
has a chance to be triggered. You can see the events in this code snippet:
var d = document.getElementById('draggable')
var t = document.getElementById('target')
d.addEventListener('mousedown', doThis)
d.addEventListener('mouseleave', thenThis)
function doThis(){
console.log('mousedown');
d.setAttribute('draggable', true);
d.addEventListener('dragstart', dragStart);
t.style.background = 'black';
t.addEventListener('dragover', dragOver);
t.addEventListener('drop', drop);
}
function thenThis(){
console.log('mouseleave');
d.setAttribute('draggable', false);
d.removeEventListener('dragstart', dragStart);
t.style.background = 'none';
t.removeEventListener('dragover', dragOver);
t.removeEventListener('drop', drop);
}
function dragStart(e){
console.log('dragstart');
e.dataTransfer.setData('text/plain', e.target.id);
e.dataTransfer.effectAllowed = 'move';
}
function dragOver(e){
e.preventDefault();
}
function drop(e){
var data = e.dataTransfer.getData('text/plain');
e.preventDefault();
e.target.parentElement.appendChild(document.getElementById(data));
}
body {
display: flex;
justify-content: space-around;
}
.square {
width: 50px;
height: 50px;
}
#draggable {
background: purple;
}
#target {
border: solid 3px black;
}
<div id="draggable" class="square"></div>
<div id="target" class="square"></div>
为了避免这种情况,您可以捕获鼠标而不是处理 mouseleave
。拖动操作开始后,您可以释放鼠标捕获并依赖 dragend
事件。当用户释放鼠标时(如果未拖动元素)或拖动操作结束时,将重置draggable元素属性。
To avoid that situation, you can capture the mouse instead of processing mouseleave
. Once the dragging operation begins, you can release the mouse capture and rely on the dragend
event. The draggable element properties will be reset when the mouse is released by the user (if the element was not dragged) or when the drag operation ends.
var d = document.getElementById('draggable')
var t = document.getElementById('target')
var releaseCapture = null;
d.addEventListener('mousedown', mouseDown);
d.addEventListener('dragend', resetDraggableElement);
function mouseDown() {
releaseCapture = captureMouse(resetDraggableElement);
d.setAttribute('draggable', true);
d.addEventListener('dragstart', dragStart);
t.style.background = 'black';
t.addEventListener('dragover', dragOver);
t.addEventListener('drop', drop);
}
function resetDraggableElement() {
d.setAttribute('draggable', false);
d.removeEventListener('dragstart', dragStart);
t.style.background = 'none';
t.removeEventListener('dragover', dragOver);
t.removeEventListener('drop', drop);
}
function dragStart(e) {
if (releaseCapture) {
releaseCapture();
releaseCapture = null;
}
e.dataTransfer.setData('text/plain', e.target.id);
e.dataTransfer.effectAllowed = 'move';
}
function dragOver(e) {
e.preventDefault();
}
function drop(e) {
var data = e.dataTransfer.getData('text/plain');
e.preventDefault();
e.target.parentElement.appendChild(document.getElementById(data));
}
function captureMouse(mouseUpHandler) {
var releaseCapture = function() {
document.removeEventListener("mouseup", lostCaptureHandler, false);
}
var lostCaptureHandler = function() {
releaseCapture();
if (mouseUpHandler) {
mouseUpHandler();
}
};
document.addEventListener("mouseup", lostCaptureHandler, false);
return releaseCapture;
}
body {
display: flex;
justify-content: space-around;
}
.square {
width: 50px;
height: 50px;
}
#draggable {
background: purple;
}
#target {
border: solid 3px black;
}
<div id="draggable" class="square"></div>
<div id="target" class="square"></div>
这篇关于Drag and Drop API问题还是?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!