我想要的:div“dragItem”应该水平移动。 如果鼠标光标位于类为“tag”的 div 顶部,则“dragItem”的位置将发生变化。
实际上这是有效的。但是当我释放鼠标按钮而光标与开始移动的位置不在同一水平行时,我得到了一个奇怪的行为: 下次我单击“dragItem”时,在释放鼠标按钮之前我看不到移动。 并且:释放鼠标按钮后,我仍然可以移动“dragItem”。
我不明白为什么会发生这种情况。在尝试调试它时,我发现 - 如果我在单击“dragItem”之前单击屏幕上的某个位置 - 事情会按预期工作。但为什么呢?
dragItem = document.getElementById("dragItem")
dragItem.addEventListener('mousedown', dragMouseDownHandler)
mouseIsDown = false;
function dragMouseDownHandler(event) {
if (!mouseIsDown) {
mouseIsDown = true;
document.addEventListener('mousemove', mouseMove)
document.addEventListener('mouseup', mouseUp)
}
}
function mouseMove(event) {
var elementsUnderMouse = document.elementsFromPoint(event.clientX, event.clientY);
elementsUnderMouse.forEach(element => {
if (element.classList.contains("tag")) {
vonLinks = element.offsetLeft
dragItem.style.left = vonLinks + 'px'
}
})
}
function mouseUp(event) {
mouseIsDown = false;
document.removeEventListener('mousemove', mouseMove)
document.removeEventListener('mouseup', mouseUp)
}
#moveArea {
width: 600px;
height: 600px;
background-color: lightgray;
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex-direction: row;
}
.tag {
height: 110px;
width: 110px;
background-color: #b3d4fc;
border: 1px solid black;
}
#dragItem {
height: 100px;
width: 100px;
background-color: lightcoral;
position: fixed;
}
<div id="moveArea">
<div class="row">
<div class="tag">
<div id="dragItem"></div>
</div>
<div class="tag"></div>
<div class="tag"></div>
<div class="tag"></div>
</div>
<div class="row">
<div class="tag"></div>
<div class="tag"></div>
<div class="tag"></div>
<div class="tag"></div>
</div>
</div>
也许您最好使用更现代的拖放API来实现这种机制。
这也:
mouseup
行为也许您还想实际移动 DOM 中的元素,而不是在视觉上移动它的位置。这样视觉和逻辑外观将被 JS 对齐和处理。
所附代码片段显示了使用拖放的粗略实现。
const dragItem = document.getElementById('dragItem');
const dropTargets = document.querySelectorAll('.tag');
makeMoveableTo(dragItem, ...dropTargets);
/**
* Makes the `element` moveable (drag & drop) to the `targetElements`.
* @param {HTMLElement} element
* @param {...HTMLElement} targetElements
*/
function makeMoveableTo( element, ...targetElements )
{
element.addEventListener('dragstart', ( event ) =>
{
// Remember the id of the element to drag on dragstart
event.dataTransfer.setData('text/plain', event.target.id);
});
targetElements.forEach(targetElement =>
{
targetElement.addEventListener('dragover', ( event ) =>
{
// Mark target as drop-zone
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
});
targetElement.addEventListener('drop', ( event ) =>
{
// On drop, read the dragged element's id and call moveTo()
const dragElementId = event.dataTransfer.getData('text/plain');
const dragElement = document.getElementById(dragElementId);
moveTo(dragElement, event.target);
});
});
}
/**
* Moves the `element` to the `targetElement`.
* @param {HTMLElement} element
* @param {HTMLElement} targetElement
*/
function moveTo( element, targetElement )
{
element.style.left = `${targetElement.offsetLeft}px`;
// targetElement.append(element); // Maybe move element in DOM instead
}
#moveArea{
width: 600px;
height: 600px;
background-color: lightgray;
display: flex;
flex-direction: column;
}
.row{
display: flex;
flex-direction: row;
}
.tag{
height: 110px;
width: 110px;
background-color: #b3d4fc;
border: 1px solid black;
}
#dragItem{
height: 100px;
width: 100px;
background-color: lightcoral;
position: fixed;
}
<div id="moveArea">
<div class="row">
<div class="tag">
<div id="dragItem" draggable="true"></div>
</div>
<div class="tag"></div>
<div class="tag"></div>
<div class="tag"></div>
</div>
<div class="row">
<div class="tag"></div>
<div class="tag"></div>
<div class="tag"></div>
<div class="tag"></div>
</div>
</div>