拖放问题 API 或者?
Issue with Drag and Drop API or?
我遇到了 HTML5 拖放 API 的问题。
长话短说,除了 dragstart
、dragover
和 drop
之外,还有三个事件对我的 objective 至关重要。这三个事件是 mousedown
、mouseup
和 mouseleave
。
鼠标按下
当用户在给定元素上触发 mousedown
事件时,以下函数将属性和侦听器应用于自身和目标元素。
function doThis() {
d.setAttribute('draggable', true)
d.addEventListener('dragstart', dragStart)
t.style.background = 'black'
t.addEventListener('dragover', dragOver)
t.addEventListener('drop', drop)
}
onmouseup & mouseleave
当用户触发 mouseup
或 mouseleave
事件时,这些属性和侦听器将被删除。
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
事件的本机检测)双击该元素,然后将光标从该元素上滑开,同时不要松开鼠标按钮,直到它超出该元素的边界。
问题...
如果用户点击距离其边缘太近的可拖动元素,尽管触发了 mousedown
事件,该元素仍将变为不可拖动。
Here is an codepen MVC which can also be viewed below.
为什么会出现这种情况? mousedown
even 被触发,但元素仍然不可拖动...
有人知道我该如何解决这个问题或首先防止它发生吗?
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>
问题是,当您尝试抓住靠近其右边缘的左侧元素时,一旦您将鼠标向右移动,mouseleave
就会在 dragstart
具有机会被触发。您可以在这段代码中看到事件:
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
事件。当用户释放鼠标(如果元素未被拖动)或拖动操作结束时,可拖动元素属性将被重置。
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>
我遇到了 HTML5 拖放 API 的问题。
长话短说,除了 dragstart
、dragover
和 drop
之外,还有三个事件对我的 objective 至关重要。这三个事件是 mousedown
、mouseup
和 mouseleave
。
鼠标按下
当用户在给定元素上触发 mousedown
事件时,以下函数将属性和侦听器应用于自身和目标元素。
function doThis() {
d.setAttribute('draggable', true)
d.addEventListener('dragstart', dragStart)
t.style.background = 'black'
t.addEventListener('dragover', dragOver)
t.addEventListener('drop', drop)
}
onmouseup & mouseleave
当用户触发 mouseup
或 mouseleave
事件时,这些属性和侦听器将被删除。
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
事件的本机检测)双击该元素,然后将光标从该元素上滑开,同时不要松开鼠标按钮,直到它超出该元素的边界。
问题...
如果用户点击距离其边缘太近的可拖动元素,尽管触发了 mousedown
事件,该元素仍将变为不可拖动。
Here is an codepen MVC which can also be viewed below.
为什么会出现这种情况? mousedown
even 被触发,但元素仍然不可拖动...
有人知道我该如何解决这个问题或首先防止它发生吗?
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>
问题是,当您尝试抓住靠近其右边缘的左侧元素时,一旦您将鼠标向右移动,mouseleave
就会在 dragstart
具有机会被触发。您可以在这段代码中看到事件:
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
事件。当用户释放鼠标(如果元素未被拖动)或拖动操作结束时,可拖动元素属性将被重置。
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>