核心是通过touchstart记录起始坐标,touchmove中累加绝对位移distX、distY,比较二者大小判定主方向:distX > distY为左右滑(再依deltaX正负定右/左),否则为上下滑(依deltaY正负定下/上),需设阈值(如60px)防误触。

怎么用 touchstart 和 touchmove 判断滑动方向
核心是记录手指按下和移动过程中的坐标变化,通过比较 clientX 和 clientY 的差值来判断主滑动方向。关键不是“有没有滑”,而是“哪个方向的位移更大”。
- 在
touchstart中保存初始位置:startX = e.touches[0].clientX、startY = e.touches[0].clientY - 在
touchmove中实时计算偏移:diffX = currentX - startX、diffY = currentY - startY - 用
Math.abs(diffX) > Math.abs(diffY)判断是否为水平主导 —— 这比单纯看正负更可靠,能过滤抖动 - 触发判定建议放在
touchend或首次满足阈值时(比如Math.abs(diffX) > 30),避免过早误判
为什么 touchmove 里直接 preventDefault() 会导致方向不准
禁用默认行为会阻止浏览器原生滚动,但也可能干扰触摸事件流,尤其在 iOS 上容易让 touches 列表异常(如突然变空或坐标跳变),导致 diffX/diffY 计算中断或失真。
- 只在明确要接管滑动逻辑时才调用
e.preventDefault(),且最好限定在已判定方向后的后续touchmove - 不要在
touchstart或首次touchmove就preventDefault(),否则 Android Chrome 可能不触发后续touchmove - 若需兼容页面内局部区域(如轮播图容器),给容器设
touch-action: none比全局preventDefault()更稳定
getBoundingClientRect() 对滑动方向检测有帮助吗
基本没用。方向检测依赖的是视口坐标系下的相对位移(clientX/Y),不是元素自身的位置。用 getBoundingClientRect() 反而引入滚动偏移、缩放等干扰因素,徒增复杂度。
- 所有坐标计算统一用
e.touches[0].clientX和e.touches[0].clientY,它们天然相对于当前视口 - 如果容器有
transform,也不影响clientX/Y,无需额外矫正 - 唯一需要
getBoundingClientRect()的场景是:你想把滑动映射到某个元素内部坐标系(比如画布绘图),但那是另一层需求,不属于方向检测本身
移动端真机测试时方向偶尔反向或失效怎么办
大概率是触发了系统级的手势(如 Safari 的返回 swipe、Android 的导航栏手势),它们会劫持部分 touch 事件,导致你的监听收不到完整序列。
立即学习“前端免费学习笔记(深入)”;
- 在
touchstart立即检查e.touches.length === 1,排除多指误触 - 加一个简单防抖:两次
touchmove间隔小于 16ms 时忽略,避免高频抖动污染判断 - iOS 必须在
body加touch-action: manipulation(或对应容器设touch-action: pan-x pan-y),否则某些机型会降级为 mouse 事件 - 真机调试优先用 Safari Web Inspector 或 Chrome Remote Debugging,别信模拟器的 touch 事件表现
实际写的时候最容易漏掉的是阈值校验和 touch-action 样式声明 —— 没这两条,90% 的“方向不准”问题都白调。



















