基于mousedown的横向滑块拖拽功能如何实现触摸适配?
横向滚动拖拽的触摸适配方案
完全不需要引入jQuery Mobile——这个库目前已经进入低维护状态,冗余代码多、包体积大,为了实现横向拖拽滚动的功能引入完全是杀鸡用牛刀。手写基于原生触摸事件的轻量适配逻辑,是目前业界针对这类场景的主流最佳实践,实现成本极低,性能远好于重型第三方库。
为什么现有代码在触摸设备上失效
你当前的代码只绑定了桌面端的鼠标事件,移动端浏览器虽然会对触摸操作做一定的鼠标事件模拟,但在你主动调用preventDefault中断默认行为后,这类模拟就会失效;同时移动端的触摸操作坐标存在于独立的Touch对象列表里,直接取e.pageX根本拿不到正确值,自然没法触发拖拽逻辑。
核心实现注意点
- 原生
touchstart/touchmove/touchend三个事件完全可以对齐现有鼠标事件的逻辑,一对一映射就行,比引入第三方库省至少几十KB的冗余代码 - 触摸事件的坐标不是直接挂在event对象根节点上的,是存在
e.touches这个触点数组里,单指操作就取第0个元素的pageX;一定要加判断逻辑:如果触点数不是1(比如用户双指捏合)就直接退出函数,别和系统手势抢事件 - 一定要给滚动容器加
touch-action: pan-y的CSS规则,不然拖拽的时候整个页面会跟着横向晃,浏览器默认的滚动优先级比绑定的JS事件高,光靠JSpreventDefault有时候拦不住,这行CSS写下去直接解决所有默认行为冲突的问题 - 不需要额外做老旧浏览器的兼容补丁,现在所有主流移动浏览器对这三个原生触摸事件的支持率已经覆盖绝大多数用户
可直接运行的完整适配代码
$(document).ready(function(){ const slider = document.querySelector('.home-cates-row'); let isDown = false; let startX; let scrollLeft; // 保留原有桌面端鼠标逻辑 slider.addEventListener('mousedown', (e) => { isDown = true; slider.classList.add('active'); startX = e.pageX - slider.offsetLeft; scrollLeft = slider.scrollLeft; }); slider.addEventListener('mouseleave', () => { isDown = false; slider.classList.remove('active'); }); slider.addEventListener('mouseup', () => { isDown = false; slider.classList.remove('active'); }); slider.addEventListener('mousemove', (e) => { if(!isDown) return; e.preventDefault(); const x = e.pageX - slider.offsetLeft; const walk = (x - startX) * 1; slider.scrollLeft = scrollLeft - walk; }); // 新增触摸端适配逻辑 slider.addEventListener('touchstart', (e) => { // 只响应单指操作 if (e.touches.length !== 1) return; isDown = true; slider.classList.add('active'); startX = e.touches[0].pageX - slider.offsetLeft; scrollLeft = slider.scrollLeft; }); slider.addEventListener('touchmove', (e) => { if(!isDown || e.touches.length !== 1) return; e.preventDefault(); const x = e.touches[0].pageX - slider.offsetLeft; const walk = (x - startX) * 1; slider.scrollLeft = scrollLeft - walk; }); slider.addEventListener('touchend', () => { isDown = false; slider.classList.remove('active'); }); });
配套需要在全局CSS里加一行规则,解决触摸行为冲突:
.home-cates-row { touch-action: pan-y; }
按上面的逻辑改造完,触摸端的拖拽手感和桌面端完全一致,不需要任何第三方依赖。如果后续想要更顺滑的物理滚动反馈,再引入对应的轻量滚动工具库就行,完全没必要上来就上jQuery Mobile这种重型框架。
内容的提问来源于stack exchange,提问作者Hamza Afzal
相关产品推荐
相关产品推荐

