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

如何实现滚动到滑块区域时停止滚动优先切换幻灯片的效果

实现方案

HTML 代码

<section></section>
<section></section>
<section></section>
<!-- 滑块区域外层占位,避免fixed后页面高度塌陷 -->
<div class="slider-wrapper">
  <section class="slider">
    <div class="slide active">Slide 1</div>
    <div class="slide">Slide 2</div>
    <div class="slide">Slide 3</div>
  </section>
</div>
<section></section>
<section></section>

CSS 代码

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

section {
  width: 100%;
  height: 500px;
}
section:nth-child(odd) {
  background-color: #666;
}
/* 滑块外层占位容器,高度和滑块一致,避免fixed后页面跳变 */
.slider-wrapper {
  height: 500px;
}
section.slider {
  background-color: #e03c0b;
  display: flex;
  justify-content: center;
  align-items: center;
}
.slide {
  display: none;
  text-align: center;
  width: 50%;
  height: 200px;
  background-color: #888;
}
.slide.active {
  display: block;
}
.fixed {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
}

JS 代码

const container = document.querySelector('.slider');
const slides = document.querySelectorAll('.slide');
const slideCount = slides.length;
// 记录当前展示的幻灯片索引
let currentSlideIndex = 0;
// 记录滑块是否处于固定状态
let isSliderFixed = false;

// 切换幻灯片的公共方法
function switchSlide(index) {
  slides.forEach(el => el.classList.remove('active'));
  slides[index].classList.add('active');
  currentSlideIndex = index;
}

// 监听页面滚动,判断是否需要固定滑块
window.addEventListener('scroll', () => {
  const scrollTop = window.pageYOffset;
  const sliderOffsetTop = document.querySelector('.slider-wrapper').offsetTop;
  // 滚动到滑块区域,且还未完成所有幻灯片切换时,固定滑块
  if (scrollTop >= sliderOffsetTop && currentSlideIndex < slideCount - 1 && !isSliderFixed) {
    container.classList.add('fixed');
    isSliderFixed = true;
  }
  // 滚动回滑块区域上方时,重置幻灯片索引
  if (scrollTop < sliderOffsetTop && currentSlideIndex !== 0) {
    switchSlide(0);
    if (isSliderFixed) {
      container.classList.remove('fixed');
      isSliderFixed = false;
    }
  }
})

// 核心:监听滚轮事件,控制滚动优先级
window.addEventListener('wheel', (e) => {
  // 只有滑块固定时才拦截滚动
  if (!isSliderFixed) return;

  // 向下滚动
  if (e.deltaY > 0) {
    e.preventDefault();
    // 还有下一张幻灯片,切换
    if (currentSlideIndex < slideCount - 1) {
      switchSlide(currentSlideIndex + 1);
    } 
    // 已经是最后一张,解除固定,恢复页面滚动
    else {
      container.classList.remove('fixed');
      isSliderFixed = false;
      // 直接滚动到滑块下方区域,避免跳变
      window.scrollTo(0, document.querySelector('.slider-wrapper').offsetTop + container.offsetHeight);
    }
  }
  // 向上滚动
  else if (e.deltaY < 0) {
    e.preventDefault();
    // 还有上一张幻灯片,切换
    if (currentSlideIndex > 0) {
      switchSlide(currentSlideIndex - 1);
    }
    // 已经是第一张,解除固定,恢复页面滚动
    else {
      container.classList.remove('fixed');
      isSliderFixed = false;
      // 直接滚动到滑块上方区域,避免跳变
      window.scrollTo(0, document.querySelector('.slider-wrapper').offsetTop - 1);
    }
  }
// 必须设置passive: false,否则preventDefault会被浏览器忽略报错
}, { passive: false })
关键逻辑说明
  • 新增.slider-wrapper占位容器,解决滑块fixed后脱离文档流导致的页面高度突变、内容跳闪问题
  • 监听wheel事件时主动设置passive: false,确保可以正常调用e.preventDefault()拦截原生滚动
  • 仅在滑块处于固定状态时拦截滚动事件,其他时间保留原生滚动体验
  • 边界状态自动解除固定:向下滚动到最后一张幻灯片、向上滚动到第一张幻灯片时,自动退出固定状态,同时调用window.scrollTo定位到对应位置,避免滚动断层

内容的提问来源于stack exchange,提问作者Gremlin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 07:57:04