You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Dragover事件下元素无法向左、向上移动的技术求助

解决元素无法向左/向上拖动的问题

你的问题出在**直接用dragover事件的clientX/clientY设置元素的left/top**上。当你这么做时,元素的左上角会瞬间跳到鼠标位置,一旦你向左或向上拖动,鼠标就会离开元素区域,dragover事件就不再触发了,自然没法继续移动。

下面给你两种可行的解决方案:

方案一:修正Drag事件逻辑(记录鼠标偏移量)

我们需要在dragstart事件中记录鼠标相对于元素左上角的偏移量,然后在dragover时用鼠标位置减去这个偏移量来设置元素位置,这样元素就能稳稳跟着鼠标移动,不会跑开:

const troll = document.getElementById('troll');
let offsetX, offsetY;

// 记录鼠标与元素的偏移
troll.addEventListener('dragstart', (e) => {
    // 计算鼠标在元素内的相对位置
    offsetX = e.clientX - troll.getBoundingClientRect().left;
    offsetY = e.clientY - troll.getBoundingClientRect().top;
    // 必须设置dataTransfer,否则部分浏览器的drag事件可能不触发
    e.dataTransfer.setData('text/plain', '');
});

troll.addEventListener('dragover', (e) => {
    e.preventDefault();
    // 用鼠标位置减去偏移量,得到元素应该的定位
    troll.style.left = `${e.clientX - offsetX}px`;
    troll.style.top = `${e.clientY - offsetY}px`;
});

CSS和HTML补充draggable属性后保持不变:

img {
    width: 100px;
    cursor: pointer;
    position: absolute;
}
<div id="troll" draggable="true">
    <img src="http://images.mmorpg.com/features/7909/images/Troll.png" alt="Troll">
</div>
> 注意:必须给`div#troll`加上`draggable="true"`,否则drag系列事件可能无法正常触发。

## 方案二:使用鼠标事件(更适合实时拖动场景)
其实`drag`系列事件更偏向**跨元素拖放操作**(比如把元素拖到另一个容器),如果只是让元素单纯跟随鼠标移动,用`mousedown`、`mousemove`、`mouseup`事件会更直观稳定:

```javascript
const troll = document.getElementById('troll');
let isDragging = false;
let startX, startY, initialLeft, initialTop;

troll.addEventListener('mousedown', (e) => {
    isDragging = true;
    // 记录初始点击位置和元素的初始定位
    startX = e.clientX;
    startY = e.clientY;
    initialLeft = parseInt(window.getComputedStyle(troll).left) || 0;
    initialTop = parseInt(window.getComputedStyle(troll).top) || 0;
    // 拖动时切换鼠标样式提升体验
    troll.style.cursor = 'grabbing';
});

// 全局监听鼠标移动,避免元素离开鼠标后事件中断
document.addEventListener('mousemove', (e) => {
    if (!isDragging) return;
    // 计算鼠标位移,更新元素位置
    const dx = e.clientX - startX;
    const dy = e.clientY - startY;
    troll.style.left = `${initialLeft + dx}px`;
    troll.style.top = `${initialTop + dy}px`;
});

document.addEventListener('mouseup', () => {
    isDragging = false;
    troll.style.cursor = 'pointer';
});

这个方案不需要设置draggable属性,拖动过程也不会因为元素移动而中断,体验会更流畅,是大多数拖动场景的首选方案~

内容的提问来源于stack exchange,提问作者Reza Saadati

火山引擎 最新活动