数位板使用PointerEvent补全轨迹坐标数据

这篇博客探讨了在浏览器中处理数位板输入时,由于用户绘制速度过快导致的touch事件缺失问题。文章提出使用PointerEvent的pointermove事件来补足缺失的数据,确保在任何输入设备上都能准确捕捉位置变化。同时,介绍了PointerEvent的兼容性和与mousemove、touchmove事件的区别,并提供了一个简单的验证Demo。解决方案包括设置touch-action:none以同时触发pointermove和touchmove事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

出现原因

数位板的输入在浏览器上是通过监听touch事件实现的。一般情况下,一次完整的手写输入将依次触发 touchstart - touchmove - touchend 三种事件。但在某些场景下,比如用户在数位板上绘制的时间过短,起始点和结束点的距离过短,浏览器只能响应到 touchstart - touchend 两种事件,导致中间过程的输入位置数据缺失,影响用户体验。

解决方案

使用 PointerEvent 中的 pointermove 事件补全这段时间内的鼠标位置数据。

原理

简单来说,PointerEvent是输入设备的硬件层抽象(比如鼠标,触摸笔,或触摸屏上的一个触摸点),描述了用于处理来自设备(包括鼠标、笔、触摸屏等)的硬件无关指针输入的事件和相关接口,里面记录了输入的具体坐标,以及对应的输入设备类型(pen / mouse / touch)等相关参数,详细说明可以参考 PointerEvent MDN文档地址

通过这个事件,无论输入的方式是数位板、鼠标还是触摸屏,都能直接获取到交互点的坐标位置,它有一个优势在于即使现在已经为每种输入设备类型分别设置监听函数,这个事件依然能够被触发(touch事件除外,后续有说明),而且是只要指针位置发生了改变就会立刻触发此事件。利用这种特性,可以很容易恢复 touchstart - touchend 这段时间内缺失的事件。

简单验证

可以观察到,在 touchstart后,touchmove事件并没有立刻触发,但此时鼠标指针是有移动的,如果仅使用touch事件捕捉鼠标位置,那么从touchstart到第一个touchmove事件中间这 300ms 的位置数据将丢失。使用了pointermove事件后,可以明显观察到这段时间内的鼠标位置变化都被很好地收集起来,效果不错。验证demo源码在文末提供。
在这里插入图片描述

PointerEvent 兼容性

PointerEvent 属于比较新的 API,现在主流浏览器的新版本都支持。
在这里插入图片描述

pointermove、touchmove、mousemove的触发条件区别

(1)mousemove

经过验证,pointermove和mousemove将会同时触发,因此这里只需要二选一即可,功能是一致的

(2)touchmove

其实从刚刚验证的图里面可以看到,当touchmove响应后,pointermove事件被浏览器取消了。MDN上有提到过:

The pointermove event is fired when a pointer changes coordinates, and the pointer has not been canceled by a browser touch-action.

这里有个解决方案,参考 StackOverflow 上的一篇回答,可以通过给dom节点设置 touch-action:none 即可同时触发 pointermove 和 touchmove 事件。

验证Demo源码

写得比较简单,轻喷

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="test" style="width: 100vw; height: 100vh;"></div>
  <script>
    var dom = document.querySelector('#test');
    var isTouchDown = false;
    var isMouseDown = false;
    var isPointDown = false;
    dom.addEventListener('touchstart', () => {isTouchDown = true; console.log('%ctouchstart', 'color:#ff0000')}, false)
    dom.addEventListener('touchend', () => { isTouchDown = false; console.log('%ctouchend', 'color:#ff0000')}, false)
    dom.addEventListener('touchmove', () => { isTouchDown && console.log('%ctouchmove', 'color:#00ff00')}, false)
    dom.addEventListener('mousedown', () => {isMouseDown = true; console.log('%cmousedown', 'color:#0000ff')}, false)
    dom.addEventListener('mouseup', () => { isMouseDown = false; console.log('%cmouseup', 'color:#0000ff')}, false)
    dom.addEventListener('mousemove', () => { isMouseDown && console.log('mousemove')}, false)
    dom.addEventListener('pointerdown', () => {isPointDown = true; console.log('%cpointerdown', 'color:#00ffff')}, false)
    dom.addEventListener('pointerup', () => { isPointDown = false; console.log('%cpointerup', 'color:#00ffff')}, false)
    dom.addEventListener('pointermove', (e) => { isPointDown && console.log('%cpointermove', 'color:#aaaa00')}, false)
    dom.addEventListener('pointerleave', () => { isPointDown && console.log('%cpointerleave', 'color:#00ffff')}, false)
  </script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZTao-z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值