کامپوننت CleverImage Astro برای تصاویر پاسخگو من

با کامپوننت CleverImage تصاویر واکنشگرا را در HTML خالص ایجاد کنید. بگذارید به شما نشان دهم که چقدر آسان است. کد کامل نوشته شده در این پست را می توانید در GitHub Gist پیدا کنید: CleverImg.astro.
تصویر واکنش گرا چیست؟
تصاویر واکنش گرا در انواع اندازه ها و وضوح صفحه نمایش به خوبی کار می کنند. می تواند به بهینه سازی عملکرد صفحه کمک کند. به عنوان مثال، شما نیازی به یک تصویر 4k روی صفحه نمایش تلفن همراه ندارید زیرا این فقط یک هدر است.
می توان آن را در HTML خالص انجام داد. برای ایجاد یکی، باید یک را تغییر دهید img
ویژگی های عنصر:
-
srcset
: چندین منبع تصویر و فاکتورهای مقیاس آنها را مشخص کنید (توجه داشته باشید که اگرsizes
تعریف نشده است، سپس مرورگر تصمیم می گیرد که کدام را نمایش دهد، به همین دلیل است که سفارش در اینجا مهم است، مرورگر از اولین تصویر قابل استفاده ای که پیدا می کند استفاده می کند) -
sizes
: مشخص کنید که از کدام منبع تصویر استفاده شودsrcset
در کدام اندازه صفحه نمایش
این دو ویژگی تولید ارزش پیاده سازی خواهد شد.
مثال
در قسمت قبل یک مولد خودکار تصویر ایجاد کردیم، برای تولید تصاویر به آن نگاه کنید، من قصد دارم از یک مثال مرتبط با آن استفاده کنم.
فرض کنید تصویر پایه ما این است cat.png
، اندازه ها و فرمت های مختلفی دارد (طرح نام فایل: [NAME]-[WIDTH]-[HEIGHT].[EXTENSION]
): cat-100-500.png
، cat-100-500.webp
، cat-200-1000.png
، cat-200-1000.webp
. اگر صفحه نمایش کاربر کوچکتر از 768 پیکسل باشد، تصویر کوچکتر باید بارگذاری شود. WebP ترجیح داده می شود.
<img
src="cat-200-1000.png"
alt="a black cat with big green eyes"
srcset="cat-100-500.webp 100w,
cat-100-500.png 100w,
cat-200-1000.webp 200w,
cat-200-1000.png 200w"
sizes="(max-width: 768px) 100px, 200px"
/>
برای توضیحات بیشتر MDN – تصاویر واکنشگرا را بخوانید.
پیاده سازی
برپایی
یک کامپوننت Astro جدید ایجاد کنید، اجازه دهید نام آن را بگذاریم CleverImg.astro
.
چه وسایلی لازم است؟
- پایه ای
img
آرگومان های برچسب:imgPath
(src
)alt
،loading
(اگر بعداً بخواهید بار تنبل را اضافه کنید) -
sizes
چه چیزی به اندازه ها برای تولید می گویدsrcset
-
breakpoints
که در چه چیزی اعلام می کندmaxWidth
منبع اندازه ای که باید در اینجا بارگذاری شود0
maxWidth
اندازه پیش فرض غیر مرتبط با پرس و جو رسانه ای خواهد بود -
withWebp
اگر تصویر(های) موجود در.webp
قالب هم
interface Props {
imgPath: string,
alt: string,
loading?: "eager" | "lazy" | null,
sizes: { width: number; height: number }[],
breakpoints?: {maxWidth: number, imgWidth: number}[]
withWebp?: boolean,
}
const { imgPath, alt, sizes, withWebp, loading, breakpoints } = Astro.props; // init each prop as a const variable
هر دو srcset
و sizes
نیاز به جدا کردن رشته ها با کاما دارد. به همین دلیل است که هر دو به عنوان یک آرایه مدیریت می شوند و پس از آن به هم متصل می شوند.
const generatedSrcset: string[] = [];
const generatedSizes: string[] = [];
اگر قسمت قبلی را دنبال کردید و تصاویر فقط در بیلد تولید میشوند، کد زیر را در if قرار دهید تا فقط در بیلد اجرا شود:
if (import.meta.env.PROD) {
// ...
}
srcset تولید کنید
ابتدا مرتب سازی کنید sizes
. چون نظم مهم است، آنها را به صعود دستور دهید.
sizes.sort((a, b) => a.width - b.width);
اکنون باید رشته ها را به آن اضافه کنیم generatedSrcset
در قالب [IMGPATH] [IMGWIDTH]w
. مسیر با تابعی که در قسمت قبلی این سری نوشته شده بود تولید می شود. این کار باید برای قالب WebP نیز انجام شود.
for (const size of sizes) {
((withWebp ?? true) ? [true, false] : [false]).forEach((isWebp) => { // to do it for webp too
generatedSrcset.push(`${ImageGenerator.generateName(imgPath, size, isWebp)} ${size.width}w`);
});
}
یک اصلاح کوچک وجود دارد که باید انجام شود. اگر وجود دارد breakpoint
، فقط شامل تصاویری می شود که در آن هستند. زیرا breakpoint
به مرورگر می گوید که کدام تصویر و چه زمانی را نمایش دهد، فقط آن تصاویر مورد نیاز است. برای این، بیایید اندازهها را فیلتر کنیم و اندازههایی را که لازم نیست حذف کنیم.
let allBreakpointSizes: number[] | null = null;
if (breakpoints) {
allBreakpointSizes = breakpoints.map(bp => bp.imgWidth);
}
sizes.sort((a, b) => a.width - b.width);
for (const size of sizes) {
if (allBreakpointSizes && allBreakpointSizes.indexOf(size.width) === -1) {continue;} // skip if the curren width is not found in breakpoints
((withWebp ?? true) ? [false, true] : [false]).forEach((isWebp) => {
generatedSrcset.push(`${ImageGenerator.generateName(imgPath, size, isWebp)} ${size.width}w`);
});
}
اندازه ها را تولید کنید
رشته ها را اضافه کنید generatedSizes
که در (max-width: [MAXWIDTH]px) {IMGWIDTH}px
قالب یک استثنا وجود دارد، اگر maxWidth
است 0
سپس به این معنی است که این مقدار پیش فرض است.
if (breakpoints) {
for (const breakpoint of breakpoints) {
if (breakpoint.maxWidth === 0) {
generatedSizes.push(`${breakpoint.imgWidth}px`); // handle default
} else {
generatedSizes.push(`(max-width: ${breakpoint.maxWidth}px) ${breakpoint.imgWidth}px`);
}
}
}
از آن در HTML استفاده کنید
این src
باید بزرگ ترین تصویر باشد. اگر مرورگر شخصی پشتیبانی نمی کند srcset
سپس این مورد استفاده قرار خواهد گرفت. سایر ویژگی ها چیز خاصی نیستند، آرایه های تولید شده باید با کاما به هم متصل شوند.
---
// ...
const biggestSize = sizes.reduce((prev, current) => {
return (prev.width > current.width) ? prev : current;
});
---
<img
src={ImageCompressorIntegration.generateName(imgPath, biggestSize)}
alt={alt}
srcset={generatedSrcset.join(", ")}
sizes={generatedSizes.join(", ")}
loading={loading}
/>
اگر قسمت قبلی را دنبال کردید و تصاویر فقط در بیلد تولید می شوند، آن را کاملاً تولید شده قرار دهید img
در یک شرط، و ساده قرار دهید img
در با import.meta.env.DEV
وضعیت. به پیاده سازی در GitHub Gist نگاه کنید: CleverImg.astro.