You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Next.js中自动获取并设置图片的固有宽高

如何自动获取图片固有宽高以适配Next.js Image组件?

手动给Next.js Image组件填写宽高确实挺烦的,尤其是处理大量远程图片的时候!我整理了几个实用的方案,帮你自动搞定这个问题:

1. 本地静态图片:直接利用Next.js的自动优化(Next.js 11+)

如果你的图片是放在项目public目录下的本地资源,Next.js已经帮你做好了自动读取宽高的支持,完全不用手动填写!示例代码:

import Image from 'next/image'
// 直接导入本地图片文件
import myLocalImage from '../public/photo.jpg'

export default function Home() {
  return (
    <div>
      {/* 不需要手动指定width和height,Next.js会自动从文件中读取固有尺寸 */}
      <Image src={myLocalImage} alt="本地示例图片" />
    </div>
  )
}

2. 远程图片:在构建/服务器端预获取尺寸

对于远程图片(比如Unsplash这类外链图),可以在构建阶段或者服务器渲染时提前获取图片的宽高元数据,再传递给Image组件。

方案A:静态生成页面(getStaticProps)

sharp库读取远程图片的元数据,在构建时完成尺寸获取:
首先安装依赖:

npm install sharp axios

然后在页面中实现:

import Image from 'next/image'
import sharp from 'sharp'
import axios from 'axios'

export async function getStaticProps() {
  const remoteImageUrl = "https://images.unsplash.com/photo-1662572163236-630fd5bcc99d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80"
  
  // 下载图片转为buffer格式
  const response = await axios.get(remoteImageUrl, { responseType: 'arraybuffer' })
  const imageBuffer = Buffer.from(response.data)
  
  // 获取图片的宽高元数据
  const imageMeta = await sharp(imageBuffer).metadata()

  return {
    props: {
      imgUrl: remoteImageUrl,
      imgWidth: imageMeta.width,
      imgHeight: imageMeta.height
    }
  }
}

export default function RemoteImagePage(props) {
  return (
    <div>
      <Image
        layout="intrinsic"
        width={props.imgWidth}
        height={props.imgHeight}
        src={props.imgUrl}
        alt="远程示例图片"
      />
    </div>
  )
}

方案B:服务器渲染页面(getServerSideProps)

如果是需要实时渲染的页面,把上面的尺寸获取逻辑放到getServerSideProps里即可,逻辑完全一致,只是执行时机从构建时变成了每次请求时。

3. 客户端动态获取(适配动态加载场景)

如果图片是客户端动态加载的(比如用户上传的图片、异步获取的图片链接),可以用原生JavaScript的Image对象在客户端获取尺寸:

import Image from 'next/image'
import { useState, useEffect } from 'react'

export default function DynamicImage({ imgSrc }) {
  const [imgDimensions, setImgDimensions] = useState({ width: 0, height: 0 })

  useEffect(() => {
    const img = new window.Image()
    img.src = imgSrc
    // 图片加载完成后获取宽高
    img.onload = () => {
      setImgDimensions({ width: img.width, height: img.height })
    }
  }, [imgSrc])

  // 等待尺寸获取完成前显示加载状态
  if (!imgDimensions.width) return <div className="loading">图片加载中...</div>

  return (
    <Image
      layout="intrinsic"
      width={imgDimensions.width}
      height={imgDimensions.height}
      src={imgSrc}
      alt="动态加载图片"
    />
  )
}

4. 用第三方库简化操作

如果不想自己写逻辑,可以用封装好的第三方库,比如next-image-autosize,它帮你封装了客户端获取尺寸的逻辑:
安装依赖:

npm install next-image-autosize

使用示例:

import AutoImage from 'next-image-autosize'

export default function Home() {
  return (
    <div>
      <AutoImage
        src="https://images.unsplash.com/photo-1662572163236-630fd5bcc99d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80"
        alt="第三方库示例图片"
        layout="intrinsic"
      />
    </div>
  )
}

内容的提问来源于stack exchange,提问作者user19666029

火山引擎 最新活动