移动端Swiper横向滑动时如何避免页面误触发垂直滚动?
问题:iOS移动端Swiper组件滑动时页面上下跳动
我在项目中实现了Swiper组件,整体表现正常,但在iOS设备(iPhone 13 mini测试)上重复滑动时,页面会随滑动角度轻微上下跳动,疑似Swiper对垂直方向手势过于敏感。
已尝试的解决方法:
- 调整
shortSwipes、longSwipes及相关毫秒参数,无效 - 在Swiper的transition start/end事件中添加
touch-action: none;,效果不理想 - 目前仅能通过
onTouchStart事件完全禁用垂直滚动,但这会导致页面无法正常滚动
期望实现类似谷歌移动端演员搜索结果中电影轮播的流畅滑动效果。
我的Swiper组件代码
<Swiper className={`${styles.swiper} ${mobileScrollLock ? styles['swiper-scroll-lock'] : ''}`} onSwiper={setSwiperInstance} onTouchEnd={onTouchEnd} onBeforeTransitionStart={() => setMobileScrollLock(true)} onTransitionEnd={() => setMobileScrollLock(false)} modules={[Mousewheel, FreeMode]} spaceBetween={10} slidesPerView='auto' mousewheel freeMode={{ enabled: true, sticky: true, }} > {loading.newPosts && <SwiperSlide className={styles['post-item-spinner']} key='spinner'><Spinner /></SwiperSlide>} {postsData && postsData.map((post: TStory) => { return <SwiperSlide className={styles['swiper-slide']} key={post.id}> <PostItem post={post} /> </SwiperSlide> })} {loading.oldPosts && <SwiperSlide className={styles['post-item-spinner']} key='spinner'><Spinner /></SwiperSlide>} </Swiper>
相关函数代码
const onTouchEnd = (swiper: SwiperType) => { if (swiper.progress < 0) checkNewPosts(); if (-swiper.translate > swiper.snapGrid[swiper.snapGrid.length - 1] + 100 && !limit) { setLoading({ postFeed: false, newPosts: false, oldPosts: true }); addOlderPosts(); } } const enableScroll = () => window.onscroll = null; const disableScroll = () => { const scrollTop = window.pageYOffset || document.documentElement.scrollTop; window.onscroll = () => window.scroll({ top: scrollTop }); }
解决方案
1. 精准控制触摸行为,避免垂直干扰
给Swiper容器添加CSS,明确限制触摸动作仅允许水平方向滑动,同时保留页面垂直滚动权限:
.swiper { touch-action: pan-y pinch-zoom; }
或者直接使用Swiper内置的touchAction配置项(适配Swiper内部逻辑,更推荐):
<Swiper // ...其他配置 touchAction="pan-y pinch-zoom" >
2. 动态锁定垂直滚动,仅在水平滑动时生效
替换当前生硬的滚动锁定逻辑,改为根据触摸方向动态控制:
const disableVerticalScroll = () => { document.body.style.overflowY = 'hidden'; document.body.style.touchAction = 'pan-x'; }; const enableVerticalScroll = () => { document.body.style.overflowY = ''; document.body.style.touchAction = ''; };
然后修改Swiper的触摸事件,仅在用户明确进行水平滑动时锁定垂直滚动:
<Swiper // ...其他配置 onTouchStart={(swiper, event) => { const touch = event.targetTouches[0]; swiper.__startX = touch.clientX; swiper.__startY = touch.clientY; }} onTouchMove={(swiper, event) => { const touch = event.targetTouches[0]; const deltaX = Math.abs(touch.clientX - swiper.__startX); const deltaY = Math.abs(touch.clientY - swiper.__startY); if (deltaX > deltaY) { disableVerticalScroll(); } else { enableVerticalScroll(); } }} onTouchEnd={() => { enableVerticalScroll(); }} >
3. 优化FreeMode配置,降低滑动敏感度
调整freeMode参数,减少不必要的动量反弹和过度滑动:
freeMode={{ enabled: true, sticky: true, momentumBounce: false, momentumRatio: 0.5, }}
4. 移动端禁用Mousewheel功能
当前配置中开启的mousewheel仅适用于桌面端,移动端不需要,建议根据设备环境动态启用:
// 自行实现设备检测逻辑,或使用第三方库 const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); <Swiper // ...其他配置 mousewheel={!isMobile} >
内容的提问来源于stack exchange,提问作者magrega
相关产品推荐
相关产品推荐

