![](/img/trans.png)
[英]Change style of header on scroll using IntersectionObserver in 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.isIntersecting
為true
調用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.