Как я могу добавить плавную анимацию для Nextjs/Image при загрузке?
я использую
next/image
, который отлично работает, за исключением того, что фактическая загрузка изображения очень резкая, и нет никакой анимации или постепенного появления. Есть ли способ добиться этого? Я перепробовал кучу вещей, но ни один из них не работал.
Вот мой код:
<Image
src={source}
alt=""
layout="responsive"
width={750}
height={height}
className="bg-gray-400"
loading="eager"
/>
Согласно документам я могу использовать
className
prop, но они загружаются немедленно, и я не могу понять, как применить класс после его загрузки.
Я тоже пробовал
onLoad
, и согласно этому билету он не поддерживается: https://github.com/vercel/next.js/issues/20368
4 ответа
NextJS теперь поддерживает заполнитель . Вы можете заполнить свойство blurDataURL строкой изображения base64, которую вы можете легко получить с помощью lib plaiceholder в getServerSideProps или getStaticProps. Затем, чтобы сделать переход плавным, вы можете добавить
transition: 0.3s;
Быстрый образец:
export const UserInfo: React.FC<TUserInfo> = ({ profile }) => {
return (
<div className="w-24 h-24 rounded-full overflow-hidden">
<Image
src={profile.image}
placeholder="blur"
blurDataURL={profile.blurDataURL}
width="100%"
height="100%"
/>
</div>
);
};
export async function getServerSideProps(props: any) {
const { username } = props.query;
const userProfileByName = `${BASE_URL}/account/user_profile_by_user_name?user_name=${username}`;
const profileResponse = await (await fetch(userProfileByName)).json();
const profile = profileResponse?.result?.data[0];
const { base64 } = await getPlaiceholder(profile.profile_image);
return {
props: {
profile: {
...profile,
blurDataURL: base64,
},
},
};
}
index.css
img {
transition: 0.3s;
}
Я хотел добиться того же и поэтому попытался использовать событие onLoad. Компонент Image в nextJs принимает это как опору, так что это был мой результат:
const animationVariants = {
visible: { opacity: 1 },
hidden: { opacity: 0 },
}
const FadeInImage = props => {
const [loaded, setLoaded] = useState(false);
const animationControls = useAnimation();
useEffect(
() => {
if(loaded){
animationControls.start("visible");
}
},
[loaded]
);
return(
<motion.div
initial={"hidden"}
animate={animationControls}
variants={animationVariants}
transition={{ ease: "easeOut", duration: 1 }}
>
<Image
{...p}
onLoad={() => setLoaded(true)}
/>
</motion.div>
);
}
Однако изображение не всегда исчезает, событие onLoad запускается слишком рано, если изображение еще не кэшировано. Я подозреваю, что это ошибка, которая будет исправлена в будущих выпусках nextJS. Если кто-то другой найдет решение, держите меня в курсе!
Однако вышеприведенное решение работает часто, и поскольку onLoad запускается каждый раз, он ничего не ломает.
Изменить: в этом решении для анимации используется кадровое движение. Его также можно заменить любой другой библиотекой анимации или собственными переходами CSS.
Вы можете попробовать использовать следующий заполнитель, чтобы добиться такого эффекта.
Да, возможно зафиксировать событие, при котором загружается фактическое изображение. Я нашел ответ на этот вопрос на Reddit и хотел опубликовать его здесь для других, таких как я, ищущих ответ.
"Чтобы onLoad работал с компонентом изображения NextJS, вам нужно убедиться, что целью является не тот 1x1 пиксель, который они используют в качестве заполнителя.
Оттуда вы можете просто использовать логическое значение imageIsLoaded для некоторого затухания с чем-то вроде библиотеки Framer Motion.
Источник: https://www.reddit.com/r/nextjs/comments/lwx0j0/fade_in_when_loading_nextimage/