React,在你向下滚动时为单个照片设置动画,使用帧器运动和交叉点观察者



我正在尝试使用交集观察器来跟踪项目是否在视图中,以及动画的帧器运动。当你向下滚动到特定的照片时,我试图让每一张照片都被动画化。相反,当你看到第一张照片时,整个容器和所有照片(点击时是博客文章(都会被动画化为一个视图。

如果我在map((中传递ref,在BlogCardContainer中我会得到同样的效果,但它只在我到达最后一篇文章时进行动画处理,在最后一篇帖子上方,照片会离开屏幕。

所以我相信问题是我在听带ref的图库容器,所以当我在滚动时,它会把所有的东西都带进去,但如果我听每张卡,它只听最后一张,然后把所有的都带进去。如果有人知道如何解决或绕过它,我将感谢任何反馈。

useEffect、来自交叉点观察器的useInView和来自帧器运动挂钩的动画低于

const { ref, inView } = useInView({
threshold: 0.05
});
const animation = useAnimation();
useEffect(() => {
if(inView) {
animation.start({
x: 0,
transition: {
type: 'spring', duration: 1, bounce: 0.5
}
});
}
if(!inView) {
animation.start({ x: '-100vw' })
}
}, [inView]);

这是退货声明

return (
<>
{isLoading ? (
<LoaderContainer>
<RingLoader />
</LoaderContainer>
) : (
<GalleryContainer ref={ref}>
{allPostsData &&
allPostsData.map((post, index) => (
<BlogCardsContainer key={post.slug.current}>
<motion.div animate={animation} >
<BlogLink to={"/" + post.slug.current}>
<BlogCards src={urlFor(post.mainImage.asset.url).url()} alt={post.title} />
<BlogCardTitle>{post.title}</BlogCardTitle>
</BlogLink>
</motion.div>
</BlogCardsContainer>

))}
</GalleryContainer>
)}

</>
);

我认为您可以在不使用Intersection Observer API的情况下实现您想要的目标。Framer Motion提供滚动动画(https://www.framer.com/docs/scroll-animations/),因此您可能需要查看"滚动触发器"部分。

无论如何,对我来说,诀窍是创建一个单独的组件,并包括motion.div和那里的逻辑。然后,您可以将传递必要道具的数组映射到该组件。你甚至不需要useRef或useEffect!

类似这样的东西:

return (
<>
{isLoading ? (
<LoaderContainer>
<RingLoader />
</LoaderContainer>
) : (
<GalleryContainer>
{allPostsData &&
allPostsData.map((post, index) => (
<MyAnimatedComponent post={post} />
))}
</GalleryContainer>
)}
</>
);

然后在组件中:

import { motion } from "framer-motion";
export const MyAnimatedComponent = (props) => {
const { post } = props;
return (
<BlogCardsContainer key={post.slug.current}>
<motion.div
initial={{ x: 0 }}
whileInView={{ x: -100 }}
viewport={{ once: true }}
transition={{ type: "spring", bounce: 0.5, duration: 1 }}
>
<BlogLink to={"/" + post.slug.current}>
<BlogCards
src={urlFor(post.mainImage.asset.url).url()}
alt={post.title}
/>
<BlogCardTitle>{post.title}</BlogCardTitle>
</BlogLink>
</motion.div>
</BlogCardsContainer>
);
};

最新更新