我遇到了HTML5拖放API的问题。
长话短说,除了dragstart
,dragover
和drop
之外,还有三个事件对我的目标至关重要。这三个事件是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)
}
当用户触发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
偶数被触发,但元素仍然是无法分割的......
有人知道如何解决这个问题或者首先防止它发生吗?
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>
答案 0 :(得分:1)
当你尝试抓住靠近右边缘的左边元素时,问题是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
为了避免这种情况,您可以capture the mouse而不是处理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;
}
事件。当用户释放鼠标时(如果未拖动元素)或拖动操作结束时,将重置draggable元素属性。
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>
ID V1
1 A
1 C
1 B
2 B
2 A
2 A
3 B
3 C
3 C