واجهة برمجة تطبيقات CSS Paint

إمكانات جديدة في Chrome 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) للإشارة إلى تطبيق رسم صغير.

كتابة قالب طلاء

لتحديد عامل طلاء يسمى myPainter، نحتاج إلى تحميل ملف Worklet الخاص بالعناصر في CSS باستخدام CSS.paintWorklet.addModule('my-paint-worklet.js'). في هذا الملف، يمكننا استخدام الدالة registerPaint لتسجيل فئة عمل الطلاء:

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

registerPaint('myPainter', MyPainter);

داخل معاودة الاتصال paint()، يمكننا استخدام ctx بالطريقة نفسها التي نستخدم بها CanvasRenderingContext2D كما نعرفها من <canvas>. إذا كنت تعرف كيفية الرسم في <canvas>، يمكنك رسم أوراق شجر صغيرة! يخبرنا geometry بعرض وارتفاع اللوحة تحت تصرفنا. properties سأشرحها لاحقًا في هذه المقالة.

كمثال تمهيدي، لنكتب عملاً صغيرًا لطلاء رقعة الشطرنج ونستخدمه كصورة خلفية لـ <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 مع نمط رقعة الشطرنج كصورة خلفية

الفرق عن استخدام صورة خلفية شائعة هنا هو أنه ستتم إعادة رسم النمط عند الطلب، كلما غيّر المستخدم حجم منطقة النص. وهذا يعني أنّ صورة الخلفية تكون دائمًا بالحجم المطلوب، بما في ذلك تعويض الشاشات عالية الكثافة.

هذا رائع، ولكنه ثابت أيضًا. هل نرغب في كتابة ملف عمل جديد في كل مرة أردنا فيها نفس النمط ولكن بمربعات مختلفة الحجم؟ والجواب هو لا

ضبط معلَمة في الوظيفة

لحسن الحظ، يمكن لوظائف الرسم الوصول إلى خصائص 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);

يمكننا الآن استخدام نفس التعليمة البرمجية لجميع الأنواع المختلفة من رقائق الشطرنج. والأفضل من ذلك، يمكننا الآن الانتقال إلى "أدوات مطوري البرامج" والتركيز على القيم إلى أن نعثر على الشكل المناسب.

المتصفحات التي لا تدعم طلاء الشاشة

في وقت الكتابة، لم يتم تنفيذ سوى الأداة الصغيرة جدًا في Chrome. وعلى الرغم من وجود إشارات إيجابية من جميع موردي المتصفحات الآخرين، لم يتم إحراز تقدم كبير. للاطّلاع على آخر الأخبار، يمكنك مراجعة هل هوديني جاهز بعد؟ بانتظام. في هذه الأثناء، تأكد من استخدام التحسين التدريجي للحفاظ على تشغيل التعليمة البرمجية حتى إذا لم يكن هناك دعم لتطبيق الطلاء. للتأكد من أن الأمور تسير كما هو متوقع، يجب عليك تعديل التعليمة البرمجية في مكانين: CSS وJS.

يمكن رصد توافق وظيفة الرسم في JavaScript من خلال التحقّق من الكائن 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);
}

في المتصفّحات التي تتوافق مع ميزة Paint Worklet، سيحلّ إعلان background-image الثاني محلّ الإعلان الأول. في المتصفّحات التي لا تتوافق مع ميزة "النُسخ المصغّرة"، يكون التعريف الثاني غير صالح وسيتم تجاهله، ما يترك التعريف الأول ساري المفعول.

استخدام polyfill لـ CSS

بالنسبة إلى العديد من الاستخدامات، يمكن أيضًا استخدام CSS Paint Polyfill، الذي يضيف دعم CSS Custom Paint وPaint Worklets إلى المتصفّحات الحديثة.

حالات الاستخدام

هناك العديد من حالات الاستخدام لصخور الطلاء، بعضها أكثر وضوحًا من الأخرى. وأحد أكثرها وضوحًا هو استخدام أداة الرسم لتقليل حجم نموذج كائن المستند (DOM). في كثير من الأحيان، تتم إضافة العناصر فقط لإنشاء زخارف باستخدام CSS. على سبيل المثال، في Material Design Lite، يحتوي الزر الذي له تأثير التموج على عنصرَي <span> إضافيَين لتنفيذ تمويج نفسه. إذا كان لديك الكثير من الأزرار، قد يؤدي ذلك إلى إضافة عدد كبير من عناصر DOM ويمكن أن يؤدي إلى انخفاض مستوى الأداء على الأجهزة الجوّالة. إذا قمت بتنفيذ تأثير التموج باستخدام طلاء الميزات، بدلاً من ذلك، ستحصل على 0 عنصر إضافي وعنصر طلاء واحد فقط. بالإضافة إلى ذلك، لديك شيء أسهل بكثير في تخصيصه وإعداد معلمات له.

من الجوانب الإيجابية الأخرى لاستخدام صلصة الطلاء أنه - في معظم السيناريوهات - يكون الحل باستخدام صلصة الطلاء صغيرًا من حيث وحدات البايت. بالطبع، هناك مقايضة: سيتم تشغيل تعليمات الطلاء الخاصة بك كلما تغير حجم اللوحة أو أي من المعايير. لذلك إذا كانت التعليمة البرمجية معقدة وتستغرق وقتًا طويلاً، فقد تؤدي إلى عرض جانك. يعمل Chrome على نقل مهام الرسم خارج سلسلة التعليمات الرئيسية كي لا تؤثر حتى مهام الرسم التي تم إنشاؤها منذ فترة طويلة في استجابة سلسلة التعليمات الرئيسية.

بالنسبة إليّ، فإنّ أكثر ما يخطر في بالنا هو أنّ أداة الرسم تتيح لك إضافة ميزات CSS المختلفة التي لا تتوفّر في المتصفّح حتى الآن. ومن الأمثلة على ذلك عمل تعويض التدرجات المخروطية حتى تصل إلى Chrome بشكلٍ أصلي. مثال آخر: في اجتماع CSS، قررت أنه يمكنك الآن أن يكون لديك ألوان حدود متعددة. وبينما كان هذا الاجتماع لا يزال جاريًا، كتب زميلي إيان كيلباتريكلسلوك CSS الجديد هذا باستخدام أدوات الرسم.

التفكير خارج الصندوق

يبدأ معظم الأشخاص في التفكير في صور الخلفية وصور الحدود عندما يتعرفون على عمل الطلاء. إحدى حالات الاستخدام الأقل سهولة في استخدام أداة الرسم هي mask-image لجعل عناصر DOM ذات أشكال عشوائية. على سبيل المثال، ماسة:

عنصر DOM على شكل معيّن.
عنصر DOM على شكل معيّن.

تلتقط mask-image صورة بحجم العنصر. المناطق التي تكون فيها صورة القناع شفافة، يكون العنصر شفافًا. المناطق التي تكون فيها صورة القناع معتمة، أو العنصر غير شفاف.

الآن في Chrome

تعمل ميزة Paint Worklet منذ فترة في Chrome Canary. مع الإصدار 65 من Chrome، يتم تفعيلها تلقائيًا. انطلق وجرب الاحتمالات الجديدة التي يفتحها طلاء الأظافر وتوضح لنا ما قمت بإنشائه! للحصول على مزيد من الأفكار، يمكنك إلقاء نظرة على مجموعة "فنسنت دي أوليفيرا".