能否用requestAnimationFrame优化Logo滚动消失效果的流畅度?
滚动覆盖时Logo平滑消失的优化实现
你的问题出在scroll事件里直接操作DOM,触发频率过高导致布局抖动,加上计算逻辑里的固定偏移误差,才会出现Logo片段残留。用requestAnimationFrame可以把DOM更新操作批量放到浏览器的重绘周期中执行,既能保证流畅无卡顿,又能通过精准计算消除残留问题,以下是优化后的实现:
核心优化点
- 用
requestAnimationFrame节流滚动处理逻辑,避免频繁DOM操作引发的布局抖动 - 修正滚动方向判断的初始值问题,防止首次滚动逻辑异常
- 重构Logo高度计算逻辑,移除固定偏移,基于元素实际位置差精准计算
- 增加高度边界限制,确保Logo高度始终在合理范围内(0到原始高度之间)
修改后的JavaScript代码
const el1 = document.querySelector(".logo"); const el2 = document.querySelector(".clickblocks"); const logoHeight = el1.offsetHeight; let oldScroll = window.scrollY; let scrollDirectionDown = true; let rafId = null; // 精准计算Logo应显示的高度 function calculateLogoHeight() { const logoRect = el1.getBoundingClientRect(); const blocksRect = el2.getBoundingClientRect(); let targetHeight = logoHeight; if (scrollDirectionDown) { // 向下滚动时,计算blocks覆盖Logo的高度 const overlapTop = Math.max(logoRect.top, blocksRect.top); const overlapBottom = Math.min(logoRect.bottom, blocksRect.bottom); const overlapHeight = overlapBottom - overlapTop; if (overlapHeight > 0) { targetHeight = logoHeight - overlapHeight; } } else { // 向上滚动时,计算blocks离开Logo的高度 const distanceFromLogoBottom = logoRect.bottom - blocksRect.top; if (distanceFromLogoBottom < logoHeight) { targetHeight = distanceFromLogoBottom; } } // 限制高度在0到原始高度之间 targetHeight = Math.max(0, Math.min(targetHeight, logoHeight)); el1.style.height = `${targetHeight}px`; } window.addEventListener("scroll", () => { // 判断滚动方向 scrollDirectionDown = window.scrollY >= oldScroll; oldScroll = window.scrollY; // 取消之前的requestAnimationFrame,避免任务堆积 if (rafId) { cancelAnimationFrame(rafId); } // 在下一帧执行计算和DOM更新 rafId = requestAnimationFrame(calculateLogoHeight); });
对应的CSS代码(仅调整关键部分,其余保留)
.logo { background: url("https://svgshare.com/i/ivR.svg"); width: 100%; background-repeat: no-repeat; background-position: top; position: fixed; top: 100px; /* 增加过渡动画让高度变化更丝滑 */ transition: height 0.05s linear; }
HTML代码(无需改动,保留原结构)
<div class="wrapper"> <main> <div class="logo-wrapper" style="height: 390px"> <div class="logo" style="height: 300px"> </div> </div> <div class="clickblocks"> <div class="clickblock"> Some Content </div> </div> </main> </div>
效果说明
优化后的代码会在滚动时精准计算clickblocks元素与Logo的重叠高度,通过requestAnimationFrame确保每次高度更新都在浏览器重绘前完成,彻底消除卡顿和Logo残留问题。同时添加了高度边界限制,避免出现负高度或超出原始高度的异常情况,加上CSS过渡动画,让消失/恢复的过程更丝滑。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

