fix(assets): Don't include asked width in srcset request
This commit is contained in:
parent
fc86fdf0c3
commit
bfe8e09ba6
4 changed files with 24 additions and 18 deletions
|
@ -6,7 +6,9 @@ Add support for generating multiple widths when using the Image component and a
|
|||
|
||||
## `srcset` support
|
||||
|
||||
The current usage is as follow:
|
||||
Two new properties have been added to `Image` and `getImage`: `densities` and `widths`.
|
||||
|
||||
These props can be used to generate a `srcset` attribute with multiple sources. For example:
|
||||
|
||||
```astro
|
||||
---
|
||||
|
@ -14,17 +16,13 @@ import { Image } from "astro";
|
|||
import myImage from "./my-image.jpg";
|
||||
---
|
||||
|
||||
<Image src={myImage} densities={[2, 3]} alt="My cool image" />
|
||||
<Image src={myImage} width={myImage.width / 2} densities={[2]} alt="My cool image" />
|
||||
```
|
||||
|
||||
Alternatively to `densities`, `widths` can be used for specific widths. In both cases, according images and the following code will be generated:
|
||||
|
||||
```html
|
||||
<img src="..." srcset="... 2x, ... 3x" alt="My cool image" />
|
||||
```
|
||||
|
||||
(if `widths` is used the descriptor will be `w` instead of `x`)
|
||||
|
||||
## Picture component
|
||||
|
||||
The `Picture` component can be used to generate a `<picture>` element with multiple sources. It can be used as follow:
|
||||
|
@ -35,7 +33,7 @@ import { Picture } from "astro:assets";
|
|||
import myImage from "./my-image.jpg";
|
||||
---
|
||||
|
||||
<Picture src={myImage} formats=["avif", "webp"] alt="My super image in multiple formats!" />
|
||||
<Picture src={myImage} formats={["avif", "webp"]} alt="My super image in multiple formats!" />
|
||||
```
|
||||
|
||||
The above code will generate the following:
|
||||
|
@ -48,4 +46,4 @@ The above code will generate the following:
|
|||
</picture>
|
||||
```
|
||||
|
||||
The `Picture` component takes all the same props as the `Image` component, including `densities` and `widths`.
|
||||
The `Picture` component takes all the same props as the `Image` component, including the new `densities` and `widths` properties.
|
||||
|
|
|
@ -45,7 +45,10 @@ interface SharedServiceProps<T extends Record<string, any> = Record<string, any>
|
|||
*/
|
||||
getURL: (options: ImageTransform, imageConfig: ImageConfig<T>) => string | Promise<string>;
|
||||
/**
|
||||
* TODO: Document
|
||||
* Generate additional `srcset` values for the image.
|
||||
*
|
||||
* While in most cases this is exclusively used for `srcset`, it can also be used in a more generic way to generate
|
||||
* multiple variants of the same image. For instance, you can use this to generate multiple aspect ratios or multiple formats.
|
||||
*/
|
||||
getSrcSet?: (
|
||||
options: ImageTransform,
|
||||
|
@ -226,8 +229,9 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
|
|||
|
||||
const aspectRatio = targetWidth / targetHeight;
|
||||
const imageWidth = isESMImportedImage(options.src) ? options.src.width : options.width;
|
||||
const maxWidth = options.width ?? imageWidth ?? Infinity;
|
||||
const maxWidth = imageWidth ?? Infinity;
|
||||
|
||||
// REFACTOR: Could we merge these two blocks?
|
||||
if (densities) {
|
||||
const densityValues = densities.map((density) => {
|
||||
if (typeof density === 'number') {
|
||||
|
@ -244,9 +248,12 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
|
|||
densityWidths.forEach((width, index) => {
|
||||
const maxTargetWidth = Math.min(width, maxWidth);
|
||||
|
||||
// If the user passed dimensions, we don't want to add it to the srcset
|
||||
const { width: transformWidth, height: transformHeight, ...rest } = options;
|
||||
|
||||
const srcSetValue = {
|
||||
transform: {
|
||||
...options,
|
||||
...rest,
|
||||
},
|
||||
descriptor: `${densityValues[index]}x`,
|
||||
attributes: {
|
||||
|
@ -254,7 +261,7 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
|
|||
},
|
||||
};
|
||||
|
||||
// Only set width and height if they are different from the original image
|
||||
// Only set width and height if they are different from the original image, to avoid duplicated final images
|
||||
if (maxTargetWidth !== imageWidth) {
|
||||
srcSetValue.transform.width = maxTargetWidth;
|
||||
srcSetValue.transform.height = Math.round(maxTargetWidth / aspectRatio);
|
||||
|
@ -270,9 +277,11 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
|
|||
widths.forEach((width) => {
|
||||
const maxTargetWidth = Math.min(width, maxWidth);
|
||||
|
||||
const { width: transformWidth, height: transformHeight, ...rest } = options;
|
||||
|
||||
const srcSetValue = {
|
||||
transform: {
|
||||
...options,
|
||||
...rest,
|
||||
},
|
||||
descriptor: `${width}w`,
|
||||
attributes: {
|
||||
|
@ -280,7 +289,6 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
|
|||
},
|
||||
};
|
||||
|
||||
// Only set width and height if they are different from the original image
|
||||
if (maxTargetWidth !== imageWidth) {
|
||||
srcSetValue.transform.width = maxTargetWidth;
|
||||
srcSetValue.transform.height = Math.round(maxTargetWidth / aspectRatio);
|
||||
|
|
|
@ -50,9 +50,9 @@ const sharpService: LocalImageService = {
|
|||
|
||||
// Never resize using both width and height at the same time, prioritizing width.
|
||||
if (transform.height && !transform.width) {
|
||||
result.resize({ height: transform.height });
|
||||
result.resize({ height: Math.round(transform.height) });
|
||||
} else if (transform.width) {
|
||||
result.resize({ width: transform.width });
|
||||
result.resize({ width: Math.round(transform.width) });
|
||||
}
|
||||
|
||||
if (transform.format) {
|
||||
|
|
|
@ -77,12 +77,12 @@ const service: LocalImageService = {
|
|||
if (transform.height && !transform.width) {
|
||||
operations.push({
|
||||
type: 'resize',
|
||||
height: transform.height,
|
||||
height: Math.round(transform.height),
|
||||
});
|
||||
} else if (transform.width) {
|
||||
operations.push({
|
||||
type: 'resize',
|
||||
width: transform.width,
|
||||
width: Math.round(transform.width),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue