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

求助:如何在React中实现随组件滚动切换背景图(仿Tomorrowland)

React实现滚动切换背景图(仿Tomorrowland官网效果)

我正在学习React,看到Tomorrowland官网首页存在随组件滚动切换背景图的效果,希望复现该功能,但不清楚如何编写对应代码,特此请求技术帮助。现有代码如下:

import './App.css';
import Hero from './components/hero/Hero';

function App() {
  return (
    <div className="app">
      <div className="Blobs_blobs__cW0d3">
        <img src="/images/principal_bg.jpg" className="Blobs_backgroundImage__ciJQh Blobs_visible__EJ_Hc" alt="default background" />
        <img src="/images/bleu_bg.jpg" className="Blobs_backgroundImage__ciJQh" alt="Belgium background" />
        <img src="/images/blanc_bg.jpg" className="Blobs_backgroundImage__ciJQh" alt="Winter background" />
        <img src="/images/violet_bg.jpg" className="Blobs_backgroundImage__ciJQh" alt="Brasil background" />
        <img src="/images/rouge_bg.jpg" className="Blobs_backgroundImage__ciJQh" alt="Owr background" />
      </div>
      <div className='appContainer'>
        <Hero />
        <Hero />
        <Hero />
        <Hero />
        <Hero />
      </div>
    </div>
  );
}

实现方案

1. 调整CSS样式

先确保背景图容器固定在视口,背景图全屏覆盖,仅visible类的图片显示:

/* App.css */
.app {
  position: relative;
}

.Blobs_blobs__cW0d3 {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: -1; /* 让背景图在内容下方 */
}

.Blobs_backgroundImage__ciJQh {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover; /* 保持图片比例 */
  opacity: 0;
  transition: opacity 0.5s ease; /* 添加平滑过渡动画 */
}

.Blobs_visible__EJ_Hc {
  opacity: 1;
}

.appContainer {
  position: relative;
  z-index: 1; /* 确保内容在背景图上方 */
}

/* 假设每个Hero组件占满整个视口高度 */
.Hero {
  height: 100vh;
}

2. 修改React组件逻辑

添加滚动监听,动态切换背景图的可见状态:

import { useState, useEffect } from 'react';
import './App.css';
import Hero from './components/hero/Hero';

// 防抖函数,减少滚动事件触发频率,优化性能
const debounce = (func, delay) => {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
};

function App() {
  const [activeBgIndex, setActiveBgIndex] = useState(0);

  useEffect(() => {
    const handleScroll = debounce(() => {
      // 计算当前滚动位置对应的Hero组件索引(基于视口高度)
      const scrollTop = window.scrollY;
      const heroHeight = window.innerHeight;
      const currentIndex = Math.floor(scrollTop / heroHeight);
      // 边界处理,防止索引超出背景图数组范围
      const clampedIndex = Math.max(0, Math.min(currentIndex, 4));
      setActiveBgIndex(clampedIndex);
    }, 100); // 100ms防抖延迟

    window.addEventListener('scroll', handleScroll);
    // 组件卸载时移除监听
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    <div className="app">
      <div className="Blobs_blobs__cW0d3">
        {[
          '/images/principal_bg.jpg',
          '/images/bleu_bg.jpg',
          '/images/blanc_bg.jpg',
          '/images/violet_bg.jpg',
          '/images/rouge_bg.jpg'
        ].map((src, index) => (
          <img
            key={index}
            src={src}
            className={`Blobs_backgroundImage__ciJQh ${index === activeBgIndex ? 'Blobs_visible__EJ_Hc' : ''}`}
            alt={`Background ${index}`}
          />
        ))}
      </div>
      <div className='appContainer'>
        <Hero />
        <Hero />
        <Hero />
        <Hero />
        <Hero />
      </div>
    </div>
  );
}

export default App;

关键说明

  • 防抖函数:避免滚动时频繁触发状态更新,减少不必要的重渲染。
  • 索引计算:通过滚动距离除以视口高度,得到当前可见的Hero组件索引,保证背景图与内容同步切换。
  • 过渡动画:CSS的opacity过渡让背景图切换更平滑,贴近Tomorrowland官网的效果。
  • 边界处理:用Math.max和Math.min限制索引范围,避免因滚动过度导致的数组越界错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:52:13