简体   繁体   中英

How can I add a fade-in animation for Nextjs/Image when it loads?

I'm using next/image , which works great, except the actual image loading in is super jarring and there's no animation or fade in. Is there a way to accomplish this? I've tried a ton of things and none of them work.

Here's my code:

<Image
  src={source}
  alt=""
  layout="responsive"
  width={750}
  height={height}
  className="bg-gray-400"
  loading="eager"
/>

According to the docs I can use the className prop, but those are loaded immediately and I can't figure out any way to apply a class after it's loaded.

I also tried onLoad , and according to this ticket, it isn't supported: https://github.com/vercel/next.js/issues/20368

You could try use next-placeholder to achieve this sort of effect

I wanted to achieve the same thing and tried to use the onLoad event, therefore. The Image component of nextJs accepts this as prop, so this was my result:

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

However, the Image does not always fade-in, the onLoad event seems to be triggered too early if the image is not cached already. I suspect this is a bug that will be fixed in future nextJS releases. If someone else finds a solution, please keep me updated!

The solution above however works often, and since onLoad gets triggered every time, it does not break anything.

Edit: This solution uses framer-motion for the animation. This could also be replaced by any other animation library or native CSS transitions

NextJS now supports placeholder . You can fill the blurDataURL property with the base64 string of the image which you can easily get using the lib plaiceholder on getServerSideProps or getStaticProps. Then to make the transition smoothly you can add transition: 0.3s;

Quick sample:

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

Yes, its possible to capture the event where the actual image loads. I found an answer to this on Reddit and wanted to repost it here for others like me searching for an anwser.

"To get onLoad to work in the NextJS image component you need make sure it's not the 1x1 px they use as placeholder that is the target.

 const [imageIsLoaded, setImageIsLoaded] = useState(false) <Image width={100} height={100} src={'some/src.jpg'} onLoad={event => { const target = event.target; // next/image use an 1x1 px git as placeholder. We only want the onLoad event on the actual image if (target.src.indexOf('data:image/gif;base64') < 0) { setImageIsLoaded(true) } }} />

From there you can just use the imageIsLoaded boolean to do some fadein with something like the Framer Motion library.

Source: https://www.reddit.com/r/nextjs/comments/lwx0j0/fade_in_when_loading_nextimage/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM