长按事件在移动端怎么实现才靠谱?
我在做一个移动端的图片预览功能,想实现长按图片弹出保存菜单,但试了 touchstart + setTimeout 的方式,总感觉不太稳定,有时候会和滚动冲突,有时候又触发不了。
我给图片加了点基础样式防止误触,但还是有问题:
.preview-image {
user-select: none;
-webkit-touch-callout: none;
pointer-events: auto;
touch-action: manipulation;
}
有没有更可靠的方案?比如用 PointerEvent 或者现成的库?自己手写真的太容易出边界情况了……
contextmenu事件,这是浏览器原生支持的,比你自己用 touchstart + setTimeout 拼凑稳定得多。核心思路:
1. 监听 contextmenu 事件
2. 阻止默认行为(弹出系统菜单)
3. 在回调里执行你的保存逻辑
这个方案的优点是不用你自己处理定时器和滚动冲突,浏览器已经帮你区分好了。
如果你需要更精确地控制长按时间(比如区分单击和长按),可以用 Pointer Events 配合定时器。按照规范,Pointer Events 是 W3C 推荐的统一输入方案,能同时处理鼠标、触摸和触控笔:
你之前试的 touchstart 方案问题在于:移动端触摸事件和滚动事件的关系比较复杂,浏览器对 touch-action 的支持也不一致。Pointer Events 统一了这些,而且 pointermove 判断位移来取消长按这个做法也比较常见。
至于库的话,如果你项目里已经有 hammer.js 可以直接用它的 Press 事件,否则没必要为了个长按单独加依赖,上面的手写方案已经够稳了。
最后提醒一下,
-webkit-touch-callout: none;这个属性在 iOS 上可以禁用默认的长按菜单,配合上面的方案效果更好。