如何在内容滚动到视图时淡入

2025-05-26

如何在内容滚动到视图时淡入

今天,我想向您展示一种以美观而巧妙的方式显示内容的技术 - 通过在内容出现时淡入来显示内容!

时尚滑动部分🎚

让我们从指定所需的 CSS 开始。我们创建两个类 - 一个fade-in-section基类和一个is-visible修饰类。当然,您可以随意命名它们。

fade-in-section应该隐藏我们的组件,而is-visible类应该显示它。我们将使用 CSS 过渡效果在它们之间进行转换。

代码如下:

.fade-in-section {
  opacity: 0;
  transform: translateY(20vh);
  visibility: hidden;
  transition: opacity 0.6s ease-out, transform 1.2s ease-out;
  will-change: opacity, visibility;
}
.fade-in-section.is-visible {
  opacity: 1;
  transform: none;
  visibility: visible;
}
Enter fullscreen mode Exit fullscreen mode

这里,我们使用该transform属性将容器初始向下移动视口的 1/5(或 20 个视口高度单位)。我们还指定初始不透明度为 0。

通过转换这两个属性,我们将获得想要的效果。我们还将visibility属性从hidden转换为visible

实际效果如下:

看起来很酷吧?现在,如果我们在视口中滚动新的内容块时都能实现这种效果,那该有多酷?

炫耀的部分👋

如果在内容可见时触发事件,岂不是很棒?我们将使用IntersectionObserverDOM API 来实现该行为。

IntersectionObserverAPI 是一个非常强大的工具,可以追踪屏幕上某些内容是否部分或全部显示。如果您想深入了解,我建议您阅读这篇MDN 文章

简单概括一下,交叉观察器接受一个 DOM 节点,并在其进入​​(或退出)视口时调用一个回调函数。它会返回一些位置数据,以及一些有用的属性isIntersecting,例如 ,用于告诉我们某个元素是否可见。

不过,本文不会深入探讨交叉观察器的其他实用功能,我们只是实现了一个很棒的“进入时淡入”功能。由于我们使用了 React,我们可以编写一个很棒的可复用组件,并在整个应用程序中重复使用。

以下是实现我们组件的代码:

function FadeInSection(props) {
  const [isVisible, setVisible] = React.useState(true);
  const domRef = React.useRef();
  React.useEffect(() => {
    const observer = new IntersectionObserver(entries => {
      entries.forEach(entry => setVisible(entry.isIntersecting));
    });
    observer.observe(domRef.current);
    return () => observer.unobserve(domRef.current);
  }, []);
  return (
    <div
      className={`fade-in-section ${isVisible ? 'is-visible' : ''}`}
      ref={domRef}
    >
      {props.children}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

下面是实现它的沙盒:

如果您正在寻找复制和粘贴解决方案 - 那就来这里吧。

正在发生的事情——一步一步

如果您想了解发生了什么,我在下面写了一步一步的指南,解释了发生了什么。

首先,我们调用三个内置的 React Hooks - useStateuseRef和。您可以在文档useEffect中阅读有关每个 Hooks 的更多信息,但在我们的代码中,我们执行以下操作:

  1. 创建一个状态变量,指示该部分是否可见useState。我们将其默认为false
  2. 使用以下方式创建对 DOM 节点的引用useRef
  3. 创建交叉口观察器并开始观察useEffect

交叉路口观察器的设置可能看起来有点陌生,但一旦你了解了发生了什么,它就非常简单。

首先,我们创建一个 IntersectionObserver 类的新实例。我们传入一个回调函数,每当注册到此观察器的任何 DOM 元素的“状态”发生改变时(例如,滚动、缩放或屏幕上出现新内容时),都会调用该函数。然后,我们用 告诉观察器实例观察我们的 DOM 节点observer.observe(domRef.current)

不过,在完成之前,我们需要稍微清理一下——每次卸载 DOM 节点时,都需要移除它的交集监听器!幸运的是,我们可以从 中返回一个清理函数useEffect,它会帮我们完成这项工作。

这就是我们在实现结束时所做的useEffect——返回一个调用unobserve观察者方法的函数。(感谢Sung Kim在评论区指出这一点!)

我们传递给观察者的回调函数会使用一个条目对象列表进行调用——每次调用该observer.observe方法时都会返回一个条目对象。由于我们只调用一次,因此可以假设该列表永远只包含一个元素。

isVisible我们通过调用其设置器(函数)来更新状态变量setVisible,并将 的值赋给entry.isIntersecting。我们可以进一步优化,只调用一次,这样就不会再次隐藏我们已经看到的内容。

我们通过将 DOM 引用附加到实际 DOM 来完成我们的代码 - 通过将其作为refprop 传递给我们<div />

然后我们可以像这样使用我们的新组件:

<FadeInSection>
  <h1>This will fade in</h1>
</FadeInSection>

<FadeInSection>
  <p>This will fade in too!</p>
</FadeInSection>

<FadeInSection>
  <img src="yoda.png" alt="fade in, this will" />
</FadeInSection>
Enter fullscreen mode Exit fullscreen mode

这就是当您滚动到视图时使内容淡入的方式!

我很想看看您如何以不同的方式实现相同的效果 - 或者是否有任何方法可以优化我编写的代码 - 在评论中。

感谢阅读!

关于可访问性的最后一点

虽然动画看起来很酷,但有些人却不太习惯。对他们来说,动画会损害用户体验。幸运的是,你可以为这些用户实现一个特殊的媒体查询 - 即。你可以(也应该!)在这篇关于此主题的CSS Tricks 文章prefers-reduced-motion中阅读更多相关信息。

文章来源:https://dev.to/selbekk/how-to-fade-in-content-as-it-scrolls-into-view-10j4
PREV
2020 年如何开始使用 React
NEXT
成为 Java 尤达大师需要学习什么