实现滚动响应式网格布局遇阻:菜单栏与文字动效需求
解决方案
一、菜单栏滚动缩放实现
核心思路
监听页面滚动事件,通过滚动方向判断,在特定阶段阻止页面默认滚动行为,动态修改菜单栏高度;当高度达到目标值后,恢复页面正常滚动。
代码实现
- 更新CSS:
.edge-panel { background-color: #eee; width: 20%; height: 301.5vh; } .menu-bar { background-color: #23252b; width: 30%; height: 75vh; position: sticky; margin-left: 70%; margin-top: 150px; top: 0; transform: translateX(30%); transition: height 0.3s ease-out; /* 优化过渡顺滑度 */ } .menu-bar:hover { border: 5px solid #eee; transition: border 0.2s ease-in-out; } /* 菜单栏收缩状态类 */ .menu-bar--collapsed { height: 10vh; /* 自定义目标收缩高度 */ }
- HTML结构:
<div class="edge-panel"> site name here <div class="menu-bar" id="menuBar"> menu here </div> </div>
- 原生JS逻辑:
const menuBar = document.getElementById('menuBar'); const initialHeight = 75; // 初始高度(单位:vh) const collapsedHeight = 10; // 收缩后目标高度(单位:vh) let currentHeight = initialHeight; let isCollapsed = false; let lastScrollTop = 0; window.addEventListener('scroll', (e) => { const scrollTop = window.pageYOffset || document.documentElement.scrollTop; const scrollDelta = scrollTop - lastScrollTop; // 向下滚动逻辑 if (scrollDelta > 0) { if (!isCollapsed) { e.preventDefault(); // 动态计算高度,确保不低于收缩值 currentHeight = Math.max(collapsedHeight, currentHeight - scrollDelta * 0.1); menuBar.style.height = `${currentHeight}vh`; // 达到收缩高度后,恢复页面滚动 if (currentHeight <= collapsedHeight) { isCollapsed = true; menuBar.classList.add('menu-bar--collapsed'); } } } // 向上滚动逻辑 else if (scrollDelta < 0) { if (isCollapsed) { e.preventDefault(); // 动态计算高度,确保不超过初始值 currentHeight = Math.min(initialHeight, currentHeight + Math.abs(scrollDelta) * 0.1); menuBar.style.height = `${currentHeight}vh`; // 恢复初始高度后,恢复页面滚动 if (currentHeight >= initialHeight) { isCollapsed = false; menuBar.classList.remove('menu-bar--collapsed'); } } } lastScrollTop = scrollTop; }, { passive: false }); // 必须设置该参数才能阻止默认滚动行为
关键说明
- 通过
scrollDelta判断滚动方向,精准控制菜单栏高度变化阶段。 - 调整
scrollDelta * 0.1中的系数,可改变高度变化的灵敏度。 passive: false是阻止默认滚动行为的必要配置。
二、单个字母滚动动效实现
核心思路
将每个字母封装为独立DOM元素,监听滚动事件,根据滚动位置为每个字母应用差异化的位移、透明度动画,形成错落的滚动响应效果。
代码示例
- HTML结构:
<div class="hero-text"> <span class="letter" data-delay="0">V</span> <span class="letter" data-delay="0.1">R</span> <span class="letter" data-delay="0.2">A</span> <span class="letter" data-delay="0.3">R</span> <span class="letter" data-delay="0.4">L</span> <span class="letter" data-delay="0.5">E</span> <span class="letter" data-delay="0.6">S</span> </div>
- CSS基础样式:
.hero-text { font-size: 8rem; font-weight: bold; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); } .letter { display: inline-block; transition: transform 0.5s ease-out, opacity 0.5s ease-out; }
- JS动画逻辑:
const letters = document.querySelectorAll('.letter'); window.addEventListener('scroll', () => { // 计算滚动进度百分比 const scrollPercent = window.pageYOffset / (document.documentElement.scrollHeight - window.innerHeight); letters.forEach(letter => { const delay = parseFloat(letter.dataset.delay); // 根据滚动进度和延迟值,计算每个字母的位移与透明度 const translateY = scrollPercent * 200 - delay * 50; const opacity = 1 - scrollPercent * 1.5 + delay * 0.5; letter.style.transform = `translateY(${translateY}px)`; letter.style.opacity = Math.max(0, opacity); }); });
关键说明
- 通过
data-delay属性为每个字母设置动画延迟,形成错落有致的视觉效果。 - 基于滚动百分比计算动画参数,滚动距离越大,字母的位移和透明度变化越明显。
- 可自定义
translateY和opacity的计算逻辑,调整动画的强度与方向。
内容的提问来源于stack exchange,提问作者Nickler-sama
相关产品推荐
相关产品推荐

