如何限制移动端带scroll-x/y元素的触摸滑动方向,禁止斜向滑动
解决移动端双滚动轴元素限制单方向滑动的问题
要实现仅允许水平或垂直单方向滑动,仅靠CSS的touch-action没法完全满足需求——touch-action: pan-x pan-y仍然允许同时触发两个方向的滚动。这里需要结合JavaScript监听触摸事件,手动判断滑动方向并限制滚动行为:
实现思路
- 记录触摸开始时的坐标,在触摸移动时计算水平、垂直方向的偏移量
- 对比两个方向的偏移幅度,判断用户的核心滑动意图(水平或垂直)
- 通过动态设置
touch-action,阻止非意图方向的原生滚动行为
修改后的完整代码示例
body { display: flex; flex-wrap: wrap; } .map { margin: 1rem; width: 300px; height: 300px; overflow: scroll; position: relative; margin-bottom: 15px; /* 初始禁用浏览器默认触摸行为,由JS控制 */ touch-action: none; } .map img { width: 1200px; height: 1200px; } .map-desc { position: absolute; width: 100%; text-align: center; font-weight: bold; top: 130px; font-size: 24px; }
<div class="map" id="scrollContainer"> <img src='https://images.unsplash.com/photo-1526778548025-fa2f459cd5c1?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ' alt=''> <code class="map-desc">限制单方向滑动</code> </div>
const container = document.getElementById('scrollContainer'); let startX, startY; let isScrollingX = false; let isScrollingY = false; container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; startY = e.touches[0].clientY; isScrollingX = false; isScrollingY = false; }); container.addEventListener('touchmove', (e) => { if (isScrollingX || isScrollingY) return; const deltaX = Math.abs(e.touches[0].clientX - startX); const deltaY = Math.abs(e.touches[0].clientY - startY); // 判断核心滑动方向并设置对应规则 if (deltaX > deltaY) { isScrollingX = true; container.style.touchAction = 'pan-x'; } else { isScrollingY = true; container.style.touchAction = 'pan-y'; } }); // 触摸结束后重置规则,保证下次触摸可重新判断方向 container.addEventListener('touchend', () => { container.style.touchAction = 'none'; });
效果说明
- 用户触摸滑动初期,会自动识别主要滑动方向
- 一旦确定方向,就锁定只能在该方向滚动,彻底避免斜向滑动时双轴同时滚动的问题
- 每次触摸结束后重置规则,不影响下一次的方向选择
内容的提问来源于stack exchange,提问作者Berg_Durden
相关产品推荐
相关产品推荐

