8

我正在使用next/image,效果很好,除了实际加载的图像非常刺耳并且没有动画或淡入淡出。有没有办法做到这一点?我已经尝试了很多东西,但它们都不起作用。

这是我的代码:

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

根据文档,我可以使用该className道具,但这些道具会立即加载,并且在加载后我无法弄清楚应用类的任何方法。

我也试过onLoad了,根据这张票,不支持: https ://github.com/vercel/next.js/issues/20368

4

4 回答 4

2

NextJS 现在支持占位符。您可以使用图像的 base64 字符串填充 blurDataURL 属性,您可以使用getServerSideProps 或 getStaticProps 上的 lib plaiceholder轻松获取。然后为了顺利过渡,您可以添加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,
      },
    },
  };
}

索引.css

img {
  transition: 0.3s;
}
于 2021-09-05T18:30:17.353 回答
1

您可以尝试使用next-placeholder来实现这种效果

于 2021-01-06T04:08:47.733 回答
1

因此,我想实现相同的目标并尝试使用 onLoad 事件。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>
    );
}

但是,图像并不总是淡入,如果图像尚未缓存,onLoad 事件似乎被触发得太早。我怀疑这是一个将在未来的 nextJS 版本中修复的错误。如果其他人找到解决方案,请让我更新!

然而,上面的解决方案经常工作,并且由于每次都会触发 onLoad,它不会破坏任何东西。

编辑:此解决方案对动画使用 framer-motion。这也可以被任何其他动画库或原生 CSS 转换替换

于 2021-02-26T19:06:00.667 回答
0

是的,它可以捕获实际图像加载的事件。我在 Reddit 上找到了对此的答案,并想将其转发给像我这样正在寻找答案的人。

“要让 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)
        }
    }}
/>

从那里你可以使用 imageIsLoaded 布尔值来做一些淡入淡出,比如 Framer Motion 库。

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

于 2021-09-10T09:32:23.577 回答