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

能否用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 22:50:27