![](/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.