برنامه نویسی

کامپوننت 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.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا