واجهة برمجة تطبيقات 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، نحتاج إلى تحميل واجهة برمجة تطبيقات 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> في الماضي، من المفترض أن يبدو هذا الرمز مألوفًا. عرض البث المباشر عرض توضيحي هنا.

مساحة نصية بنمط رقعة الشطرنج كصورة خلفية
مساحة نصية بنمط رقعة الشطرنج كصورة خلفية

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

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

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

لحسن الحظ، يمكن لوظيفة الرسم الوصول إلى خصائص 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. أثناء التواجد إشارات إيجابية من جميع موردي المتصفحات الآخرين، فلن يتم إحراز تقدم كبير. للاطّلاع على آخر الأخبار، يمكنك مراجعة المقالة Is Houdini ready more? (هل هوديني جاهز؟) بانتظام. في هذه الأثناء، احرص على استخدام البيانات التحسين للحفاظ على تشغيل التعليمة البرمجية حتى في حال عدم دعم سرعة عرض محتوى الصفحة الوظيفة. للتأكد من أن الأمور تسير كما هو متوقع، يجب عليك تعديل التعليمة البرمجية في مكانان: 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);
}

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

استخدام polyfill لـ CSS

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

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

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

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

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

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

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

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

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

الآن في Chrome

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