CSS Paint API

امکانات جدید در کروم 65

CSS Paint API (همچنین به‌عنوان «CSS Custom Paint» یا «Houdini's paint Worklet» نیز شناخته می‌شود) به‌طور پیش‌فرض با شروع Chrome 65 فعال است. چیست؟ چه کاری می توانید با آن انجام دهید؟ و چگونه کار می کند؟ خوب، ادامه دهید، آیا…

CSS Paint API به شما این امکان را می دهد که هر زمان که یک ویژگی CSS انتظار یک تصویر را داشت، به صورت برنامه نویسی یک تصویر تولید کنید. ویژگی هایی مانند background-image یا border-image معمولاً با url() برای بارگذاری یک فایل تصویر یا با توابع داخلی CSS مانند linear-gradient() استفاده می شود. به جای استفاده از آن‌ها، اکنون می‌توانید از paint(myPainter) برای ارجاع به یک Worklet رنگ استفاده کنید.

نوشتن کارنامه رنگ

برای تعریف یک Worklet paint به نام myPainter ، باید یک فایل Worklet paint CSS را با استفاده از CSS.paintWorklet.addModule('my-paint-worklet.js') بارگذاری کنیم. در آن فایل، می‌توانیم از تابع registerPaint برای ثبت کلاس Worklet paint استفاده کنیم:

class MyPainter {
  paint(ctx, geometry, properties) {
    // ...
  }
}

registerPaint('myPainter', MyPainter);

در داخل callback paint() ، می‌توانیم از ctx به همان روشی که از CanvasRenderingContext2D استفاده می‌کنیم، همانطور که از <canvas> می‌شناسیم استفاده کنیم. اگر می‌دانید چگونه در یک <canvas> طراحی کنید، می‌توانید در یک صفحه رنگ نقاشی بکشید! geometry عرض و ارتفاع بوم را که در اختیار ماست به ما می گوید. properties در ادامه این مقاله توضیح خواهم داد.

به عنوان یک مثال مقدماتی، بیایید یک Worklet paint شطرنجی بنویسیم و از آن به عنوان تصویر پس‌زمینه یک <textarea> استفاده کنیم. (من از یک textarea استفاده می کنم زیرا به طور پیش فرض قابل تغییر اندازه است.):

<!-- index.html -->
<!doctype html>
<style>
  textarea {
    background-image: paint(checkerboard);
  }
</style>
<textarea></textarea>
<script>
  CSS.paintWorklet.addModule('checkerboard.js');
</script>
// checkerboard.js
class CheckerboardPainter {
  paint(ctx, geom, properties) {
    // Use `ctx` as if it was a normal canvas
    const colors = ['red', 'green', 'blue'];
    const size = 32;
    for(let y = 0; y < geom.height/size; y++) {
      for(let x = 0; x < geom.width/size; x++) {
        const color = colors[(x + y) % colors.length];
        ctx.beginPath();
        ctx.fillStyle = color;
        ctx.rect(x * size, y * size, size, size);
        ctx.fill();
      }
    }
  }
}

// Register our class under a specific name
registerPaint('checkerboard', CheckerboardPainter);

اگر در گذشته از <canvas> استفاده کرده اید، این کد باید آشنا به نظر برسد. دمو زنده را اینجا ببینید.

Textarea با الگوی شطرنجی به عنوان تصویر پس زمینه
Textarea با الگوی شطرنجی به عنوان تصویر پس زمینه.

تفاوت با استفاده از یک تصویر پس‌زمینه رایج در اینجا این است که هر زمان که کاربر اندازه ناحیه متنی را تغییر دهد، الگو در صورت تقاضا دوباره ترسیم می‌شود. این بدان معناست که تصویر پس‌زمینه همیشه دقیقاً به اندازه‌ای است که باید باشد، از جمله جبران نمایشگرهای با چگالی بالا.

این بسیار جالب است، اما همچنین کاملا ثابت است. آیا می‌خواهیم هر بار که الگوی مشابهی را می‌خواهیم اما با مربع‌هایی با اندازه‌های متفاوت، یک Worklet جدید بنویسیم؟ پاسخ منفی است!

پارامترهای کاری خود را

خوشبختانه، Worklet paint می‌تواند به سایر ویژگی‌های CSS دسترسی داشته باشد، جایی که properties پارامتر اضافی وارد عمل می‌شوند. با دادن ویژگی استاتیک inputProperties به کلاس، می توانید در تغییرات هر ویژگی CSS، از جمله ویژگی های سفارشی، مشترک شوید. مقادیر از طریق پارامتر properties به شما داده می شود.

<!-- index.html -->
<!doctype html>
<style>
  textarea {
    /* The paint worklet subscribes to changes of these custom properties. */
    --checkerboard-spacing: 10;
    --checkerboard-size: 32;
    background-image: paint(checkerboard);
  }
</style>
<textarea></textarea>
<script>
  CSS.paintWorklet.addModule('checkerboard.js');
</script>
// checkerboard.js
class CheckerboardPainter {
  // inputProperties returns a list of CSS properties that this paint function gets access to
  static get inputProperties() { return ['--checkerboard-spacing', '--checkerboard-size']; }

  paint(ctx, geom, properties) {
    // Paint worklet uses CSS Typed OM to model the input values.
    // As of now, they are mostly wrappers around strings,
    // but will be augmented to hold more accessible data over time.
    const size = parseInt(properties.get('--checkerboard-size').toString());
    const spacing = parseInt(properties.get('--checkerboard-spacing').toString());
    const colors = ['red', 'green', 'blue'];
    for(let y = 0; y < geom.height/size; y++) {
      for(let x = 0; x < geom.width/size; x++) {
        ctx.fillStyle = colors[(x + y) % colors.length];
        ctx.beginPath();
        ctx.rect(x*(size + spacing), y*(size + spacing), size, size);
        ctx.fill();
      }
    }
  }
}

registerPaint('checkerboard', CheckerboardPainter);

اکنون می‌توانیم از کد یکسانی برای انواع مختلف شطرنج‌ها استفاده کنیم. اما حتی بهتر از آن، اکنون می‌توانیم به DevTools برویم و با مقادیر کمانچه بپردازیم تا زمانی که ظاهر مناسب را پیدا کنیم.

مرورگرهایی که از paint worklet پشتیبانی نمی کنند

در زمان نگارش این مقاله، فقط Chrome Worklet رنگ را پیاده‌سازی کرده است. در حالی که سیگنال‌های مثبتی از سایر فروشندگان مرورگر وجود دارد، پیشرفت چندانی وجود ندارد. برای به روز ماندن، بررسی کنید آیا هودینی هنوز آماده است؟ به طور منظم در عین حال، مطمئن شوید که از بهبود پیشرونده استفاده کنید تا کد خود را در حال اجرا نگه دارید، حتی اگر هیچ پشتیبانی از Worklet رنگ وجود نداشته باشد. برای اطمینان از اینکه کارها همانطور که انتظار می رود کار می کنند، باید کد خود را در دو مکان تنظیم کنید: CSS و JS.

تشخیص پشتیبانی از Worklet paint در JS می تواند با بررسی شی CSS انجام شود: js if ('paintWorklet' in CSS) { CSS.paintWorklet.addModule('mystuff.js'); } برای سمت CSS، دو گزینه دارید. می توانید از @supports استفاده کنید:

@supports (background: paint(id)) {
  /* ... */
}

یک ترفند فشرده تر، استفاده از این واقعیت است که CSS در صورت وجود یک تابع ناشناخته، کل یک اعلان ویژگی را باطل می کند و متعاقباً نادیده می گیرد. اگر یک ویژگی را دو بار مشخص کنید - ابتدا بدون رنگ و سپس با رنگ کار - بهبود تدریجی دریافت خواهید کرد:

textarea {
  background-image: linear-gradient(0, red, blue);
  background-image: paint(myGradient, red, blue);
}

در مرورگرهایی که از Worklet paint پشتیبانی می‌کنند، دومین اعلان background-image مورد اول را بازنویسی می‌کند. در مرورگرهایی که از paint worklet پشتیبانی نمی‌کنند ، اعلان دوم نامعتبر است و کنار گذاشته می‌شود و اعلان اول به اجرا در می‌آید.

CSS Paint Polyfill

برای بسیاری از کاربردها، می توان از CSS Paint Polyfill نیز استفاده کرد که پشتیبانی از CSS Custom Paint و Paint Worklets را به مرورگرهای مدرن اضافه می کند.

موارد استفاده کنید

موارد استفاده زیادی برای کارگاه رنگ وجود دارد که برخی از آنها واضح تر از بقیه هستند. یکی از بارزترین موارد استفاده از رنگ کاری برای کاهش اندازه DOM است. اغلب، عناصر صرفا برای ایجاد تزئینات با استفاده از CSS اضافه می شوند. برای مثال، در Material Design Lite، دکمه با افکت ریپل حاوی 2 عنصر <span> اضافی برای پیاده سازی خود ریپل است. اگر تعداد زیادی دکمه دارید، این می‌تواند به تعداد زیادی از عناصر DOM اضافه شود و منجر به کاهش عملکرد در تلفن همراه شود. اگر به جای آن افکت ریپل را با استفاده از Worklet رنگ اجرا کنید ، در نهایت با 0 عنصر اضافی و فقط یک Worklet رنگ مواجه خواهید شد. علاوه بر این، شما چیزی دارید که سفارشی کردن و پارامترسازی آن بسیار ساده تر است.

مزیت دیگر استفاده از رنگ ورکلت این است که - در اکثر سناریوها - راه حلی که از ورکلت رنگ استفاده می کند از نظر بایت کوچک است. البته، یک معامله وجود دارد: هر زمان که اندازه بوم یا هر یک از پارامترها تغییر کند، کد رنگ شما اجرا می شود. بنابراین اگر کد شما پیچیده باشد و طولانی باشد، ممکن است jank را معرفی کند. کروم در حال کار بر روی جابجایی ورکلت‌های رنگ از رشته اصلی است، به‌گونه‌ای که حتی ورکلت‌های رنگ طولانی‌مدت نیز بر روی پاسخ‌دهی رشته اصلی تأثیری نمی‌گذارند.

به نظر من، هیجان‌انگیزترین چشم‌انداز این است که Worklet paint امکان پرکردن کارآمد ویژگی‌های CSS را می‌دهد که مرورگر هنوز از آن برخوردار نیست. یکی از مثال‌ها این است که گرادیان‌های مخروطی را چند بار پر کنید تا زمانی که به صورت بومی در کروم قرار بگیرند. مثال دیگر: در یک جلسه CSS، تصمیم گرفته شد که اکنون می توانید چندین رنگ حاشیه داشته باشید. در حالی که این جلسه هنوز ادامه داشت، همکارم Ian Kilpatrick یک polyfill برای این رفتار CSS جدید با استفاده از رنگ Worklet نوشت .

تفکر خارج از "جعبه"

اکثر مردم وقتی در مورد رنگ کاری یاد می گیرند شروع به فکر کردن به تصاویر پس زمینه و تصاویر حاشیه می کنند. یکی از موارد استفاده کمتر بصری برای Worklet رنگ mask-image است تا عناصر DOM دارای اشکال دلخواه باشند. به عنوان مثال یک الماس :

یک عنصر DOM به شکل الماس.
یک عنصر DOM به شکل الماس.

mask-image تصویری به اندازه عنصر می گیرد. مناطقی که تصویر ماسک شفاف است، عنصر شفاف است. مناطقی که تصویر ماسک مات است، عنصر مات است.

اکنون در کروم

Worklet Paint مدتی است که در Chrome Canary وجود دارد. با کروم 65، به طور پیش فرض فعال است. ادامه دهید و امکانات جدیدی را که Worklet رنگ باز می کند امتحان کنید و آنچه را که ساخته اید به ما نشان دهید! برای الهام بیشتر، نگاهی به مجموعه وینسنت دی اولیویرا بیندازید.