簡體   English   中英

如何使用 IntersectionObserver 使 React 組件在滾動時淡入淡出,但只有一次?

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

當用戶滾動時,我試圖在 React 中為組件提供淡入效果,但我希望淡入效果僅在元素第一次移動到視口時發生。

目前,每次元素移動到視口時,我使用的代碼都會導致淡入,因此它們不斷地淡入淡出。

這是我的淡入組件:

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>
  )
}

這些是我正在使用的樣式:

.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; 
}

這是我的網站,它不斷地淡入淡出組件,提供了糟糕的體驗:

我的網站

這是想要的效果:

甜美的淡入效果

我怎樣才能達到預期的效果?

這是代碼沙箱的鏈接以進行測試: 代碼沙箱鏈接

您只需要在entry.isIntersectingtrue調用setVisible ,因此只需替換:

setVisible(entry.isIntersecting);

和:

entry.isIntersecting && setVisible(true);

這樣,一旦一個條目已經被標記為可見,即使您向上滾動,它也不會被取消標記,因此該元素離開視口,並且entry.isIntersecting再次變為false

實際上,此時您甚至可以調用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM