ऑनबोर्डिंग और एम्प्टी स्टेट में मैस्कॉट कैसे जोड़ें
Charmotion टीम द्वारा · अपडेट:

ऑनबोर्डिंग और एम्प्टी स्टेट में मैस्कॉट जोड़ने के लिए, हर स्टेप और खाली स्क्रीन की सूची बनाएँ, हर एक को एक लूपिंग मूड (welcome, listening, sleeping) या एक वन-शॉट रिएक्शन (success, error) दें, और उस स्टेट को अपने ऐप के मौजूदा events से सेट करें। असली काम टेक्स्ट और बटन से होने दें, और यूज़र्स को मोशन skip या pause करने दें।
मुख्य बातें
- एनिमेट करने से पहले स्क्रीन को स्टेट से मैप करें: हर स्टेप के लिए एक मूड, हर नतीजे के लिए एक ट्रिगर।
- मैस्कॉट को उन events से चलाएँ जो आपके पास पहले से हैं, जैसे focus, submit, success और error।
- एम्प्टी स्टेट को एक शांत लूप और एक साफ़ action चाहिए; मैस्कॉट माहौल बनाता है, काम बटन करता है।
- WCAG 2.2.2 के तहत कंटेंट के पास चलने वाले लंबे लूप को pause या stop करने का तरीका चाहिए, और मोशन कम करें चालू होने पर एक स्थिर पोज़ दिखना चाहिए।
पहले से कोई कैरेक्टर या लोगो है? अपने कैरेक्टर को असली ऐप स्क्रीन में देखें: स्प्लैश, ऑनबोर्डिंग, लोडिंग और एम्प्टी स्टेट स्क्रीन। यह फ़्री है, आपके ब्राउज़र में चलता है और कुछ भी अपलोड नहीं होता।
मैस्कॉट कहाँ मदद करता है, और कहाँ परेशान करता है?
मैस्कॉट उन पलों में मदद करता है जो वरना खाली या अनिश्चित लगते हैं: ऑनबोर्डिंग की पहली स्क्रीन, इनपुट का इंतज़ार करता फ़ॉर्म, ऐसी लिस्ट जिसमें अभी कुछ नहीं है, पहली सफलता के बाद का confirmation। यह तब परेशान करता है जब यह काम के बीच में आता है।
सही जगहें:
- एक welcome स्क्रीन जहाँ कैरेक्टर यूज़र का एक बार स्वागत करता है।
- साइन-अप या setup फ़ॉर्म, जहाँ यूज़र के टाइप करते समय वह "सुनता" है।
- जब कोई स्टेप सफल या असफल होता है, उस पल एक छोटे रिएक्शन के रूप में।
- खाली लिस्ट, inbox और search results में, साफ़ अगले action के पास एक शांत लूप के रूप में।
गलत जगहें:
- एनिमेशन खत्म होने तक next बटन को ब्लॉक करना।
- फ़ॉर्म फ़ील्ड या error messages को ढक देना।
- निर्देशों की जगह कैरेक्टर के एक्सप्रेशन रख देना। क्या करना है, यह टेक्स्ट को ही समझाना होगा।
- हर स्क्रीन पर ज़्यादा मोशन। इसे कुछ ही अहम पलों में इस्तेमाल करें।
Apple की launch guidance भी इससे जुड़ी बात कहती है: अगर आप ब्रांडेड splash पल चाहते हैं, तो उसे लॉन्च स्क्रीन में नहीं, बल्कि ऑनबोर्डिंग की शुरुआत में रखें (Apple HIG)। इससे ऑनबोर्डिंग की पहली स्क्रीन स्वागत के लिए स्वाभाविक जगह बन जाती है।
ऑनबोर्डिंग के किस स्टेप के लिए कौन-सा मैस्कॉट रिएक्शन सही है?
हर स्टेप को या तो एक condition (ऐसा लूप जो उसके सच रहने तक चलता है) या एक event (वन-शॉट, जो चलकर वापस लौट आता है) मानें। यह mapping ज़्यादातर ऑनबोर्डिंग flows को कवर करती है:
| स्टेप या event | स्टेट | प्रकार |
|---|---|---|
| Welcome स्क्रीन दिखती है | enter, फिर wave | ट्रिगर, फिर लूप |
| यूज़र text field पर focus करता है | listening | लूप |
| फ़ॉर्म submit हुआ, इंतज़ार जारी | thinking या loading | लूप |
| स्टेप सफल होता है | success, फिर happy | ट्रिगर, फिर लूप |
| Validation या network error | error, फिर idle | ट्रिगर, फिर लूप |
| हाँ/ना विकल्प (notifications, tracking) | yes या no | ट्रिगर |
| यूज़र ऑनबोर्डिंग छोड़ता है | exit | ट्रिगर |

रिएक्शन छोटे रखें ताकि यूज़र के आगे बढ़ने से पहले खत्म हो जाएँ, और आगे बढ़ने से पहले कभी रिएक्शन पूरा होने का इंतज़ार न करें। सभी स्टेट और टाइमिंग की पूरी सूची के लिए मैस्कॉट एनिमेशन स्टेट देखें।
Charmotion एक अपलोड किए गए मैस्कॉट से ये बनाता है: mood नंबर से चुने जाने वाले दस लूप (0 idle, 1 happy, 2 wave, 3 thinking, 4 sad, 5 loading, 6 listening, 7 talking, 8 sleeping, 9 attention) और छह ट्रिगर (success, error, yes, no, enter, exit), सब एक .riv में, हर पेड प्लान पर वेब, React और SwiftUI कोड के साथ।
एम्प्टी स्टेट पर मैस्कॉट कैसे दिखाएँ?
एम्प्टी स्टेट (जब स्क्रीन पर दिखाने को कुछ न हो) के तीन हिस्से होते हैं: क्या नहीं है, क्यों नहीं है, और आगे क्या करना है। मैस्कॉट इनके ऊपर या बगल में रहता है, कभी इनकी जगह नहीं।
<section class="empty">
<canvas id="mascot" width="160" height="160" aria-hidden="true"></canvas>
<h2>No projects yet</h2>
<p>Projects you create or are invited to will show up here.</p>
<button>Create a project</button>
</section>
एक शांत लूप चुनें: "अभी यहाँ कुछ नहीं है" के लिए sleeping या idle सही रहते हैं, जबकि "कुछ नया इंतज़ार कर रहा है" के लिए attention सही है। अलग-अलग एम्प्टी स्टेट एक ही फ़ाइल से अलग मूड इस्तेमाल कर सकते हैं, जैसे खाली inbox के लिए sleeping और कोई search result न मिलने पर thinking।
क्योंकि एम्प्टी स्टेट लंबे समय तक स्क्रीन पर रह सकता है, लंबे मोशन के एक्सेसिबिलिटी नियम का ध्यान रखें। WCAG 2.2 SC 2.2.2 के अनुसार, दूसरे कंटेंट के साथ पाँच सेकंड से ज़्यादा चलने वाले ऑटोमैटिक मोशन को pause, stop या hide करने का तरीका होना चाहिए (W3C)। व्यावहारिक विकल्प हैं: लूप को कुछ बार चलाकर किसी स्थिर फ़्रेम पर रोक देना, एक छोटा pause बटन जोड़ना, या लूप को बहुत हल्का रखना और मोशन कम करें चालू होने पर पूरी तरह रोक देना।
ऐप code से success और error रिएक्शन कैसे ट्रिगर करें?
जब कोई condition शुरू हो तब मूड सेट करें, और जब कोई event हो तब ट्रिगर फ़ायर करें। मैस्कॉट code को आपके ऐप की स्टेट सुननी चाहिए, उसे खुद नहीं संभालना चाहिए। Rive Data Binding के साथ React में, एक component स्टेप और आखिरी नतीजे को props के रूप में ले सकता है:
import { useEffect } from "react";
import { useRive, useViewModelInstanceNumber, useViewModelInstanceTrigger } from "@rive-app/react-webgl2";
export function Mascot({ mood, result }: { mood: number; result: { kind: "success" | "error"; id: number } | null }) {
const { rive, RiveComponent } = useRive({
src: "/character.riv",
stateMachine: "CharacterViewModelMachine",
autoplay: true,
autoBind: true,
});
const vmi = rive?.viewModelInstance;
const { setValue: setMood } = useViewModelInstanceNumber("mood", vmi);
const { trigger: success } = useViewModelInstanceTrigger("success", vmi);
const { trigger: error } = useViewModelInstanceTrigger("error", vmi);
useEffect(() => { setMood(mood); }, [mood, setMood]);
useEffect(() => {
if (result?.kind === "success") success();
if (result?.kind === "error") error();
}, [result?.id]);
return <RiveComponent aria-hidden="true" style={{ width: 160, height: 160 }} />;
}
बढ़ते हुए id के साथ नतीजा पास करने से एक ही रिएक्शन लगातार दो बार फ़ायर हो सकता है, जैसे दो असफल कोशिशों पर। Hook के नाम Rive के React runtime से आते हैं (Rive); सादे web पर इसके बराबर r.viewModelInstance.number("mood").value = 6 और .trigger("success").trigger() हैं।
SwiftUI, Compose और Flutter में इसे कैसे जोड़ें?
हर प्लेटफ़ॉर्म पर pattern एक जैसा है: हर स्क्रीन पर एक Rive instance रखें और अपने व्यू मॉडल के events से set-mood या fire-trigger कॉल करें। legacy input API के साथ:
SwiftUI (legacy Apple runtime, RiveViewModel):
@StateObject private var mascot = RiveViewModel(fileName: "character",
stateMachineName: "CharacterStateMachine")
mascot.view().frame(width: 160, height: 160).accessibilityHidden(true)
// on focus
mascot.setInput("mood", value: 6.0)
// on success
mascot.triggerInput("success")
Android (legacy RiveAnimationView, जिसे AndroidView के ज़रिए Compose से भी इस्तेमाल किया जा सकता है):
riveView.setNumberState("CharacterStateMachine", "mood", 6f)
riveView.fireState("CharacterStateMachine", "success")
Flutter:
final sm = controller.stateMachine;
sm.number("mood")?.value = 6;
sm.trigger("success")?.fire();
ये calls Rive के पुराने input docs से ली गई हैं: Apple, Android और Flutter। नए काम के लिए Rive अब Data Binding की सलाह देता है, और नया Apple रनटाइम सिर्फ़ Data Binding सपोर्ट करता है। मोशन कम करें सेटिंग के लिए SwiftUI में accessibilityReduceMotion पढ़ें और दूसरी जगहों पर इसके बराबर की सिस्टम सेटिंग देखें, फिर एनिमेशन की जगह एक स्थिर इमेज दिखाएँ।
कैसे पता करें कि मैस्कॉट मदद कर रहा है?
मैस्कॉट को ऑनबोर्डिंग के किसी भी दूसरे बदलाव की तरह मानें और उसे मापें। काम के संकेत:
- हर ऑनबोर्डिंग स्टेप का कंप्लीशन रेट, पहले और बाद में।
- हर स्टेप पर लगने वाला समय। अगर यह बढ़ता है, तो हो सकता है कोई एनिमेशन लोगों को धीमा कर रहा हो या फ़ॉर्म से ध्यान हटा रहा हो।
- एम्प्टी स्टेट कन्वर्ज़न: यूज़र खाली स्क्रीन पर मुख्य एक्शन पर कितनी बार क्लिक करते हैं।
- कुछ usability सेशन से मिला गुणात्मक फ़ीडबैक, जिसमें देखें कि क्या लोग कैरेक्टर के लिए रुककर इंतज़ार करते हैं।
code path में मैस्कॉट को वैकल्पिक रखें: अगर फ़ाइल लोड न हो या मोशन कम करें चालू हो, तो स्क्रीन स्थिर इमेज के साथ या बिना किसी इमेज के भी पूरी तरह पढ़ने और काम करने लायक होनी चाहिए। यह fallback धीमे कनेक्शन पर पहला लॉन्च भी तेज़ रखता है।
स्प्लैश से ऑनबोर्डिंग तक के बदलाव के लिए लॉन्च और स्प्लैश एनिमेशन गाइड देखें।
ऑनबोर्डिंग और एम्प्टी स्टेट में मैस्कॉट कैसे जोड़ें
- मौकों की सूची बनाएँ. हर ऑनबोर्डिंग स्टेप, हर खाली स्क्रीन और उनके बीच के इवेंट लिख लें: focus, submit, success, error, skip।
- स्टेट तय करें. हर स्थिति को एक लूपिंग मूड और हर इवेंट को एक ट्रिगर दें, जैसे focus पर listening और पूरे हुए स्टेप पर success।
- हर स्क्रीन पर एक instance जोड़ें. मैस्कॉट का canvas या view कंटेंट के बगल में तय साइज़ के साथ रखें, और उसे screen readers से छिपाएँ।
- इवेंट जोड़ें. मौजूदा व्यू मॉडल या component state से मूड सेट करें और ट्रिगर फ़ायर करें। नेविगेशन को कभी किसी एनिमेशन के लिए न रोकें।
- मोशन सेटिंग्स संभालें. लंबे एम्प्टी स्टेट लूप को कुछ चक्रों के बाद रोकें या pause कंट्रोल दें, और मोशन कम करें चालू होने पर स्थिर पोज़ दिखाएँ।
- मापें. स्टेप कंप्लीशन, हर स्टेप का समय और एम्प्टी स्टेट क्लिक की पहले और बाद में तुलना करें।
अक्सर पूछे जाने वाले सवाल
क्या ऑनबोर्डिंग मैस्कॉट को बोलना चाहिए?
सिर्फ़ तब, जब बोलने से कुछ ऐसा मिले जो टेक्स्ट नहीं दे सकता। voice या assistant flows के लिए talking लूप उपयोगी है। आम ऑनबोर्डिंग में छोटा टेक्स्ट और एक रिएक्शन ज़्यादा साफ़ रहता है, screen readers के साथ काम करता है और lip-sync का काम बचाता है। दोनों ही हालात में सारे निर्देश असली टेक्स्ट में रखें।
एम्प्टी स्टेट के लिए कौन सा मूड ठीक है?
कोई शांत मूड। "यहाँ अभी कुछ नहीं है" के लिए sleeping या idle ठीक है, और "कुछ नया इंतज़ार कर रहा है" के लिए attention। इसके साथ एक हेडिंग, एक लाइन की व्याख्या और एक मुख्य बटन रखें, और कुछ चक्रों के बाद लूप रोक दें ताकि वह लगातार न चलता रहे।
क्या हर ऑनबोर्डिंग स्टेप के लिए अलग फ़ाइल चाहिए?
नहीं। एक Rive स्टेट मशीन सभी स्टेट एक ही फ़ाइल में रखती है, और आप लूप के लिए एक नंबर और रिएक्शन के लिए ट्रिगर से उनके बीच स्विच करते हैं। इससे डाउनलोड छोटा रहता है, कैरेक्टर सभी स्क्रीन पर एक जैसा रहता है, और स्टेट के बीच ट्रांज़िशन स्मूद रहते हैं क्योंकि वे एक ही फ़ाइल में होते हैं।
अगर मैस्कॉट लोड न हो तो?
स्क्रीन तब भी काम करनी चाहिए। जगह रिज़र्व रखें, स्थिर इमेज दिखाएँ या कुछ भी नहीं, और हर निर्देश व एक्शन सामान्य टेक्स्ट और बटन में रखें। एनिमेशन को एक बेहतरी मानें, कभी निर्भरता नहीं, और पुष्टि के लिए एक बार फ़ाइल को ब्लॉक करके स्क्रीन टेस्ट करें।
इस गाइड से झटपट जवाब
स्रोत
- Launching, Apple Human Interface Guidelines
- Understanding SC 2.2.2: Pause, Stop, Hide, W3C WAI
- React runtime, Rive
- Data binding (web runtime), Rive
- Inputs (Apple runtime, legacy), Rive
- Inputs (Android runtime, legacy), Rive
- Inputs (Flutter runtime, legacy), Rive
- accessibilityReduceMotion, Apple Developer Documentation