提问人:user22911026 提问时间:11/15/2023 更新时间:11/15/2023 访问量:22
Javascript 拖放不适用于指针事件
Javascript drag and drop not working with pointer events
问:
我是 javascript 和 Web 开发的新手,所以我确信这里缺少一个概念,希望有一种简单的方法来解决这个问题。我正在使用指针事件进行拖放,似乎在使用触摸时效果很好。但是当使用鼠标时,可拖动的 div 将具有不可预知的行为。如果您在拖动 div 时快速移动鼠标,光标将失去元素,并且 div 将陷入困境。同样奇怪的是,可能相关的是,pointermove 事件将在没有首先触发指针的情况下触发。
我认为某种类型的默认行为导致了这个问题,所以我添加了一个 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)
}
答:
1赞
Nick Friesen
11/15/2023
#1
我建议使用,以便您可以轻松地依靠光标位置来应用拖放功能的位置。position: absolute;
然后,我还建议使用 ,和事件侦听器来更好地捕获您希望使用的用户响应类型。mouseup
mousedown
mousemove
最后,我会在触发拖动功能之前对 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.classList.add('dragging');
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.classList.remove('dragging');
currentDraggable.style.cursor = 'grab';
currentDraggable = null;
}
});
body {
margin: 0;
padding: 10px;
overflow: hidden;
font-family: Arial, Helvetica, sans-serif;
}
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;
margin: 2px;
color: blue;
}
.draggable.dragging {
opacity: .5;
}
<!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">1</div>
<div class=draggable id="player2">2</div>
<div class=draggable id="player3">3</div>
</div>
</div>
</body>
</html>
0赞
user22911026
12/6/2023
#2
谢谢尼克。我看到您通过将侦听器放在文档上解决了鼠标问题。触摸侦听器不是以这种方式工作的。我不得不把它们放在 div 上才能让它们工作......有点。我一直在寻找一种使用这两种类型的侦听器的简单方法。为此,答案是jQuery。我刚刚开始 Web 开发,所以我不知道 jQuery 的存在。:)对于任何可能正在阅读本文的人,对于像我这样的 Web 开发来说,我建议您先学习 vanilla js,然后学习 jQuery。您将体会到jQuery的帮助和效率。
评论