发布于 2026-01-06 1 阅读
0

使用 react-spring 创建视差效果

使用 react-spring 创建视差效果

我知道你们肯定在想:“又一篇用 react-spring 的博文?!这家伙……” 好吧,事实证明,我用 react-spring 做各种动画/运动效果真的挺开心的。而且,把这些写下来也让我更好地理解了它的工作原理。所以,没办法,开始吧。

市面上有一些不错的库可以帮助你轻松实现视差效果。但视差效果的基本原理其实很简单:组件 X(或其一部分)在水平或垂直方向上的移动速度与组件 Y 不同,从而产生深度感。因此,即使不使用专门的插件,实现同样的效果也并非难事。

目标

  1. 添加滚动监听器
  2. 通过设置 translateY 属性来应用视差效果

1. 添加滚动监听器

使用 React 的 Hook 添加滚动监听器其实非常简单useEffect。我们只需向 Hook 传递一个添加事件监听器的函数。该函数scroll的第一个参数是 `<script>` 标签,handleScroll第二个参数是一个函数。我们返回一个移除事件监听器的函数。通过返回这个函数,我们告诉 React 在组件更新或卸载时执行一些清理工作。

import React, { useEffect, useRef } from 'react';

const Comp = () => {
  const ref = useRef();

  const handleScroll = () => {
    const posY = ref.current.getBoundingClientRect().top;
    const offset = window.pageYOffset - posY;
    console.log(offset);
  };

  useEffect(() => {
    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  });

  return (<div ref={ref}>Contents of your component</div>)
}

export default Comp;
Enter fullscreen mode Exit fullscreen mode

请注意,在该handleScroll方法中,我们通过top从窗口的当前偏移量中减去边界客户端矩形的属性值来计算组件的相对 Y 距离。如果不这样做,视差效果的影响将取决于组件的垂直位置。通过使用这种巧妙的校正,我们可以确保offset只要组件的顶部低于视口的顶部,该值就为负值。当组件的顶部超过视口的顶部时,该值offset变为正值。

请注意,目前还没有使用 react-spring ;-)

2. 应用视差效应

现在我们已经获得了组件的相对 Y 坐标,可以开始利用它来创建视差效果了。我们将使用一个简单的弹簧,并使用该useSpring方法定义默认偏移量(为 0)。该方法会返回插值结果和一个更新/设置函数。我们将在方法中使用这个更新/设置函数handleScroll

*我在之前的帖子中更详细地解释了这种方法,如果你想了解更多信息,请点击此链接。useSpring

import React, { useEffect, useRef } from 'react';
import { useSpring } from 'react-spring';

const Comp = () => {
  const ref = useRef();
  const [{ offset }, set] = useSpring(() => ({ offset: 0 }));

  const handleScroll = () => {
    const posY = ref.current.getBoundingClientRect().top;
    const offset = window.pageYOffset - posY;
    set({ offset });
  };

  useEffect(() => {
    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  });

  return (<div ref={ref}>Contents of your component</div>)
}

export default Comp;
Enter fullscreen mode Exit fullscreen mode

现在,我们已经具备了实现视差效果所需的一切。下一步就是开始移动元素了。在这个例子中,我们将使用一些“非正式”的内联样式,你可以使用类似 `div`styled-components或其他任何工具来实现。

import React, { useEffect, useRef } from 'react';
import { animated, useSpring } from 'react-spring';

// You can use this `calc` method to increase the impact
// of the effect by playing around with the values and units.
const calc = o => `translateY(${o * 0.1}px)`;

const Comp = () => {
  const ref = useRef();
  const [{ offset }, set] = useSpring(() => ({ offset: 0 }));

  const handleScroll = () => {
    const posY = ref.current.getBoundingClientRect().top;
    const offset = window.pageYOffset - posY;
    set({ offset });
  };

  useEffect(() => {
    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  });

  return (
    <div style={{
      background: '#123456',
      position: 'relative',
      width: '100vw',
      height: '400px',
      ref={ref}
    }}>
      <animated.div style={{
        background: '#654321',
        position: 'absolute',
        width: '100vw',
        height: '100px',
        transform: offset.interpolate(calc)
      }} />
    </div>
  )
}

export default Comp;
Enter fullscreen mode Exit fullscreen mode

就是这样!正如你所见,只需定义一个animated.div带有样式对象的元素即可。通过react-spring函数对提供的偏移量进行插值,calc我们可以完全控制效果的影响范围。例如,你可以修改该calc函数来操作translateX属性。这样,我们的视差效果就会水平作用。

看看下面这个虽然丑陋但能用的 CodeSandbox 吧。

有任何疑问或反馈吗?

你觉得这个方法有用吗?或者你知道其他更酷炫的实现视差效果的方法吗?我正在考虑如何巧妙地定义不同的景深🤔 如果你有其他想了解的主题,请告诉我!接下来我可能会讲解的主题有:

  • 使用 Jest 设置并编写你的第一个测试
  • 如何使用 Now 设置预发布/生产环境

别忘了在MediumTwitter上关注我

文章来源:https://dev.to/robbertvancaem/creating-a-parallax-effect-using-react-spring-16km