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

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

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

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

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

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

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

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

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

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

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

अब Chrome में

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