如何同时适配触摸和鼠标事件检测滑动并判断方向,实现轮播手势操作
问题原因说明
- 事件名称错误:原生DOM不存在
mousestart事件,鼠标按下对应的事件为mousedown,且你直接替换了原有的触摸事件监听,导致移动端功能完全失效 - 事件对象属性不兼容:触摸事件通过
evt.touches数组取触点坐标,而鼠标事件没有该属性,直接从事件对象本身取clientX/clientY即可 - 逻辑缺失:没有限制仅在鼠标按下状态下的移动才触发滑动逻辑,也没有
mouseup事件重置坐标状态,会出现大量误触发 - 未做滑动方向优先级判断:当前代码只要有横向位移就会触发轮播,上下滑动时也会误触发跳转
修复后完整代码
// 同时注册触摸和鼠标两类事件,兼容多端 document.addEventListener('touchstart', handleStart, false); document.addEventListener('touchmove', handleMove, false); document.addEventListener('touchend', handleEnd, false); document.addEventListener('mousedown', handleStart, false); document.addEventListener('mousemove', handleMove, false); document.addEventListener('mouseup', handleEnd, false); // 鼠标移出目标区域也重置状态,避免误触发 document.addEventListener('mouseleave', handleEnd, false); var xDown = null; var yDown = null; // 新增阈值,避免微小位移就触发跳转,提升体验 const SWIPE_THRESHOLD = 30; function getPoint(evt) { // 兼容触摸和鼠标事件的坐标获取 if (evt.touches && evt.touches.length) { return evt.touches[0]; } return evt; } function handleStart(evt) { const firstPoint = getPoint(evt); xDown = firstPoint.clientX; yDown = firstPoint.clientY; }; function handleMove(evt) { if (!xDown || !yDown) { return; } // 阻止默认滑动行为,避免和页面原生滚动冲突,不需要可以删掉 evt.preventDefault(); const currentPoint = getPoint(evt); var xUp = currentPoint.clientX; var yUp = currentPoint.clientY; var xDiff = xDown - xUp; var yDiff = Math.abs(yDown - yUp); // 优先判断是横向滑动,且位移超过阈值才触发轮播 if (Math.abs(xDiff) > yDiff && Math.abs(xDiff) > SWIPE_THRESHOLD) { if (xDiff > 0) { jQuery('.CarouselNext').click(); } else { jQuery('.CarouselPrevious').click(); } // 触发后直接重置状态,避免一次滑动触发多次 handleEnd(); } }; function handleEnd() { xDown = null; yDown = null; }
额外优化说明
- 新增了
SWIPE_THRESHOLD滑动阈值,只有横向滑动距离超过30px才触发跳转,避免点击或者微小移动误触发 - 增加了方向优先级判断,只有横向位移大于纵向位移时才判定为轮播滑动,避免上下滚动页面时误触发轮播跳转
- 增加了
mouseleave和touchend/mouseup的统一状态重置逻辑,避免状态残留导致的误触发 - 保留了原有的触摸事件监听,移动端功能不受影响
内容的提问来源于stack exchange,提问作者Aditya Agarwal
相关产品推荐
相关产品推荐

