我问了这个问题:PDF.JS叠加层不能被拖动。
我注意到 PDF.js 似乎阻止了document.onmousemove
和document.onmouseup
事件被触发。
我认为解决方案是使用该元素的onmousemove和onmouseup,但这会带来问题。
例如,如果鼠标移动速度过快,元素的onmousemove
和onmouseup
事件将停止触发。同样的事情发生,如果你尝试把它拖出界外,元素的事件将停止触发。您可以在下面的代码片段中亲自尝试。
// Modified from https://www.w3schools.com/howto/howto_js_draggable.asp
function dragElement(elmnt, _bounds) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
elmnt.onmousedown = dragMouseDown;
let bounds = [..._bounds];
bounds[2] -= +elmnt.style.width.slice(0, -2);
bounds[3] -= +elmnt.style.height.slice(0, -2);
function dragMouseDown(e)
{
e = e || window.event;
e.preventDefault();
pos3 = e.clientX;
pos4 = e.clientY;
elmnt.onmouseup = closeDragElement; // Originally document.onmouseup
elmnt.onmousemove = elementDrag; // Originally document.onmousemove
}
function elementDrag(e)
{
e = e || window.event;
e.preventDefault();
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
let yC = elmnt.offsetTop - pos2, xC = elmnt.offsetLeft - pos1;
if (xC < bounds[0]) xC = bounds[0];
else if (xC > bounds[2]) xC = bounds[2];
if (yC < bounds[1]) yC = bounds[1];
else if (yC > bounds[3]) yC = bounds[3];
elmnt.style.top = yC + "px";
elmnt.style.left = xC + "px";
}
function closeDragElement()
{
elmnt.onmouseup = null; // Originally document.onmouseup
elmnt.onmousemove = null; // Originally document.onmousemove
}
}
dragElement(toDrag, [0, 0, 200, 200]);
<div style="
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 200px;
border: 1px solid black
" onmousedown="event.preventDefault()" onmouseup="event.preventDefault()">
<h1 style="text-align:center">My PDF</h1>
<div style="
position: absolute;
left: 150px;
top: 150px;
width: 25px;
height: 25px;
border: 1px solid black;
">
</div>
<div id=toDrag style="
cursor: move;
position: absolute;
left: 10px;
top: 25px;
width: 25px;
height: 25px;
border: 1px solid black;
background-color: #cac;
border-radius: 25px
">
</div>
</div>
我的问题是,即使event.preventDefault()
被解雇,也要检测mousemove
和mouseup
。
我最好的猜测是这样的:
document.querySelectorAll('*').forEach(e => e.addEventListener('mousemove', elementDrag);
document.querySelectorAll('*').forEach(e => e.addEventListener('mouseup', closeDragElement);
但是,我担心这可能会影响性能,尤其是在mousemove
上。
DOM 事件传播分为三个阶段:捕获阶段、目标阶段和气泡阶段。粗略地说,事件首先向下工作到目标,到达目标,然后又向上工作。
EventTarget.addEventListener() 有一个可选参数useCapture
(请参阅文档):
useCapture
可选一个布尔值,指示此类型的事件是否为 在被派送给任何
listener
EventTarget
在它下面的 DOM 树中。冒泡的事件 向上通过树不会触发指定使用的侦听器 捕获。事件冒泡和捕获是传播的两种方式 嵌套在另一个元素中的元素中发生的事件, 当两个元素都为该事件注册句柄时。活动 传播模式确定元素接收 事件。请参阅 DOM 级别 3 事件和 JavaScript 事件顺序 详细解释。如果未指定,则useCapture
默认为false
。
话虽如此,您可以尝试类似的东西来侦听捕获阶段的事件,而不是气泡阶段:
document.addEventListener('mousemove', elementDrag, true);
document.addEventListener('mouseup', closeDragElement, true);