JS拖拽交互必用setPointerCapture方法

这篇文章发布于 2026年11月6日,星期五,17:51,归类于 JS API。 阅读 70 次, 今日 69 次 没有评论

 

一、还在mousedown个棒槌

关于拖拽的文章,我之前写过至少两三篇,之前实现逻辑都是这样。

一个拖拽标志量,一个存储数据的变量。

mousedown后标志量开启,存储初始数据,
然后在document文档上绑定mousemove,实时计算位置。
等mouseup后再恢复和处理。

用了很多年,自我感觉也挺好的,眼睛闭着都能手写出来。

实际上,上面这套实现已经过时了,且过时很久了。

现在还在使用mousedown实现拖拽效果,那就是个棒槌了。

应该使用pointerdown、pointerup这类事件(PC、Mobile双通),同时,移动的事件也不需要绑定在document或者<body>元素上了,直接写在触发元素上即可!

有人会问了,要是拖动太快,鼠标从触发元素上移出,岂不是pointermove事件不会触发?

是有这个问题,不过,此事件在设计的时候就考虑到这种场景了,于是设计了setPointerCapture方法,专门针对此问题。

二、setPointerCapture与拖拽

setPointerCapture可以捕获事件的pointerId,在鼠标或手势释放之前,后续所有事件都将以该捕获元素为目标。

所以拖拽的时候,不要担心目标元素会丢失。

眼见为实,直接看案例,假设一个球是ball:

<div class="ball" id="ball"></div>

那么所有拖拽事件都可以绑定在 ball 元素上,通过setPointerCapture捕获,不要担心拖拽行为那么容易丢失。

JS代码参考示意:

let dragging = false;
let offsetX = 0;
let offsetY = 0;

ball.addEventListener("pointerdown", function (event) {
    dragging = true;
    // 最关键代码就是我
    ball.setPointerCapture(event.pointerId);
    ...
});

ball.addEventListener("pointermove", function (event) {
    if (dragging == false) {
        return;
    }
    ...
});

const stopDrag = function (event) {
    dragging = false;
    if (ball.hasPointerCapture(event.pointerId)) {
        ball.releasePointerCapture(event.pointerId);
    }
};

ball.addEventListener("pointerup", stopDrag);
ball.addEventListener("pointercancel", stopDrag);
ball.addEventListener("lostpointercapture", stopDrag);

鼠标或手指按下的时候setPointerCapture,抬起的时候释放releasePointerCapture,就可以完成体验流畅的拖拽效果啦。

眼见为实,您可以狠狠地点击这里:setPointerCapture实现小球拖拽demo

小球拖拽截图

演示效果是AI生成的,虽然不是我的UI美学风格,但是算了,省心啊,嘿嘿😋。

三、在唠叨点什么,水些字数

哎呀,内容有点少了,再水些内容吧。

说到Pointer,我不自觉又联想到了requestPointerLock,这个是用来实现无限滚动的,属于JS Pointer Lock的内容,之前写文章介绍过:鼠标无限移动 JS API Pointer Lock简介

CSS的pointer-events:none可以干掉JS pointer相关的事件,不过却阻止不了focus交互。

还有啥,好有啥,我想想……

哦,还有个touch-action,与触摸有关的,可以阻止滚动啥的,可以防止自怼拖拽和原生滚动冲突。

然后老的setCapture()方法已经废弃了,万不可使用。

噢啦,差不多就这么多了。

感谢大家的阅读,周末愉快,祝我爆护。

这是我上周末钓的,168五小时,钓得都铺出来了,😁😁。

鳊鱼爆护

(本篇完)

分享到:


发表评论(目前没有评论)