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

Chrome 65 में नई संभावनाएं

CSS Paint API (जिसे “CSS कस्टम पेंट” या “Houdini’s पेंट वर्कलेट” के नाम से भी जाना जाता है) को 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 का इस्तेमाल उसी तरह कर सकते हैं जिस तरह 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> का इस्तेमाल किया है, तो आपको यह कोड जाना-पहचाना लगेगा. लाइव डेमो यहां देखें.

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

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

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

वर्कलेट में पैरामीटर सेट करना

अच्छी बात यह है कि पेंट वर्कलेट से दूसरी सीएसएस प्रॉपर्टी को ऐक्सेस किया जा सकता है. यहां से अतिरिक्त पैरामीटर 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 पर ही पेंट किया गया वर्कलेट लागू किया गया है. हालांकि, अन्य सभी ब्राउज़र वेंडर से इस बारे में पॉज़िटिव सिग्नल मिलते हैं, लेकिन इसमें ज़्यादा प्रोग्रेस नहीं हुई है. अप-टू-डेट रहने के लिए, नियमित तौर पर क्या हौडीनी अब भी तैयार है? देखें. इस बीच, कोड को चलाने के लिए प्रोग्रेसिव बेहतर सुविधा का इस्तेमाल करना न भूलें. भले ही, पेंटवर्कलेट की सुविधा न हो. यह पक्का करने के लिए कि चीज़ें उम्मीद के मुताबिक काम करें, आपको अपने कोड में इन दो जगहों पर बदलाव करना होगा: सीएसएस और 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 के दूसरे एलान में पहले वाले को ओवरराइट कर दिया जाएगा. अगर किसी ब्राउज़र में पेंट वर्कलेट की सुविधा नहीं है, तो दूसरा एलान अमान्य होगा और उसे खारिज कर दिया जाएगा. इससे, पहला एलान लागू हो जाएगा.

सीएसएस पेंट पॉलीफ़िल

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

इस्तेमाल के उदाहरण

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

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

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

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

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

हीरे के आकार वाला DOM एलिमेंट.
डायमंड के आकार वाला DOM एलिमेंट.

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

अब Chrome में

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