我正在使用成帧器运动来创建交错效果,其中 2 个图像从左侧滑入。
如果我处于正确的视口并刷新屏幕,它会完美工作。
但是,如果我向下滚动到元素,如果我缓慢滚动,第一个图像将会动画,而第二个图像将不会动画,直到我进一步向下滚动。
我认为这个错误是因为没有同时在同一个视口中。
如何使用包装容器或其他东西来解决这个问题?
"use client";
import { motion } from "framer-motion";
const variants = {
initial: {
opacity: 0,
transform: 'translateX(-150px)',
// filter: 'blur(5px)'
},
animate: (index: number) => ({
opacity: 1,
transform: 'translateX(0px)',
// filter: 'blur(0px)',
transition: {
duration: 1,
ease: 'easeInOut',
delay: 0.3 * index,
}
})
};
const FramerAnimationSlideIn = ({ items }: any) => {
return (
// @ts-ignore
items.map((item, index) => (
<motion.div
variants={variants}
initial="initial"
whileInView="animate"
key={item.src}
viewport={{
once: true,
}}
custom={index}
>
{item}
</motion.div>
)))
}
export default FramerAnimationSlideIn;
因为每个项目元素上都有
whileInView
属性,所以元素将单独动画,并且仅当元素在视图中时。您是正确的,您需要添加一个包装 div 来用作视口触发器,以便所有 elemet 的动画同时触发。
isInView
钩子,可用于在这种情况下提供帮助。当容器元素在视图中时,我们可以告诉每个元素进行动画处理:
const FramerAnimationSlideIn = ({ items }: { items: Array<any> }) => {
const ref = useRef(null);
const isInView = useInView(ref, { once: true });
return (
<div ref={ref}>
{items.map((item, index) => (
<motion.div
key={index}
variants={variants}
initial="initial"
// Animate when the container is in view
animate={isInView && 'animate'}
custom={index}
>
{item}
</motion.div>
))}
</div>
);
};
您可以使用不同的选项自定义行为,类似于更改运动元素上的
viewport
道具。
这是一个工作示例。