सीएसएस पेंट एपीआई

Chrome 65 में नई सुविधाएं

CSS Paint API (जिसे “CSS कस्टम पेंट” या “Houdini का पेंट वर्कलेट” भी कहा जाता है) Chrome 65 से डिफ़ॉल्ट रूप से चालू है. यह क्या है? इसकी मदद से क्या किया जा सकता है? यह सुविधा कैसे काम करती है? तो, आगे पढ़ें…

CSS Paint API की मदद से, प्रोग्राम के हिसाब से इमेज जनरेट की जा सकती है. ऐसा तब किया जाता है, जब किसी सीएसएस प्रॉपर्टी में इमेज की ज़रूरत होती है. आम तौर पर, background-image या border-image जैसी प्रॉपर्टी का इस्तेमाल, इमेज फ़ाइल लोड करने के लिए url() के साथ किया जाता है. इसके अलावा, इन्हें linear-gradient() जैसे सीएसएस के पहले से मौजूद फ़ंक्शन के साथ भी इस्तेमाल किया जा सकता है. इनके बजाय, अब पेंट वर्कलेट का रेफ़रंस देने के लिए, paint(myPainter) का इस्तेमाल किया जा सकता है.

पेंट वर्कलेट लिखना

myPainter नाम के पेंट वर्कलेट को तय करने के लिए, हमें CSS.paintWorklet.addModule('my-paint-worklet.js') का इस्तेमाल करके सीएसएस पेंट वर्कलेट फ़ाइल लोड करनी होगी. उस फ़ाइल में, हम पेंट वर्कलेट क्लास को रजिस्टर करने के लिए registerPaint फ़ंक्शन का इस्तेमाल कर सकते हैं:

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

registerPaint('myPainter', MyPainter);

paint() कॉलबैक में, ctx का इस्तेमाल उसी तरह किया जा सकता है जिस तरह <canvas> में CanvasRenderingContext2D का इस्तेमाल किया जाता है. अगर आपको <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> का इस्तेमाल किया है, तो आपको यह कोड जाना-पहचाना लगेगा. यहां लाइव डेमो देखें.

बैकग्राउंड इमेज के तौर पर चेकरबोर्ड पैटर्न वाला टेक्स्टएरिया
बैकग्राउंड इमेज के तौर पर चेकरबोर्ड पैटर्न वाला टेक्स्ट एरिया.

आम तौर पर इस्तेमाल की जाने वाली बैकग्राउंड इमेज के मुकाबले, यहां पैटर्न को मांग पर फिर से बनाया जाएगा. ऐसा तब होगा, जब उपयोगकर्ता टेक्स्टएरिया का साइज़ बदलेगा. इसका मतलब है कि बैकग्राउंड इमेज हमेशा उतनी ही बड़ी होती है जितनी ज़रूरी होती है. इसमें ज़्यादा पिक्सल डेंसिटी वाले डिसप्ले के लिए, इमेज का साइज़ बढ़ाना भी शामिल है.

यह सुविधा काफ़ी अच्छी है, लेकिन इसमें बदलाव नहीं किया जा सकता. क्या हर बार एक ही पैटर्न के लिए, अलग-अलग साइज़ के स्क्वेयर के साथ नया वर्कलेट लिखना होगा? इसका जवाब है, नहीं!

अपने वर्कलेट को पैरामीटराइज़ करना

अच्छी बात यह है कि पेंट वर्कलेट, अन्य सीएसएस प्रॉपर्टी को ऐक्सेस कर सकता है. यहीं पर अतिरिक्त पैरामीटर properties काम आता है. क्लास को स्टैटिक inputProperties एट्रिब्यूट देकर, किसी भी सीएसएस प्रॉपर्टी में होने वाले बदलावों की सदस्यता ली जा सकती है. इसमें कस्टम प्रॉपर्टी भी शामिल हैं. आपको वैल्यू, 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 में जाकर, वैल्यू में बदलाव कर सकते हैं, ताकि हमें सही लुक मिल सके.

ऐसे ब्राउज़र जिनमें पेंट वर्कलेट काम नहीं करता

फ़िलहाल, सिर्फ़ Chrome में पेंट वर्कलेट लागू किया गया है. हालांकि, अन्य सभी ब्राउज़र वेंडर से मिले सिग्नल अच्छे हैं, लेकिन इसमें ज़्यादा प्रगति नहीं हुई है. अप-टू-डेट रहने के लिए, समय-समय पर क्या Houdini अब तक तैयार है? पर जाएं. इस दौरान, अपने कोड को चालू रखने के लिए, प्रोग्रेसिव बेहतर बनाने की सुविधा का इस्तेमाल करना न भूलें. भले ही, पेंट वर्कलेट के लिए कोई सहायता न हो. यह पक्का करने के लिए कि चीज़ें उम्मीद के मुताबिक काम करें, आपको अपने कोड में दो जगहों पर बदलाव करना होगा: सीएसएस और JS.

JS में पेंट वर्कलेट के लिए सहायता का पता लगाने के लिए, CSS ऑब्जेक्ट की जांच की जा सकती है: js if ('paintWorklet' in CSS) { CSS.paintWorklet.addModule('mystuff.js'); } सीएसएस के लिए, आपके पास दो विकल्प हैं. @supports का इस्तेमाल इन कामों के लिए किया जा सकता है:

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

एक और आसान तरीका यह है कि सीएसएस में मौजूद किसी अनजान फ़ंक्शन को अमान्य कर दिया जाए और फिर पूरी प्रॉपर्टी के एलान को अनदेखा कर दिया जाए. अगर किसी प्रॉपर्टी को दो बार तय किया जाता है — पहले पेंट वर्कलेट के बिना और फिर पेंट वर्कलेट के साथ — तो आपको प्रगतिशील बेहतर अनुभव मिलता है:

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

जिन ब्राउज़र में पेंट वर्कलेट की सुविधा काम करती है उनमें background-image का दूसरा एलान, पहले एलान को ओवरराइट कर देगा. जिन ब्राउज़र में पेंट वर्कलेट के लिए सहायता नहीं है उनमें दूसरा एलान अमान्य होगा और उसे खारिज कर दिया जाएगा. हालांकि, पहला एलान लागू रहेगा.

CSS Paint Polyfill

कई कामों के लिए, सीएसएस पेंट पॉलीफ़िल का इस्तेमाल भी किया जा सकता है. इससे, आधुनिक ब्राउज़र में सीएसएस कस्टम पेंट और पेंट वर्कलेट की सुविधा मिलती है.

उपयोग के उदाहरण

पेंट वर्कलेट के इस्तेमाल के कई उदाहरण हैं. इनमें से कुछ उदाहरणों को समझना आसान है. सबसे आसान तरीका यह है कि अपने DOM का साइज़ कम करने के लिए, पेंट वर्कलेट का इस्तेमाल करें. अक्सर, सीएसएस का इस्तेमाल करके एलिमेंट सिर्फ़ बेहतर बनाने के लिए जोड़े जाते हैं. उदाहरण के लिए, Material Design Lite में, रिपल इफ़ेक्ट वाले बटन में दो अतिरिक्त <span> एलिमेंट होते हैं, ताकि रिपल इफ़ेक्ट लागू किया जा सके. अगर आपके पास बहुत सारे बटन हैं, तो इससे डीओएम एलिमेंट की संख्या काफ़ी बढ़ सकती है. साथ ही, मोबाइल पर परफ़ॉर्मेंस खराब हो सकती है. इसके बजाय, पेंट वर्कलेट का इस्तेमाल करके रिपल इफ़ेक्ट लागू करने पर, आपको कोई अतिरिक्त एलिमेंट नहीं दिखेगा. सिर्फ़ एक पेंट वर्कलेट दिखेगा. इसके अलावा, आपके पास ऐसा कुछ है जिसे पसंद के मुताबिक बनाना और पैरामीटर करना बहुत आसान है.

पेंट वर्कलेट का इस्तेमाल करने का एक और फ़ायदा यह है कि ज़्यादातर मामलों में, पेंट वर्कलेट का इस्तेमाल करने वाला समाधान, बाइट के हिसाब से छोटा होता है. हालांकि, इसके लिए आपको कुछ बदलाव करने होंगे: जब भी कैनवस का साइज़ या कोई पैरामीटर बदलेगा, तब आपका पेंट कोड चलेगा. इसलिए, अगर आपका कोड जटिल है और इसमें ज़्यादा समय लगता है, तो हो सकता है कि इसमें लैग दिखे. Chrome, पेंट वर्कलेट को मुख्य थ्रेड से हटाने पर काम कर रहा है, ताकि लंबे समय तक चलने वाले पेंट वर्कलेट भी मुख्य थ्रेड के रिस्पॉन्सिव होने पर असर न डालें.

मेरे हिसाब से, सबसे दिलचस्प बात यह है कि पेंट वर्कलेट की मदद से, सीएसएस की उन सुविधाओं को बेहतर तरीके से पॉलीफ़िल किया जा सकता है जो ब्राउज़र में अभी उपलब्ध नहीं हैं. उदाहरण के लिए, कॉनिक ग्रेडिएंट को तब तक पॉलीफ़िल करना, जब तक वे Chrome में नेटिव तौर पर उपलब्ध न हो जाएं. एक और उदाहरण: सीएसएस मीटिंग में, यह तय किया गया था कि अब बॉर्डर के कई रंग हो सकते हैं. इस मीटिंग के दौरान, मेरे सहकर्मी इयान किल्पैट्रिक ने पेंट वर्कलेट का इस्तेमाल करके, सीएसएस के इस नए व्यवहार के लिए पॉलीफ़िल लिखा.

“बॉक्स” से बाहर सोचना

पेंट वर्कलेट के बारे में जानने के बाद, ज़्यादातर लोग बैकग्राउंड इमेज और बॉर्डर इमेज के बारे में सोचने लगते हैं. पेंट वर्कलेट के इस्तेमाल का एक और उदाहरण यह है कि mask-image डीओएम एलिमेंट को मनमुताबिक आकार दिया जा सकता है. उदाहरण के लिए, डायमंड:

हीरे के आकार का डीओएम एलिमेंट.
हीरे के आकार का डीओएम एलिमेंट.

mask-image, एलिमेंट के साइज़ वाली इमेज लेता है. जिन जगहों पर मास्क इमेज पारदर्शी है वहां एलिमेंट भी पारदर्शी होगा. जिन जगहों पर मास्क की इमेज अपारदर्शी है वहां एलिमेंट भी अपारदर्शी होगा.

अब Chrome में उपलब्ध

Paint वर्कलेट, Chrome Canary में कुछ समय से उपलब्ध है. Chrome 65 में, यह सुविधा डिफ़ॉल्ट रूप से चालू होती है. आगे बढ़ें और पेंट वर्कलेट में मौजूद नई सुविधाओं को आज़माएं. साथ ही, हमें बताएं कि आपने क्या बनाया है! ज़्यादा जानकारी के लिए, Vincent De Oliveira के कलेक्शन पर जाएं.