【问题标题】:How can I add a fade-in animation for Nextjs/Image when it loads?加载时如何为 Nextjs/Image 添加淡入动画?
【发布时间】:2021-04-09 06:41:42
【问题描述】:

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

这是我的代码:

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

根据docs,我可以使用className 属性,但它们会立即加载,我无法弄清楚加载后应用类的任何方法。

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

【问题讨论】:

    标签: reactjs next.js nextjs-image


    【解决方案1】:

    你可以尝试使用next-placeholder来达到这种效果

    【讨论】:

    • 不知道为什么。我不认为它消失了?
    【解决方案2】:

    因此,我想实现相同的目标并尝试使用 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 过渡替换

    【讨论】:

    【解决方案3】:

    NextJS 现在支持placeholder。您可以使用图像的 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,
          },
        },
      };
    }
    

    index.css

    img {
      transition: 0.3s;
    }
    

    【讨论】:

      【解决方案4】:

      是的,它可以捕获实际图像加载的事件。我在 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/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-26
        • 1970-01-01
        相关资源
        最近更新 更多