- canvas-confetti वेब पेज पर canvas-आधारित confetti animation चलाने के लिए एक client-side लाइब्रेरी है, जो NPM इंस्टॉलेशन और CDN direct include दोनों को सपोर्ट करती है
- बेसिक
confetti() API एक options object के जरिए particle count, angle, spread, velocity, gravity, color, shape, position, z-index आदि को adjust करती है, और Promise सपोर्ट वाले environment में animation पूरा होने का समय भी दिया जा सकता है
- Reduced Motion यूज़र्स के लिए
disableForReducedMotion option दिया गया है; इसका डिफ़ॉल्ट मान अभी false है, लेकिन भविष्य की किसी major release में यह बदल सकता है
- SVG Path और text-आधारित custom shapes बनाई जा सकती हैं, और
square, circle, star जैसी बेसिक shapes के अलावा emoji confetti जैसे effect भी बनाए जा सकते हैं
confetti.create() किसी खास canvas पर instance बनाता है और resize, useWorker जैसे global options को सपोर्ट करता है, लेकिन useWorker: true में canvas का control web worker को चला जाता है, इसलिए main thread से उसे modify करने पर error होगा
इंस्टॉलेशन और चलाने के तरीके
- demo page पर लाइब्रेरी का काम देख सकते हैं
- इसे NPM package के रूप में install किया जा सकता है
npm install --save canvas-confetti
- प्रोजेक्ट build में इसे
require('canvas-confetti') से इस्तेमाल किया जा सकता है
- यह लाइब्रेरी एक client component है और Node में नहीं चलती
- README बताता है कि प्रोजेक्ट को webpack जैसे टूल से build करना होगा
- HTML पेज में इसे CDN script के जरिए सीधे include किया जा सकता है
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.4/…;
- CDN इस्तेमाल करते समय प्रोजेक्ट में include करते वक्त उपलब्ध latest version इस्तेमाल करने की सलाह दी जाती है; सभी versions releases page पर देखे जा सकते हैं
Reduced Motion सपोर्ट
- कुछ यूज़र वेबसाइट पर movement नहीं चाहते या उसे कम पसंद करते हैं, और browser इसे
prefers-reduced-motion के जरिए बता सकता है
disableForReducedMotion option इस्तेमाल करने पर ऐसे यूज़र्स के लिए confetti नहीं दिखाया जा सकता जिन्हें भ्रमित करने वाले animation से दिक्कत हो सकती है
- इस option का मौजूदा default
false है
- भविष्य की major release में इसका default बदलने पर विचार किया जा रहा है; अगर आपकी मजबूत राय है तो issue के रूप में बता सकते हैं
- अगर
disableForReducedMotion लागू होने से confetti disable हो जाता है, तो confetti() Promise तुरंत resolve हो जाता है
बेसिक API और Promise व्यवहार
- NPM install होने पर प्रोजेक्ट build में इसे client component की तरह require किया जा सकता है, और CDN version में यह
window के confetti function के रूप में expose होता है
confetti([options]) एक optional options object लेता है
- अगर
window.Promise मौजूद है, तो यह animation पूरा होने की सूचना देने वाला Promise लौटाता है
- Promise न होने वाले IE जैसे environment में यह
null लौटाता है
- Promise polyfill इस्तेमाल किया जा सकता है
confetti.Promise = MyPromise के रूप में Promise implementation सीधे दी जा सकती है
- पूरा होने से पहले
confetti को कई बार call करने पर हर बार वही Promise लौटता है
- अंदरूनी तौर पर वही canvas element reuse होता है, और मौजूदा animation जारी रखते हुए नया confetti जोड़ दिया जाता है
- हर call से लौटा Promise सभी animations खत्म होने के बाद resolve होता है
मुख्य options
particleCount: launch किए जाने वाले confetti की संख्या, default 50
angle: launch angle, default 90, जहाँ 90 ऊपर की दिशा है
spread: केंद्र से फैलाव की सीमा, default 45
startVelocity: शुरुआती velocity, default 45
decay: velocity घटने की दर, default 0.9
- इसे 0 और 1 के बीच रखना चाहिए; range से बाहर होने पर velocity बढ़ भी सकती है
gravity: particles को नीचे खींचने की मात्रा, default 1
0.5 आधी gravity है, और इसकी कोई सीमा नहीं है, इसलिए इसे ऊपर उठने जैसा भी बनाया जा सकता है
drift: बाएँ-दाएँ बहाव की मात्रा, default 0
- negative का मतलब बाएँ, positive का मतलब दाएँ
flat: असली 3D confetti की तरह tilt और wobble effect को बंद कर सकता है; default false
ticks: confetti कितनी बार move करेगा, default 200
origin: launch की शुरुआती position
origin.x: पेज पर x position, 0 बायाँ, 1 दायाँ, default 0.5
origin.y: पेज पर y position, 0 ऊपर, 1 नीचे, default 0.5
colors: HEX format color strings की array
shapes: confetti shapes की array
- built-in default values
square, circle, star हैं
- default रूप से square और circle बराबर अनुपात में मिलाए जाते हैं
['circle', 'circle', 'square'] जैसी array ratio से mix proportion बदला जा सकता है
scalar: हर particle का scale, default 1
zIndex: confetti display layer, default 100
disableForReducedMotion: Reduced Motion preference वाले यूज़र्स के लिए confetti disable करता है
custom shapes बनाना
confetti.shapeFromPath({ path, matrix? }) SVG Path string से custom confetti shape बनाता है
- Path-आधारित shapes पर कुछ सीमाएँ हैं
- सभी path को filled shape की तरह treat किया जाता है; stroke path implement नहीं है
- path एक single color तक सीमित है
- हर path के लिए valid transform matrix ज़रूरी है
- matrix calculate करना महँगा हो सकता है, इसलिए development के दौरान हर path के लिए एक बार calculate करके cache करना बेहतर है
- वही path value होने पर matrix हमेशा एक जैसा रहेगा
- लाइब्रेरी update होने पर forward compatibility के लिए matrix को फिर से generate करके cache करना बेहतर है
- path-आधारित confetti उन्हीं browsers तक सीमित है जो
Path2D को सपोर्ट करते हैं
- return value एक
Shape object होती है, जिसे सीधे shapes array में डालकर इस्तेमाल किया जा सकता है
var triangle = confetti.shapeFromPath({ path: 'M0 10 L5 0 L10 10z' });
confetti({
shapes: [triangle]
});
confetti.shapeFromText({ text, scalar?, color?, fontFamily? }) text-आधारित confetti shape बनाता है, और standard Unicode emoji इस्तेमाल किए जा सकते हैं
- text-आधारित shapes emoji confetti के लिए उपयुक्त हैं
- wobble करने वाले confetti में आम तौर पर square-जैसे single character, खासकर emoji, बेहतर काम करते हैं
- text को हर बार draw नहीं किया जाता बल्कि rasterize किया जाता है, इसलिए shape बनने के बाद scale बहुत बदलने पर वह blurry हो सकता है
- अगर confetti options में
scalar इस्तेमाल करना है, तो shape बनाते समय भी वही scalar value देना बेहतर है
- text options में
text, scalar, color, fontFamily दिए जाते हैं
fontFamily का default native OS emoji rendering convention को follow करता है और sans-serif को fallback के रूप में इस्तेमाल करता है
- web font इस्तेमाल करते समय confetti render होने से पहले font load हो चुका होना चाहिए
var scalar = 2;
var pineapple = confetti.shapeFromText({ text: '🍍', scalar });
confetti({
shapes: [pineapple],
scalar
});
custom canvas और worker rendering
confetti.create(canvas, [globalOptions]) किसी खास canvas का इस्तेमाल करने वाला confetti function instance बनाता है
- यह तब उपयोगी है जब confetti को पेज के सिर्फ किसी खास हिस्से तक सीमित रखना हो
- डिफ़ॉल्ट रूप से यह method canvas पर draw करने के अलावा canvas को modify नहीं करता
- canvas में CSS से display size बदलने पर असली canvas image size नहीं बदलती, इसलिए वह खिंचा हुआ और blurry दिख सकता है
resize option on करने पर लाइब्रेरी canvas image size को match करती है, और window resize या mobile rotation पर भी उसे maintain करती है
- एक ही canvas element पर confetti instance को कई बार initialize नहीं करना चाहिए; बनाए गए custom instance को बनाए रखना चाहिए
-
global options
resize: canvas image size सेट करे और window changes के साथ उसे बनाए रखे या नहीं, default false
useWorker: जहाँ संभव हो, async web worker में confetti animation render करता है, default false
- default स्थिति में animation हमेशा main thread पर चलता है
- अगर browser सपोर्ट करता है, तो animation main thread के बाहर चल सकता है ताकि main thread block न हो
- unsupported browsers में इस value को ignore कर दिया जाता है
disableForReducedMotion: इस confetti instance को यूज़र की Reduced Motion request का हमेशा सम्मान करने देता है
-
useWorker: true सावधानियाँ
useWorker: true इस्तेमाल करने पर canvas का control web worker को transfer हो जाता है
- इस स्थिति में canvas को DOM से हटाने के अलावा main thread से उसे modify करने पर error होगा
- अगर canvas को सीधे modify करना है, तो
useWorker option इस्तेमाल नहीं करना चाहिए
var myCanvas = document.createElement('canvas');
document.body.appendChild(myCanvas);
var myConfetti = confetti.create(myCanvas, {
resize: true,
useWorker: true
});
myConfetti({
particleCount: 100,
spread: 160
});
animation रोकना और example patterns
confetti.reset() animation रोकता है, सारे confetti हटाता है, और pending Promise को तुरंत resolve कर देता है
confetti.create() से बने अलग instance का अपना reset method होता है
confetti();
setTimeout(() => {
confetti.reset();
}, 100);
- बेसिक execution में बिना argument के
confetti() call किया जाता है
particleCount: 150 के साथ बहुत सारा confetti launch किया जा सकता है
spread: 180 से wide-spread confetti बनाया जा सकता है
origin में Math.random() इस्तेमाल करने पर पेज पर random position से छोटे explosion effect बनाए जा सकते हैं
- README example
requestAnimationFrame का इस्तेमाल करके 30 सेकंड तक बाएँ और दाएँ किनारों से लगातार confetti launch करने वाला pattern दिखाता है
1 टिप्पणियां
Hacker News की राय
यहां बेहतर performance वाली animation बनाने की तरकीब यह है कि canvas पर draw करें, फिर उस canvas को बाकी सभी elements के सामने रखें, लेकिन pointer events बंद कर दें ताकि page के साथ interaction जारी रह सके
2015 में high school में web development करने के अच्छे दिन याद आ गए. homecoming पर साथ चलने के लिए एक लड़की से पूछने के लिए मैंने confetti वाला छोटा website बनाया था, पीछे मुड़कर देखूं तो काफी nerdy था
उस समय किसी बच्चे के लिए website बनाना superpower जैसा लगता था. timing के हिसाब से शायद यह package नहीं था, लेकिन animation काफी अच्छी थी
मुझे ऐसे पूरी तरह मज़ेदार छोटे projects पसंद हैं. programming शुरू करने की वजह भी यही थी, और आज भी यह मेरे लिए बड़ी प्रेरणा है
demo page का यह हिस्सा अच्छा लगा:
ऐसी details को लेकर obsession दुर्लभ है, और चाहे statistical visualization हो, film props हों या website confetti, जब भी यह दिखता है तो बहुत कीमती लगता है
solution के तौर पर मैं random distribution को ही बदलकर देखता. असल में verify तो करता, लेकिन अंदाज़ा है कि real-world distribution शायद Gaussian distribution के करीब होगा
जब sales rep कोई sale close करता है तो दिखने वाला admin dashboard confetti जोड़ा था, और यह आश्चर्यजनक रूप से मज़ेदार और motivating है
reset function को confetti.resetti() कहा होता तो अच्छा होता
"confetti.resetti = confetti.reset"से इसे आसानी से ठीक किया जा सकता हैइस approach की थोड़ी software engineering cost तो होगी, लेकिन जैसा कि कोई भी सावधान observer साफ़ देख सकता है, फायदा भारी है, इसलिए मेरे हिसाब से कर ही देना चाहिए
cool और useful library होने से अलग, यह John Ousterhout की Philosophy of Software Design में बताए गए deep module का अच्छा example है
सबसे basic version, यानी confetti summon करने वाला feature, इस्तेमाल में बहुत आसान है, लेकिन options देखें तो snow, specific colors, अलग-अलग confetti effects जैसी काफी चीज़ें मिलती हैं
बढ़िया और impressive है
साथ ही, मैं इसे अपने इस्तेमाल वाले किसी भी website पर चलते हुए नहीं देखना चाहता. खासकर newsletter popup या cart में item डालते समय confetti साथ आए, यह नहीं चाहिए
अजीब बात है कि इस effect को काफी effective ढंग से इस्तेमाल किया जा सकता है. ऐसे full-screen तरीके का तो पता नहीं, लेकिन हाल में जिस client के यहां गया था, उनके project management software में item close करने पर button green हो जाता था और ऐसा effect आता था
subtle था, लेकिन दिखने लायक था, और meeting के बाद एक दूसरे developer और मैंने दोनों ने कहा, “काफी ठीक effect था.” इससे “अच्छा, progress हो रही है!” वाला feel आता था
बस इसे optional बना देना चाहिए
legitimate use case शायद YouTube के like button जैसा होगा. बढ़िया animation है, और mobile app में device भी vibrate करता है. बहुत pleasant user experience है
browser में motion reduce prefer करने की setting कर सकते हैं. site operators और library maintainers को confetti जैसी चीज़ implement करते समय इसका सम्मान करना चाहिए. इस library में खास तौर पर
disableForReducedMotionoption हैकुछ जगहों पर ऐसे effects fit बैठते हैं. जैसे game complete होने पर
हम इस library का उपयोग तब करते हैं जब कोई व्यक्ति कोई particular qualification पूरी करता है. onboarding flow में इसका काफी अच्छा असर पड़ता है
Party.js library भी है: https://party.js.org/
तो कौन-सी छोटी है?
10.4 kB minified, 4.2kB minified + Gzip
https://bundlephobia.com/package/canvas-confetti@1.9.2
28.3kB minified, 7.4kB minified + Gzip
https://bundlephobia.com/package/party-js@2.2.0
हालांकि bundlephobia कैसे काम करता है, यह मुझे ठीक से नहीं पता. हो सकता है यह package का final size सबसे अच्छे से न दिखाता हो. शायद code splitting या सिर्फ ज़रूरी चीज़ें import करने के तरीके को reflect नहीं करता. मैं इसे बस एक तेज़ और rough overview की तरह देख रहा हूं
Gzip के हिसाब से confetti कुछ KB से जीतता दिखता है, इसलिए अगर उन कुछ KB को squeeze करना ज़रूरी नहीं है, तो कौन-से features चाहिए इस पर निर्भर करते हुए दोनों चल सकते हैं
original post का script mobile पर कहीं ज़्यादा performant दिखता है
original post वाली library काफी ज़्यादा performant लगती है. मेरे पुराने work computer पर Party.js में सिर्फ 3 clicks के बाद ही हल्का delay महसूस होता है
canvas-confetti में delay तब शुरू हुआ जब मैंने कई seconds तक लगातार click किया और शायद 30 से ज़्यादा confetti instances और बहुत सारे particles बना दिए
downforacross.com पर crossword solve करता हूं, और puzzle solve होने पर confetti निकलता है
इसे हल्का महसूस कराने के लिए यहां के ज़्यादा performant code का कुछ हिस्सा इस्तेमाल किया जा सकता है
लेकिन अगर यह “fun” site या rare use नहीं है, तो ऐसी animations हर जगह दिखना मुझे पसंद नहीं होगा
title में useful डालने की खास ज़रूरत नहीं लगती