滚动时切换堆叠图片opacity值的实现方案咨询
实现思路
1. 布局基础调整
- 给四张图片的父容器设置
position: relative,所有图片设置position: absolute; top: 0; left: 0; width: 100%; opacity: 0; transition: opacity 0.5s ease;(过渡时长可自定义),仅第一张图片初始设opacity: 1,确保它们完全堆叠在一起。 - 父容器要设置与图片一致的宽高(可通过JS动态获取图片尺寸,或者CSS固定),避免影响下方正常内容的布局。
2. 滚动事件控制核心
- 监听
wheel事件而非scroll事件,精准捕捉滚动方向并控制页面默认滚动行为:- 定义三个状态变量:
currentIndex: 当前已完全显示的图片索引(初始为0,对应第一张图)isTransitioning: 是否正在执行图片透明度过渡(防止滚动事件重复触发)isCompleted: 是否完成所有图片的切换(初始为false)
- 当
isCompleted为false时,调用event.preventDefault()阻止页面实际滚动;当所有图片切换完成后,不再阻止。
- 定义三个状态变量:
3. 滚动方向与过渡逻辑
向下滚动(deltaY > 0)
- 若
currentIndex < 3且!isTransitioning:- 将
isTransitioning设为true,给currentIndex + 1对应的图片设置opacity: 1。 - 监听该图片的
transitionend事件,过渡完成后:currentIndex += 1isTransitioning = false- 若
currentIndex === 3,将isCompleted设为true,允许页面正常滚动到下方内容。
- 将
向上滚动(deltaY < 0)
- 若
currentIndex > 0且!isTransitioning:- 将
isTransitioning设为true,给currentIndex对应的图片设置opacity: 0。 - 监听该图片的
transitionend事件,过渡完成后:currentIndex -= 1isTransitioning = false- 将
isCompleted设为false,重新阻止页面滚动。
- 将
4. 细节优化
- 给
wheel事件添加防抖处理,避免短时间内多次触发过渡(比如设置300ms的防抖阈值)。 - 每次
transitionend事件触发后,解绑事件监听,防止内存泄漏或重复执行。 - 通过JS动态获取图片的自然尺寸,给父容器设置对应宽高,适配不同图片尺寸。
核心代码片段示例
let currentIndex = 0; let isTransitioning = false; let isCompleted = false; const images = document.querySelectorAll('.stacked-image'); // 防抖函数 function debounce(func, delay) { let timeoutId; return function(...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; } const handleWheel = debounce((e) => { if (isTransitioning) return; if (!isCompleted) { e.preventDefault(); } // 向下滚动 if (e.deltaY > 0) { if (currentIndex < images.length - 1) { isTransitioning = true; const nextImg = images[currentIndex + 1]; nextImg.style.opacity = 1; nextImg.addEventListener('transitionend', () => { currentIndex++; isTransitioning = false; if (currentIndex === images.length - 1) { isCompleted = true; } nextImg.removeEventListener('transitionend', arguments.callee); }); } } // 向上滚动 else { if (currentIndex > 0) { isTransitioning = true; const currentImg = images[currentIndex]; currentImg.style.opacity = 0; currentImg.addEventListener('transitionend', () => { currentIndex--; isTransitioning = false; isCompleted = false; currentImg.removeEventListener('transitionend', arguments.callee); }); } } }, 300); window.addEventListener('wheel', handleWheel);
内容的提问来源于stack exchange,提问作者Andres SK
相关产品推荐
相关产品推荐

