gpt4 book ai didi

javascript - 实现鼠标拖动时出现问题

转载 作者:行者123 更新时间:2023-12-03 02:19:34 26 4
gpt4 key购买 nike

我想实现一个包含某些元素的可拖动 map 。

--> 请参阅 JSFiddle:https://jsfiddle.net/7ndx7s25/7/

通过使用mousedownmousemovemouseup我实现了拖动。然而我面临着问题:

  1. 当按下鼠标按钮然后移出窗口时,我没有收到 mouseup 事件。重新进入窗口(很久以前就释放了鼠标按钮)我的 map 仍然认为该按钮已按下并相应地出现异常行为。

  2. 本地图上有对象时,我在这些对象之间移动时不会收到 mousemove 事件。因此,当我进入和离开这样的物体时, map 会悬挂和跳跃。

  3. 当在这些对象上时,我仍然希望有一个移动鼠标光标。我可以更改每个对象上的 cursor 样式(在 Fiddle 中,我以对象 1 为例),但这似乎不是一个好方法。有没有更优雅的解决方案?

最佳答案

你需要例如mouseout 在离开canvas 时捕获,不过当光标移到其他元素上时该事件也会触发。

一个简单的解决方法是简单地将一个类添加到 canvas 中,并在这些类上设置 pointer-events: none

使用该类,您还可以控制光标,并避免使用脚本设置它。

堆栈片段

updateInfo = function() {
document.getElementById('info').innerHTML =
'Position = ' + JSON.stringify(position) +
'<br />dragInfo = ' + JSON.stringify(dragInfo);
};

const canvas = document.getElementsByTagName('canvas')[0];

let position = { x: 0, y : 0 };
let dragInfo = null;
updateInfo();

canvas.addEventListener('mousedown', function(e) {
dragInfo = {
startEvent: {
x: e.clientX,
y: e.clientY,
},
startPosition: position
};
canvas.classList.add('dragging');
updateInfo();
});

canvas.addEventListener('mousemove', function(e) {
if (dragInfo === null) return;

position = {
x: dragInfo.startPosition.x - (e.clientX - dragInfo.startEvent.x),
y: dragInfo.startPosition.y - (e.clientY - dragInfo.startEvent.y)
};
updateInfo();
});

canvas.addEventListener('mouseup', function(e) {
dragInfo = null;
canvas.classList.remove('dragging');
updateInfo();
});

canvas.addEventListener('mouseout', function(e) {
dragInfo = null;
canvas.classList.remove('dragging');
updateInfo();
});
* {
user-select: none;
font-family: monospace;
}
canvas {
background: black;
border: 1px solid red;
}
.dragging {
cursor: move;
}
.obj {
position: absolute;
width: 50px;
height: 50px;
background: green;
color: white;
text-align: center;
line-height: 50px;
font-weight: bold;
}
.dragging ~ .obj {
pointer-events: none;
}
<div id="myMap-ish">
<canvas width="500" height="300"></canvas>
<div class="obj" style="left: 30px; top: 35px">1</div>
<div class="obj" style="left: 175px; top: 79px">2</div>
<div class="obj" style="left: 214px; top: 145px">3</div>
<div class="obj" style="left: 314px; top: 215px">4</div>
</div>
<div id="info"></div>

<小时/>

另一个选择是在外部包装器上使用 mouseleave,即 myMap-ish 元素,它可以与上面添加的类结合起来以简单地进行光标处理。

mouseoutmouseleave 之间的主要区别是后者在悬停子项时不会触发,如下例所示,因此我们不需要切换pointer-events 就像我们在第一个示例中所做的那样。

请注意,在第一个示例中,在 canvas 上简单地使用 mouseleave 将会遇到与 mouseout 相同的问题,因为“其他元素”不是 canvas 的子元素。

堆栈片段

updateInfo = function() {
document.getElementById('info').innerHTML =
'Position = ' + JSON.stringify(position) +
'<br />dragInfo = ' + JSON.stringify(dragInfo);
};

const canvas = document.getElementById('myMap-ish');

let position = { x: 0, y : 0 };
let dragInfo = null;
updateInfo();

canvas.addEventListener('mousedown', function(e) {
dragInfo = {
startEvent: {
x: e.clientX,
y: e.clientY,
},
startPosition: position
};
canvas.style.cursor = 'move';
document.querySelectorAll('.obj')[0].style.cursor = 'move'; // TODO for all objects
updateInfo();
});

canvas.addEventListener('mousemove', function(e) {
if (dragInfo === null) return;

position = {
x: dragInfo.startPosition.x - (e.clientX - dragInfo.startEvent.x),
y: dragInfo.startPosition.y - (e.clientY - dragInfo.startEvent.y)
};
updateInfo();
});

canvas.addEventListener('mouseup', function(e) {
dragInfo = null;
canvas.style.cursor = 'default';
document.querySelectorAll('.obj')[0].style.cursor = 'default'; // TODO for all objects
updateInfo();
});

canvas.addEventListener('mouseleave', function(e) {
dragInfo = null;
canvas.style.cursor = 'default';
document.querySelectorAll('.obj')[0].style.cursor = 'default'; // TODO for all objects
updateInfo();
});
* {
user-select: none;
font-family: monospace;
}
canvas {
background: black;
border: 1px solid red;
}
.obj {
position: absolute;
width: 50px;
height: 50px;
background: green;
color: white;
text-align: center;
line-height: 50px;
font-weight: bold;
}
<div id="myMap-ish">
<canvas width="500" height="300"></canvas>
<div class="obj" style="left: 30px; top: 35px">1</div>
<div class="obj" style="left: 175px; top: 79px">2</div>
<div class="obj" style="left: 214px; top: 145px">3</div>
<div class="obj" style="left: 314px; top: 215px">4</div>
</div>
<div id="info"></div>

关于javascript - 实现鼠标拖动时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49220436/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com