You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移动端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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:25:46