Javascript 拖放不适用于指针事件

问题描述 投票:0回答:1

我对 javascript 和 Web 开发都是新手,所以我确信我在这里缺少一个概念,希望有一个简单的方法来解决这个问题。我正在使用指针事件进行拖放,似乎在使用触摸时效果很好。但是当使用鼠标时,可拖动的 div 将会出现不可预知的行为。如果在拖动 div 时快速移动鼠标,光标将松开该元素,并且 div 将陷入困境。同样奇怪且可能相关的是,pointermove 事件将在没有首先触发pointerdown 的情况下触发。

我认为某种类型的默认行为导致了这个问题,所以我添加了一个pointercancel事件(这没有帮助)。我已将 e.preventDefault() 添加到处理程序中,但这也没有帮助。

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="styles.css">
    <script src="script.js" defer></script>
    <title>Document</title>
  </head>

  <body>
    <div>
      <div class="container" id="lineup">
        <div class=draggable id="player1" draggable="false">1</div>
        <div class=draggable id="player2" draggable="false">2</div>
        <div class=draggable id="player3" draggable="false">3</div>
      </div>
    </div>
  </body>

</html>
* {
box-sizing: border-box;
}

body {
    font-family: Arial, Helvetica, sans-serif;
    margin: 0;
}
#player{
    border: 2px solid white;
    border-radius: 6px;
    margin: 2px;

}
.dragging{
    border: 5px solid white;
    border-radius: 6px;
    margin: 2px;
    color:blue; 
   
}

.draggable.dragging {
    opacity: .5;
}

.draggable{
    height: 50px;
    width: 50px;
    border: 1px solid #000;
    border-radius: 10px;
    float: left;
    background: blueviolet;
    margin: 10px;
    touch-action: none;

}
const draggables = document.querySelectorAll('.draggable')

draggables.forEach(draggable => {

  draggable.addEventListener('pointerdown', e => {
    e.preventDefault()
    console.log(e)
    draggable.classList.add('dragging')
    draggable.setAttribute('draggable', true)
  })
  
  draggable.addEventListener('pointermove', e => {
    console.log(e)
    e.preventDefault()
    const player = document.getElementById(e.target.attributes.id.nodeValue)
    if (player == null) return
    if (player.classList.contains('dragging')) {
      positionPlayer(e, player)
    } else {
      return
    }
  })
  
  draggable.addEventListener('pointerup', e => {
    console.log(e)
    e.preventDefault()
    draggable.classList.remove('dragging')
    draggable.setAttribute('draggable', false)
  })
  draggable.addEventListener('pointercancel', e => {
    console.log(e)
    e.preventDefault()
  })
})

function positionPlayer(e, player) {
  e.preventDefault()
  player.style.position = 'absolute'
  player.style.left = `${e.pageX-player.clientWidth/2}px`
  player.style.top = `${e.pageY-player.clientWidth/2}px`
  console.log(e)

}

https://jsfiddle.net/MG_03035/fcjxb5Lp/

javascript drag-and-drop pointer-events
1个回答
0
投票

我建议使用

position: absolute;
,这样您就可以轻松地依靠光标位置来应用拖放功能的位置。

然后,我还建议对事件侦听器使用

mousemove
mouseup
,以更好地捕获您想要使用的用户响应类型。

最后,我会在触发拖动功能之前使用边距布局 div,然后在选择后删除 div 上的边距。

let offsetX, offsetY;
let isDragging = false;
let currentDraggable = null;

document.addEventListener('mousedown', (e) => {
  if (e.target.classList.contains('draggable')) {
    isDragging = true;
    currentDraggable = e.target;
    offsetX = e.clientX - currentDraggable.getBoundingClientRect().left;
    offsetY = e.clientY - currentDraggable.getBoundingClientRect().top;
    currentDraggable.style.margin = 0;
    currentDraggable.style.cursor = 'grabbing';
  }
});

document.addEventListener('mousemove', (e) => {
  if (!isDragging) return;

  const x = e.clientX - offsetX;
  const y = e.clientY - offsetY;

  currentDraggable.style.left = `${x}px`;
  currentDraggable.style.top = `${y}px`;
});

document.addEventListener('mouseup', () => {
  if (isDragging) {
    isDragging = false;
    currentDraggable.style.cursor = 'grab';
    currentDraggable = null;
  }
});
body {
  margin: 0;
  padding: 10px;
  overflow: hidden;
}

div:nth-child(2) {
  margin-left: 70px;
}

div:nth-child(3) {
  margin-left: 135px;
}

.draggable {
  width: 50px;
  height: 50px;
  border: 1px solid #000;
  border-radius: 10px;
  background-color: blueviolet;
  position: absolute;
  cursor: grab;
  margin: 5px;
}

.dragging {
  border: 5px solid white;
  border-radius: 6px;
  margin: 2px;
  color: blue;
}

.draggable.dragging {
  opacity: .5;
}
<body>
  <div class="draggable" id="player1">1</div>
  <div class="draggable" id="player2">2</div>
  <div class="draggable" id="player3">3</div>
</body>

© www.soinside.com 2019 - 2024. All rights reserved.