JavaScript 鼠标事件的意外行为

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

我想要的: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>

JS mousemove问题demo

javascript mouseevent mousemove
1个回答
0
投票

也许您最好使用更现代的拖放API来实现这种机制。
这也:

  • 带来了触摸设备的兼容性
  • 修复了损坏的
    mouseup
    行为
  • 提高性能(无需 z 索引分析和每秒 n 帧的迭代)

也许您还想实际移动 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>

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