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

إمكانيات جديدة في Chrome 65

يتم تفعيل واجهة برمجة تطبيقات CSS (المعروفة أيضًا باسم "CSS Custom Paint" أو "Houdini’s Paint Worklet" بشكل تلقائي بدءًا من Chrome 65. ما هي هذه الميزة؟ ماذا يمكنك أن تفعل به؟ ما هي طريقة العمل؟ حسنًا، استمر في القراءة، هلا...

تتيح لك واجهة برمجة تطبيقات CSS Paint API إنشاء صورة بشكل آلي في الحالات التي تتوقع فيها خاصية CSS ظهور صورة. ويتم عادةً استخدام الخصائص مثل background-image أو border-image مع url() لتحميل ملف صورة أو مع دوال CSS المضمّنة مثل linear-gradient(). بدلاً من استخدام هذه الأدوات، يمكنك الآن استخدام paint(myPainter) للإشارة إلى عمل مصغَّر.

كتابة عمل طلاء مصغّر

لتحديد وظيفة طلاء اسمية myPainter، نحتاج إلى تحميل ملف عمل مصغَّر لطلاء 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>. (أستخدم منطقة نصية لأنه يمكن تغيير حجمها افتراضيًا):

<!-- 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. وعلى الرغم من أنّ هناك إشارات إيجابية من جميع مورّدي المتصفحات الآخرين، فليس هناك الكثير من التقدّم. للاطّلاع على آخر المعلومات، تحقّق بانتظام من السؤال هل Houdini جاهزية بعد؟. وفي غضون ذلك، تأكد من استخدام التحسين التدريجي للحفاظ على تشغيل التعليمات البرمجية حتى إذا لم يكن هناك دعم للعمل الصغير للطلاء. للتأكد من أن الأمور تسير كما هو متوقع، عليك تعديل التعليمات البرمجية في مكانين: CSS وJS.

يمكن رصد توافق محتوى JavaScript مع محتوى 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);
}

في المتصفّحات التي تتوافق مع هذه الميزة، سيحلّ التعريف الثاني للسمة background-image محلّ الإعلان الأول. في المتصفّحات التي لا تتيح العمل الصغير، يكون التعريف الثاني غير صالح وسيتم تجاهله، ليبقى التعريف الأول ساري المفعول.

الملء التلقائي لطلاء CSS

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

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

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

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

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

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

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

عنصر DOM على شكل معيَّن معيّن.
عنصر DOM على شكل ماسة.

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

الميزات الجديدة في Chrome

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