简体   繁体   English

如何在加载时为 Nextjs/Image 添加淡入 animation?

[英]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?我正在使用next/image ,效果很好,除了实际加载的图像非常刺耳,并且没有 animation 或淡入。有没有办法做到这一点? 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.根据文档,我可以使用className道具,但是这些道具会立即加载,并且在加载 class 后,我想不出任何方法来应用它。

I also tried onLoad , and according to this ticket, it isn't supported: https://github.com/vercel/next.js/issues/20368我也试过onLoad ,根据这张票,它不受支持: 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.因此,我想实现相同的目标并尝试使用 onLoad 事件。 The Image component of nextJs accepts this as prop, so this was my result: nextJs 的 Image 组件接受这个作为道具,所以这是我的结果:

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.但是,图像并不总是淡入,如果图像尚未缓存,onLoad 事件似乎被触发得太早了。 I suspect this is a bug that will be fixed in future nextJS releases.我怀疑这是一个将在未来的 nextJS 版本中修复的错误。 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.然而,上面的解决方案经常工作,并且由于每次都会触发 onLoad,它不会破坏任何东西。

Edit: This solution uses framer-motion for the animation.编辑:此解决方案对 animation 使用成帧器运动。 This could also be replaced by any other animation library or native CSS transitions这也可以被任何其他 animation 库或本机 CSS 转换替换

NextJS now supports placeholder . NextJS 现在支持占位符 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.您可以使用图像的 base64 字符串填充 blurDataURL 属性,您可以使用 getServerSideProps 或 getStaticProps 上的 lib plaiceholder轻松获取该字符串。 Then to make the transition smoothly you can add transition: 0.3s;然后为了使过渡平滑,您可以添加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索引.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.我在 Reddit 上找到了对此的答案,并想将其转发给像我这样正在寻找答案的人。

"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. “要让 onLoad 在 NextJS 图像组件中工作,您需要确保目标不是他们用作占位符的 1x1 像素。

 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.从那里你可以使用 imageIsLoaded boolean 来做一些像 Framer Motion 库这样的淡入淡出。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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