gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 11:27:57 24 4
gpt4 key购买 nike

当用户滚动时,我试图在 React 中为组件提供淡入效果,但我希望淡入效果仅在元素第一次移动到视口(viewport)时发生。

目前,我使用的代码每次元素移动到视口(viewport)时都会导致淡入,因此它们会不断地淡入和淡出。

这是我的淡入组件:

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

这是我的网站,它不断地淡入淡出组件,提供了糟糕的体验:

My Website

这是想要的效果:

Sweet fade-in effect

我怎样才能达到预期的效果?

这是代码沙箱的链接以进行测试: Code sandbox link

最佳答案

您只需调用setVisible如果 entry.isIntersectingtrue ,所以只需替换:

setVisible(entry.isIntersecting);
和:
entry.isIntersecting && setVisible(true);
这样,一旦条目已被标记为可见,即使您向上滚动,它也不会被取消标记,因此元素会离开视口(viewport), 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.disconnect();
}, []);

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>

关于javascript - 如何使用 IntersectionObserver 使 React 组件在滚动时淡入,但只有一次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59595700/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com