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

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

CSS Paint API (इसे “CSS कस्टम पेंट” या “Huudini का पेंट वर्कलेट भी कहा जाता है) 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 में पेंट वर्कलेट लागू किया गया है. हालांकि, अन्य ब्राउज़र वेंडर से पॉज़िटिव सिग्नल मिलते हैं, लेकिन खास जानकारी नहीं मिली है. अप-टू-डेट रहने के लिए, क्या 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 का इस्तेमाल भी किया जा सकता है. यह मॉर्डन ब्राउज़र के साथ, सीएसएस कस्टम पेंट और पेंट वर्कलेट के साथ काम करता है.

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

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

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

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

कुछ अलग तरीके से सोचना

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

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

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

अब Chrome में

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