کامپوننت 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منبع اندازه ای که باید در اینجا بارگذاری شود0maxWidthاندازه پیش فرض غیر مرتبط با پرس و جو رسانه ای خواهد بود -
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.



