简体   繁体   English

如何使用 IntersectionObserver 使 React 组件在滚动时淡入淡出,但只有一次?

[英]How to make a React component fade in on scroll using IntersectionObserver, but only once?

I am trying to give components a fade-in effect in React when the user scrolls, but I want the fade-in effect to only happen the first time the element moves into the viewport.当用户滚动时,我试图在 React 中为组件提供淡入效果,但我希望淡入效果仅在元素第一次移动到视口时发生。

Currently, the code I am using causes a fade-in every time the element moves into the viewport, so they are constantly fading in and out.目前,每次元素移动到视口时,我使用的代码都会导致淡入,因此它们不断地淡入淡出。

Here is my fade-in component:这是我的淡入组件:

import React, {useState, useRef, useEffect} from 'react';
import './styles/FadeInSection.css';

export default function FadeInSection(props) {
  const [isVisible, setVisible] = useState(true);

  const domRef = React.useRef();

  useEffect(() => {
    const observer = new IntersectionObserver(entries => {
      entries.forEach(entry => setVisible(entry.isIntersecting));
    });

    observer.observe(domRef.current);

    return () => observer.unobserve(domRef.current);
  }, []);

  return (
    <div ref={ domRef } className={ `fade-in-section ${ isVisible ? 'is-visible' : '' }` }>
      { props.children }
    </div>
  )
}

And these are the styles I'm using:这些是我正在使用的样式:

.fade-in-section {
  opacity: 0;
  transform: translateY(20vh);
  isibility: hidden;
  transition: opacity 0.2s ease-out, transform 0.6s ease-out;
  will-change: opacity, visibility;
}

.fade-in-section.is-visible {
  opacity: 1;
  transform: none;
  visibility: visible;
  display: flex; 
}

Here is my website, which keeps fading components in and out, offering a terrible experience:这是我的网站,它不断地淡入淡出组件,提供了糟糕的体验:

我的网站

And this is the desired effect:这是想要的效果:

甜美的淡入效果

How can I achieve the desired effect?我怎样才能达到预期的效果?

Here is a link to the code sandbox to test it: Code sandbox link这是代码沙箱的链接以进行测试: 代码沙箱链接

You only need to call setVisible if entry.isIntersecting is true , so simply replace:您只需要在entry.isIntersectingtrue调用setVisible ,因此只需替换:

setVisible(entry.isIntersecting);

With:和:

entry.isIntersecting && setVisible(true);

This way, once an entry has already been marked as visible, it won't be unmarked, even if you scroll back up, so the element goes out of the viewport, and entry.isIntersecting becomes false again.这样,一旦一个条目已经被标记为可见,即使您向上滚动,它也不会被取消标记,因此该元素离开视口,并且entry.isIntersecting再次变为false

Actually, you can even call observer.unobserve at that point, as you don't care anymore.实际上,此时您甚至可以调用observer.unobserve ,因为您不再关心了。

 const FadeInSection = ({ children, }) => { const domRef = React.useRef(); const [isVisible, setVisible] = React.useState(false); React.useEffect(() => { const observer = new IntersectionObserver(entries => { // In your case there's only one element to observe: if (entries[0].isIntersecting) { // Not possible to set it back to false like this: setVisible(true); // No need to keep observing: observer.unobserve(domRef.current); } }); observer.observe(domRef.current); return () => observer.unobserve(domRef.current); }, []); return (<section ref={ domRef } className={ isVisible ? ' is-visible' : '' }>{ children }</section>); }; const App = () => { const items = [1, 2, 3, 4, 5, 6, 7, 8].map(number => ( <FadeInSection key={ number }>Section { number }</FadeInSection> )); return (<main>{ items }</main>); } ReactDOM.render(<App />, document.querySelector('#app'));
 body { font-family: monospace; margin: 0; } section { padding: 16px; margin: 16px; box-shadow: 0 0 8px rgba(0, 0, 0, .125); height: 64px; opacity: 0; transform: translate(0, 50%); visibility: hidden; transition: opacity 300ms ease-out, transform 300ms ease-out; will-change: opacity, visibility; } .is-visible { opacity: 1; transform: none; visibility: visible; display: flex; }
 <script src="https://unpkg.com/react@16.12.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.development.js"></script> <div id="app"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在反应中使用 IntersectionObserver 更改滚动头的样式 - Change style of header on scroll using IntersectionObserver in react 如何使淡入/淡出仅发生一次 - How to make fade in/out only happen once 如何使用 React 钩子或其他方式(React/Next js)使组件(弹出模式)仅出现一次 - How to make a component (popup modal) appear only once using React hooks or otherwise (React/Next js) 如何使用 IntersectionObserver 使我的框只出现一次? - How can I manage to make my boxes appear only once with IntersectionObserver? 如何使用纯JavaScript在React组件中淡入淡出? - How to fade in a React component using pure JavaScript? 如何仅使用 javascript(无 jquery)使 html 图像在滚动时淡入? - How can I make html images fade in on scroll using only javascript (no jquery)? 如何使用 React Hooks/React Spring 在滚动时淡入元素 - How to fade in element on scroll using React Hooks/React Spring 使用 IntersectionObserver 和 HTML 在 React 中延迟加载组件<template>标签问题?</template> - Lazy loading component in React using IntersectionObserver and HTML <template> tag issue? 如何将 IntersectionObserver 与 React 一起使用? - How to use IntersectionObserver with React? 如何使 API 在 REACT INFINITE 滚动此处的每个页面仅请求一次 - how to make API request only once for each page in REACT INFINITE scroll here
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM