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

React:实现固定头部感知下方Div并触发调整逻辑

根据滚动位置切换头部Logo颜色方案

核心思路

通过监听页面滚动事件,定位头部下方对应的页面区块,计算该区块背景色的明暗度,据此切换Logo的颜色样式,实现适配不同背景的视觉效果。

实现步骤与代码示例

1. 基础结构与样式

先搭建页面结构,固定头部包含Logo,页面划分不同明暗的区块:

<!-- 固定头部 -->
<header class="header">
  <div class="logo" id="siteLogo">Logo</div>
</header>

<!-- 页面区块 -->
<section class="block block-dark">深色区块</section>
<section class="block block-light">浅色区块</section>
<section class="block block-dark">深色区块</section>
<section class="block block-light">浅色区块</section>

对应的CSS样式:

.header {
  position: fixed;
  top: 0;
  width: 100%;
  padding: 1rem;
  background: transparent;
}

.logo {
  font-size: 1.5rem;
  font-weight: bold;
  transition: color 0.3s ease;
}

/* Logo颜色状态类 */
.logo-dark {
  color: #000;
}
.logo-light {
  color: #fff;
}

.block {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
}

.block-dark {
  background-color: #222;
  color: #fff;
}

.block-light {
  background-color: #eee;
  color: #000;
}

2. 滚动监听与逻辑处理

编写JavaScript实现核心功能,包含滚动防抖、区块定位、亮度计算:

const header = document.querySelector('.header');
const logo = document.getElementById('siteLogo');
const blocks = document.querySelectorAll('.block');
const headerHeight = header.offsetHeight;

// 防抖函数,避免滚动事件频繁触发
function debounce(func, delay = 100) {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

// 计算颜色亮度(0-255,127为分界点)
function getColorBrightness(hexColor) {
  // 处理简写hex(如#fff)
  const hex = hexColor.replace('#', '');
  const r = parseInt(hex.length === 3 ? hex[0].repeat(2) : hex.slice(0, 2), 16);
  const g = parseInt(hex.length === 3 ? hex[1].repeat(2) : hex.slice(2, 4), 16);
  const b = parseInt(hex.length === 3 ? hex[2].repeat(2) : hex.slice(4, 6), 16);
  // 加权亮度公式,符合人眼感知
  return (r * 299 + g * 587 + b * 114) / 1000;
}

// 判断当前头部下方对应的区块
function getCurrentUnderlyingBlock() {
  const scrollTop = window.scrollY;
  // 取头部中间位置作为检测点,避免边缘切换时的频繁跳动
  const targetY = scrollTop + headerHeight / 2;

  for (const block of blocks) {
    const blockTop = block.offsetTop;
    const blockBottom = blockTop + block.offsetHeight;
    if (targetY >= blockTop && targetY < blockBottom) {
      return block;
    }
  }
  return null;
}

// 更新Logo颜色
function updateLogoColor() {
  const currentBlock = getCurrentUnderlyingBlock();
  if (!currentBlock) return;

  const bgColor = window.getComputedStyle(currentBlock).backgroundColor;
  // 将RGB格式转换为HEX
  let hexColor;
  if (bgColor.startsWith('rgb')) {
    const rgb = bgColor.match(/\d+/g).map(Number);
    hexColor = `#${((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1)}`;
  } else {
    hexColor = bgColor;
  }

  const brightness = getColorBrightness(hexColor);
  // 根据亮度切换Logo类
  if (brightness > 127) {
    logo.classList.add('logo-dark');
    logo.classList.remove('logo-light');
  } else {
    logo.classList.add('logo-light');
    logo.classList.remove('logo-dark');
  }
}

// 初始加载时执行一次,确保初始状态正确
updateLogoColor();
// 绑定防抖后的滚动事件
window.addEventListener('scroll', debounce(updateLogoColor));

关键细节说明

  • 防抖处理:滚动事件会频繁触发,用防抖函数减少计算次数,提升页面性能
  • 检测点选择:取头部中间位置作为检测点,避免头部边缘区块切换时的Logo颜色频繁跳动
  • 亮度计算:使用加权公式计算颜色亮度,结果更符合人眼对明暗的实际感知
  • 初始状态处理:页面加载完成后立即执行一次颜色更新,避免初始状态Logo颜色与背景不匹配

内容的提问来源于stack exchange,提问作者Bert1986

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:27:41