Drag and Drop API问题还是? [英] Issue with Drag and Drop API or?

查看:158
本文介绍了Drag and Drop API问题还是?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了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.

这是一个codepen MVC也可以在下面查看。

为什么会出现这种情况?甚至触发了 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆