【问题标题】:Is there a way to make nextjs Image have fixed height and responsive width?有没有办法让 nextjs Image 有固定的高度和响应的宽度?
【发布时间】:2022-02-13 04:49:10
【问题描述】:

我想渲染具有固定高度的图像并使其宽度响应。使用普通图像,您只需设置高度,它就会响应

<img src={image} style={{height: 48}} />

我在使用 nextjs Image 组件时遇到了麻烦。我尝试了一些解决方案,例如:

<div>
  <Image
    src={image}
    layout="responsive" - only has responsive height
    height={48}
    width={48}
  />
</div>

<div style={{position: "relative"}}> - wasnt responsive and its position was unpredictable
  <Image
    src={image}
    layout="fill"
    objectFit="contain"
    height={48}
  />
</div>

另一个看起来很有希望的解决方案是这个,但它没有填满宽度。

.company_logo {
  position: relative !important;
  object-fit: contain;
  width: unset !important;
  height: 48px;
}

.company_image {
  width: 100% !important;
}
.company_image div {
  position: unset !important;
}

<Image
  className={styles.company_image}
  src={image}
  alt=""
  layout="fill"
  quality={100}
  priority
/>

我正在使用 js 解决方案,我使用图像和不透明度为 0 的参考,获取图像的尺寸,然后设置为具有动态高度和宽度的基本图像,这应该可以正常工作,但我m 假设有一个更简单的解决方案

const imageRef = useRef(),
      [imageDimensions, setImageDimensions] = useState({ height: 0, width: 0 })

useEffect(() => {
  let height = imageRef.current?.naturalHeight,
      width = imageRef.current?.naturalWidth

  setImageDimensions({ height, width })
}, [])

<img ref={imageRef} src={image} style={{opacity: 0}} />

<Image
  src={image}
  height={imageDimensions.height}
  width={imageDimensions.width}
  quality={100}
  priority
/>

【问题讨论】:

  • 使用&lt;img&gt; 元素有什么问题?如果抽象能让你的生活更轻松,那么它们很好,但不要让它们妨碍你。
  • @jsejcksn 在生产中我只是出于这个原因使用 img 元素。 nextjs 图像将在内容没有跳转的情况下加载,并且具有一些其他属性,例如 placeholder="blur" 从用户体验的角度来看,它们只是更好一点,而无需我编写很多代码。我现在将继续使用 img 元素,但很想知道是否有一个我还没有读过的新解决方案
  • 也许您可以分享更多关于您的用例的信息:光栅图像具有固定数量的像素(在 x 和 y 维度上),因此它们也具有固定的纵横比。当你说你想要“一个固定的高度和一个响应式宽度”时,你能解释一下你的意思吗? (如果高度是固定的,那么宽度也应该是。)
  • @jsejcksn 图片由用户上传,因此它们的尺寸会有所不同。想要的结果是图片高 48px,宽度和他们上传的图片保持相同的比例
  • FWIW,Next 团队似乎对指定高度的纵横比的想法有些敌意:与此相关的问题(12)立即关闭、锁定并转移到维护者没有进一步参与的讨论。

标签: reactjs image next.js


【解决方案1】:

Next 不提供仅声明图像高度尺寸的方法(因此将自动计算宽度)。如果要防止 x 方向上的布局偏移,这是有道理的,因为否则,它将需要 Next 加载每个图像的数据,以便在计算宽度并响应请求用户之前确定其固有尺寸.

如果防止布局转换对您来说很重要,那么您可以自己解决这个问题。

如果你追求这个,你可以通过缓存每张图片的尺寸来优化响应:因为你说你是存储用户上传的图片,你可以在收到时计算每张图片的内在尺寸,然后存储图片数据和它的元数据:ID、维度等(ID策略由你决定,但也许它是图像数据的哈希值。)

然后,当您想加载仅使用指定高度的图像时,您可以检索该图像的尺寸元数据,并使用它根据指定高度计算组件中的固定尺寸(使用纵横比函数)。这应该比预加载每个图像以便在请求时确定其尺寸要快很多


您可以像这样从固有尺寸计算所需尺寸:

TS Playground

type Dimensions = [width: number, height: number];

type DimensionProps = {
  height: number;
  width: number;
};

function getDimensionsFromHeight (
  intrinsicDimensions: Dimensions,
  targetHeight: number,
  roundingStrategy?: 'ceil' | 'floor' | 'round',
): Dimensions {
  const [w, h] = intrinsicDimensions;
  const width = targetHeight * w / h;
  const targetWidth = roundingStrategy ? Math[roundingStrategy](width) : width;
  return [targetWidth, targetHeight];
}

function asProps ([width, height]: Dimensions): DimensionProps {
  return {width, height};
}


// Use:

const {width, height} = asProps(getDimensionsFromHeight([1920, 1080], 48));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-21
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 2016-09-11
    • 1970-01-01
    • 2011-03-13
    相关资源
    最近更新 更多