如何实现滚动逐行切换显示图片 保留parallax.js视差效果
逐行滚动切换图片实现方案
核心原则:完全保留原有parallax.js视差效果,不修改其初始化逻辑,仅通过容器控制、自动分行、滚动方向监听实现逐行切换的平滑交互。
实现逻辑
- 自动识别网格布局下的图片行分组,无需手动给元素添加行标识,适配原有grid跨列规则
- 容器固定为单行高度、溢出隐藏,初始仅展示第一行内容
- 加动画锁防止快速滚动时的跳变bug,所有切换使用缓动动画实现平滑过渡
- 视口尺寸变化时自动重新计算行分组,适配响应式场景
第一步:替换/追加CSS样式
保留原有parallax相关样式,补充动画和布局控制代码:
.parallax-window { min-height: 400px; background: transparent; /* 固定容器高度为单行高度,溢出隐藏 */ height: 475px; overflow: hidden; position: relative; } .service-box-container{ display: grid; grid-template-columns: repeat(6, 2fr); gap: 15px; /* 容器平移动画 */ transition: transform 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94); width: 100%; } .service-box-container .service-box{ grid-column: span 2; /* 单元素进出场动画初始状态 */ opacity: 0; transform: translateY(30px); transition: opacity 0.5s ease, transform 0.5s ease; } .service-box-container .service-box:nth-child(5n+4), .service-box-container .service-box:nth-child(5n+5) { grid-column: span 3; } /* 清除figure默认边距,避免高度计算偏差 */ .service-box figure { margin: 0; } /* 激活行的元素显示状态 */ .service-box-container .service-box.active-row { opacity: 1; transform: translateY(0); } .service-box-container img{ max-width: 100%; width: 100%; object-fit: cover; object-position: center; height: 460px; border-radius: 20px; }
第二步:添加交互JS代码
将以下代码放在原有parallax初始化逻辑之后,不会干扰原有视差效果:
$(document).ready(function(){ // 原有视差初始化代码完全保留,不做任何修改 $('.parallax-window').parallax({}); const $container = $('.service-box-container'); const $boxes = $('.service-box'); let currentRow = 0; let isAnimating = false; const rowHeight = 475; // 与容器高度保持一致 let rows = []; // 自动按网格位置对元素分行 function groupRows() { rows = []; let lastTop = -1; $boxes.removeClass('active-row'); $boxes.each(function() { const top = Math.round($(this).position().top); if (top !== lastTop) { rows.push([]); lastTop = top; } rows[rows.length - 1].push($(this)); }); showRow(currentRow); } // 展示指定索引的行 function showRow(rowIndex) { if (rowIndex < 0 || rowIndex >= rows.length || isAnimating) return; isAnimating = true; // 容器整体位移实现行切换 $container.css('transform', `translateY(-${rowIndex * rowHeight}px)`); // 切换当前行元素激活状态 $boxes.removeClass('active-row'); rows[rowIndex].forEach($el => $el.addClass('active-row')); // 动画结束后解锁 setTimeout(() => { isAnimating = false; }, 600); } // 防抖工具,避免窗口resize时频繁计算 function debounce(func, wait) { let timeout; return function() { const context = this, args = arguments; clearTimeout(timeout); timeout = setTimeout(() => func.apply(context, args), wait); }; } // 初始化分行 groupRows(); // 窗口尺寸变化时重新计算分行 $(window).on('resize', debounce(groupRows, 200)); // 监听滚动方向触发行切换 let lastScrollY = window.scrollY; $(window).on('scroll', function() { const currentScrollY = window.scrollY; const scrollDown = currentScrollY > lastScrollY; // 仅当容器在视口范围内时触发切换 const rect = $container[0].getBoundingClientRect(); const containerInView = rect.top < window.innerHeight && rect.bottom > 0; if (!containerInView || isAnimating) { lastScrollY = currentScrollY; return; } currentRow = scrollDown ? currentRow + 1 : currentRow - 1; showRow(currentRow); lastScrollY = currentScrollY; }); });
效果说明
- 原有parallax.js背景视差效果完全不受影响
- 页面初始加载仅展示第一行图片
- 向下滚动时上一行平滑上移淡出,下一行同步淡入展示
- 向上滚动时自动回退展示上一行内容
- 快速滚动时不会出现行错乱、跳变问题
- 窗口大小变化时自动适配网格布局,重新计算行位置
内容的提问来源于stack exchange,提问作者Aayush Dahal
相关产品推荐
相关产品推荐

