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

使用React setState实现视差效果:滚动时图片左右移动问题求助

问题核心原因

  1. 你现在用布尔状态控制固定的margin数值,没法实现随滚动距离实时变化的平滑视差效果,同时加的2s过渡动画会导致偏移更新和滚动不同步,看起来就像图片不跟着动
  2. 只写了0300px滚动区间的逻辑,没有补充300600px区间的右移动计算

修改方案

不用布尔值控制开关,直接存储滚动的垂直偏移量,分区间动态计算图片和文本的位置,修改后的完整代码如下:

import { useState, useEffect } from 'react';

export default function App() {
  // 直接存储滚动垂直偏移量
  const [scrollY, setScrollY] = useState(0);

  useEffect(() => {
    const handleScroll = () => {
      setScrollY(window.scrollY);
    };
    window.addEventListener('scroll', handleScroll);
    // 组件卸载时移除监听,避免内存泄漏
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  // 分区间计算图片偏移
  const getImageStyle = () => {
    // 以下系数都可以根据你想要的移动速度自行调整
    if (scrollY <= 300) {
      // 0~300px滚动区间:左移+下移,匹配你已有的效果
      return {
        marginRight: `${scrollY * 1}px`,
        marginTop: `${scrollY * 1}px`,
        transition: 'none' // 实时滚动不需要过渡,避免卡顿滞后
      }
    } else if (scrollY <= 600) {
      // 300~600px滚动区间:从左向右移动
      const offset = scrollY - 300;
      return {
        marginRight: `${300 - offset * 2}px`, // 系数越大右移速度越快
        marginTop: `${300 + offset * 0.5}px`,
        transition: 'none'
      }
    } else {
      // 滚动超过600px后的状态,可按需求自行修改
      return {
        marginRight: '-300px',
        marginTop: '450px',
        transition: 'none'
      }
    }
  }

  // 计算文本偏移
  const getTextStyle = () => {
    if (scrollY <= 300) {
      return {
        marginTop: `${800 - scrollY * 1.67}px`,
        transition: 'none',
        marginLeft: '120px'
      }
    } else {
      return {
        marginTop: '300px',
        transition: 'none',
        marginLeft: '120px'
      }
    }
  }

  return (
    <div className="background">
      <div
        style={{
          backgroundColor: "#0E2043",
          padding: "50px",
          height: "1000px",
          display: "flex",
          justifyContent: "center"
        }}
      >
        <div className="header">Vanuatu</div>
        <img
          className="image"
          style={getImageStyle()}
          alt="random"
          src="https://cdn.britannica.com/87/122087-050-1C269E8D/Cover-passport.jpg"
        />
        <div
          className="text"
          style={getTextStyle()}
        >
          Minimum Investment
        </div>
      </div>
    </div>
  )
}

优化建议

如果想要更好的性能,可以用transform: translate()代替margin修改位置,浏览器对transform的动画渲染性能更高,不会触发页面重排。如果滚动监听触发太频繁,也可以加节流函数限制触发频率,减少不必要的状态更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 22:15:02