我对 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)
}
我建议使用
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>