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

基于背景色动态切换导航栏(Logo及菜单)颜色的实现方案

实现导航Logo与菜单颜色随横向滚动平滑切换

实现思路

  1. 给每个滚动区块配置对应的导航目标颜色,通过自定义属性存储
  2. 监听Locomotive Scroll的滚动事件,获取横向滚动位置与进度
  3. 基于滚动进度对相邻区块的目标颜色进行插值计算,实现平滑过渡
  4. 将计算后的颜色应用到Logo和菜单元素上

代码修改与实现

1. HTML结构调整

给每个区块添加data-nav-color属性定义导航目标颜色,同时给导航元素添加ID方便选择:

<nav class="fixed w-full z-50" id="main-nav">
    <div class="container mx-auto flex my-7">
        <div class="w-1/2" id="logo-container">
            <!-- 建议使用可修改fill的SVG格式Logo,若为PNG需调整方案 -->
            <img src="/logo.svg" alt="logo" />
        </div>
        <ul class="flex w-1/2 gap-7 justify-end items-center text-white font-spacegrotesk" id="menu-list">
            <li>Work</li>
            <li>About</li>
            <li>Contact</li>
        </ul>
    </div>
</nav>
<div class="scroll-container relative w-full flex">
    <div data-scroll-section class="min-w-full min-h-screen h-screen bg-[#EDE1D1]" data-nav-color="#ffffff">
        <h1 class="text-white">section 1</h1>
    </div>
    <div data-scroll-section class="min-w-full min-h-screen h-screen bg-[#BD7E36]" data-nav-color="#ff0000">
        <h1 class="text-green-700">section 2</h1>
    </div>
    <div data-scroll-section class="min-w-full min-h-screen h-screen bg-[#6F311A]" data-nav-color="#00ff00">
        <h1 class="text-black">section 3</h1>
    </div>
</div>

2. JavaScript逻辑实现

添加颜色转换、插值计算与滚动监听逻辑:

// 十六进制颜色转RGB数组
function hexToRgb(hex) {
    const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
    hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? [
        parseInt(result[1], 16),
        parseInt(result[2], 16),
        parseInt(result[3], 16)
    ] : null;
}

// 颜色插值计算(实现平滑过渡)
function interpolateColor(color1, color2, factor) {
    const result = [];
    for (let i = 0; i < 3; i++) {
        result[i] = Math.round(color1[i] + factor * (color2[i] - color1[i]));
    }
    return `rgb(${result.join(',')})`;
}

// 初始化Locomotive Scroll
var locoScroll = new LocomotiveScroll({
    el: document.querySelector('.scroll-container'),
    smooth: true,
    direction: 'horizontal',
    class: true,
    multiplier: 1,
    lerp: 0.04,
    scrollbarContainer: false,
    getDirection: true,
    getSpeed: true,
    scrollFromAnywhere: true,
});

// 获取DOM元素
const logoImg = document.querySelector('#logo-container img');
const menuItems = document.querySelectorAll('#menu-list li');
const sections = document.querySelectorAll('[data-scroll-section]');
const sectionColors = Array.from(sections).map(section => hexToRgb(section.dataset.navColor));
let sectionWidth = window.innerWidth;

// 初始设置导航颜色
function setInitialColor() {
    const initialColor = sectionColors[0];
    const initialRgb = `rgb(${initialColor.join(',')})`;
    menuItems.forEach(item => item.style.color = initialRgb);
    logoImg.style.fill = initialRgb;
}

// 窗口大小变化时更新区块宽度
window.addEventListener('resize', () => {
    sectionWidth = window.innerWidth;
});

// 页面加载完成后设置初始颜色
window.addEventListener('load', setInitialColor);

// 监听滚动事件更新导航颜色
locoScroll.on('scroll', (args) => {
    const scrollX = args.scroll.x;
    const currentSectionIndex = Math.floor(scrollX / sectionWidth);
    const nextSectionIndex = Math.min(currentSectionIndex + 1, sections.length - 1);
    const progress = (scrollX % sectionWidth) / sectionWidth;

    const currentColor = sectionColors[currentSectionIndex];
    const nextColor = sectionColors[nextSectionIndex];
    const targetColor = interpolateColor(currentColor, nextColor, progress);

    // 应用颜色到菜单和Logo
    menuItems.forEach(item => item.style.color = targetColor);
    logoImg.style.fill = targetColor;
});

注意事项

  • 若你的Logo是PNG格式,无法直接通过fill属性修改颜色,建议替换为SVG格式;或使用CSS滤镜(如filter: hue-rotate())实现颜色变化,但自定义精准颜色的话SVG方案更可靠。
  • 可根据需求调整interpolateColor函数中的计算逻辑,优化过渡效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:10:16