setPointerCapture实现小球拖拽实例页面
回到相关文章 »效果:
按住小球拖动,可以试试把指针快速移出小球或容器。
left: 20px, top: 20px
代码:
CSS代码:
.drag-area {
position: relative;
height: 240px;
border: 1px dashed #a0b3d6;
background-color: #f7f9fd;
overflow: hidden;
/* 触屏拖动时禁止页面滚动 */
touch-action: none;
user-select: none;
}
.ball {
position: absolute;
left: 20px;
top: 20px;
width: 48px;
height: 48px;
border-radius: 50%;
background-image: radial-gradient(circle at 32% 28%, #fff 0, #7eaaf5 35%, #2b6ce1 100%);
cursor: grab;
touch-action: none;
}
.ball.dragging { cursor: grabbing; }
HTML代码:
<label><input type="checkbox" id="useCapture" checked> 使用 setPointerCapture</label>
<div class="drag-area" id="dragArea">
<div class="ball" id="ball"></div>
</div>
<p class="remind" id="pos">left: 20px, top: 20px</p>
JS代码:
const area = document.getElementById("dragArea");
const ball = document.getElementById("ball");
const useCapture = document.getElementById("useCapture");
const pos = document.getElementById("pos");
let dragging = false;
let offsetX = 0;
let offsetY = 0;
ball.addEventListener("pointerdown", function (event) {
dragging = true;
ball.classList.add("dragging");
// 关键:把后续所有指针事件都重定向到 ball
if (useCapture.checked) {
ball.setPointerCapture(event.pointerId);
}
const rect = area.getBoundingClientRect();
offsetX = event.clientX - rect.left - ball.offsetLeft;
offsetY = event.clientY - rect.top - ball.offsetTop;
});
ball.addEventListener("pointermove", function (event) {
if (dragging == false) {
return;
}
const rect = area.getBoundingClientRect();
const maxX = area.clientWidth - ball.offsetWidth;
const maxY = area.clientHeight - ball.offsetHeight;
// 限制在容器内
const x = Math.max(0, Math.min(maxX, event.clientX - rect.left - offsetX));
const y = Math.max(0, Math.min(maxY, event.clientY - rect.top - offsetY));
ball.style.left = x + "px";
ball.style.top = y + "px";
pos.textContent = "left: " + Math.round(x) + "px, top: " + Math.round(y) + "px";
});
const stopDrag = function (event) {
dragging = false;
ball.classList.remove("dragging");
if (ball.hasPointerCapture(event.pointerId)) {
ball.releasePointerCapture(event.pointerId);
}
};
ball.addEventListener("pointerup", stopDrag);
ball.addEventListener("pointercancel", stopDrag);
ball.addEventListener("lostpointercapture", stopDrag);