Adding a <Picture />
component
This commit is contained in:
parent
4ec0b2d9ff
commit
621fb8fcce
3 changed files with 54 additions and 1 deletions
|
@ -4,7 +4,7 @@ import loader from 'virtual:image-loader';
|
|||
import { getImage } from '../src/index.js';
|
||||
import type { ImageAttributes, ImageMetadata, TransformOptions, OutputFormat } from '../src/types.js';
|
||||
|
||||
export interface LocalImageProps extends Omit<TransformOptions, 'src'>, Omit<ImageAttributes, 'src'> {
|
||||
export interface LocalImageProps extends Omit<TransformOptions, 'src'> {
|
||||
src: ImageMetadata | Promise<{ default: ImageMetadata }>;
|
||||
}
|
||||
|
||||
|
@ -23,3 +23,9 @@ const attrs = await getImage(loader, props);
|
|||
---
|
||||
|
||||
<img {...attrs} />
|
||||
|
||||
<style>
|
||||
img {
|
||||
content-visibility: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
46
packages/integrations/image/components/Picture.astro
Normal file
46
packages/integrations/image/components/Picture.astro
Normal file
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
import Image from './Image.astro';
|
||||
// @ts-ignore
|
||||
import loader from 'virtual:image-loader';
|
||||
import { lookup } from 'mrmime';
|
||||
import { getImage } from '../src/index.js';
|
||||
import type { ImageMetadata, OutputFormat } from '../src/types.js';
|
||||
|
||||
export interface Props extends Partial<HTMLPictureElement> {
|
||||
src: ImageMetadata;
|
||||
sizes: HTMLImageElement['sizes'];
|
||||
widths: number[];
|
||||
formats?: OutputFormat[];
|
||||
}
|
||||
|
||||
const { src, sizes, widths, formats = ['avif', 'webp', 'jpeg'] } = Astro.props as Props;
|
||||
|
||||
if (widths.length <= 0) {
|
||||
throw new Error('At least one width must be provided for the <Picture>');
|
||||
}
|
||||
|
||||
const aspectRatio = src.width / src.height;
|
||||
|
||||
async function getSource(format: OutputFormat) {
|
||||
const imgs = await Promise.all(widths.map(async (width) => {
|
||||
const img = await getImage(loader, { src: src.src, format, width, height: Math.round(width / aspectRatio) });
|
||||
return `${img.src} ${width}w`;
|
||||
}))
|
||||
|
||||
return {
|
||||
type: lookup(format) || format,
|
||||
srcset: imgs.join(',')
|
||||
};
|
||||
}
|
||||
|
||||
const sources = await Promise.all(formats.map(format => getSource(format)));
|
||||
|
||||
const width = widths.sort().shift()!;
|
||||
const height = Math.round(width / aspectRatio);
|
||||
---
|
||||
|
||||
<picture>
|
||||
{sources.map(attrs => (
|
||||
<source {...attrs} {sizes}>))}
|
||||
<Image {sizes} {src} {width} {height} />
|
||||
</picture>
|
|
@ -1 +1,2 @@
|
|||
export { default as Image } from './Image.astro';
|
||||
export { default as Picture } from './Picture.astro';
|
||||
|
|
Loading…
Reference in a new issue