कंटेंट पर जाएँ
charmotion

Compose Multiplatform और Ionic/Capacitor में Rive

Charmotion टीम द्वारा · अपडेट:

फ़्रेमवर्क और नो-कोड गाइड का कवर इलस्ट्रेशन: Compose Multiplatform और Ionic/Capacitor में Rive, Charmotion के डेमो कैरेक्टर के साथ

Compose Multiplatform के लिए Rive का कोई आधिकारिक रनटाइम नहीं है। कम्युनिटी का RiveCMP wrapper, जो Rive के docs में लिस्टेड है, rive-android, rive-ios और web runtime को wrap करता है और experimental के रूप में चिह्नित है। Ionic और Capacitor ऐप web code रेंडर करते हैं, इसलिए वे सीधे Rive का आधिकारिक web runtime @rive-app/canvas इस्तेमाल करते हैं। RuntimeLoader.setWasmUrl() के साथ rive.wasm को bundle करें ताकि ऐप offline भी काम करे।

मुख्य बातें

  • RiveCMP कम्युनिटी द्वारा मेंटेन किया जाता है और experimental है; यह Rive का नहीं है।
  • इसके README के अनुसार, iOS पर RiveCMP ट्रांसपेरेंट बैकग्राउंड रेंडर नहीं कर सकता।
  • Capacitor ऐप नेटिव WebView के अंदर स्टैंडर्ड web runtime चलाते हैं।
  • डिफ़ॉल्ट रूप से web runtime rive.wasm को unpkg से लाता है; ऐप offline भी खुल सके, इसके लिए इसे bundle करें।
  • जब किसी प्लेटफ़ॉर्म का wrapper बहुत जोखिम भरा हो, तो ट्रांसपेरेंट वीडियो हर जगह चलता है।

क्या Compose Multiplatform के लिए Rive का आधिकारिक सपोर्ट है?

नहीं। Rive, Android (Jetpack Compose सहित), Apple प्लेटफ़ॉर्म और web के लिए आधिकारिक रनटाइम मेंटेन करता है, लेकिन कोई भी रनटाइम सीधे Compose Multiplatform को टारगेट नहीं करता। Rive के docs में RiveCMP को Angular, C# और Qt के साथ कम्युनिटी रनटाइम में लिस्ट किया गया है, और बताया गया है कि यह Rive के स्वामित्व या मेंटेनेंस वाला प्रोजेक्ट नहीं है।

इससे Kotlin Multiplatform ऐप के लिए तीन विकल्प बचते हैं:

विकल्पMaintainerप्लेटफ़ॉर्मफ़ायदा-नुकसान
RiveCMPCommunityAndroid, iOS, वेबएक Compose API; experimental
expect/actual के पीछे आधिकारिक रनटाइमRiveहर प्लेटफ़ॉर्मज़्यादा glue code; पूरी तरह सपोर्टेड
वीडियो एक्सपोर्टकुछ नहीं चाहिएसभीकोई स्टेट मशीन नहीं

production ऐप के लिए दूसरा विकल्प विचार करने लायक है। common code में Mascot(mood: Int) जैसा एक expect composable डिक्लेयर करें, Android पर इसे आधिकारिक Android रनटाइम से implement करें, और iOS पर Apple रनटाइम के view को UIKitView में wrap करें। आपको थोड़ा ज़्यादा कोड लिखना पड़ता है, लेकिन हर रेंडरिंग पाथ को Rive ही मेंटेन करता है।

RiveCMP क्या है और यह कितना स्थिर है?

RiveCMP, जो GitHub पर muazkadan/Rive-CMP के नाम से पब्लिश है, Compose Multiplatform को तीन आधिकारिक रनटाइम के ऊपर एक ही API देता है: Android पर rive-android, iOS पर rive-ios और web पर @rive-app/canvas. Rive के docs इसे Compose Multiplatform wrapper library बताते हैं और इसका लिंक देते हैं।

इसका README प्रोजेक्ट को experimental कहता है। व्यवहार में इसका मतलब है:

  • releases के बीच APIs बदल सकते हैं, इसलिए version पिन करें और अपग्रेड करने से पहले release notes पढ़ें।
  • हो सकता है कि नीचे के रनटाइम का हर फ़ीचर उपलब्ध न हो। इन पर कुछ बनाने से पहले जाँचें कि आपका version स्टेट मशीन इनपुट और data binding सपोर्ट करता है या नहीं।
  • यह इस बात पर निर्भर है कि एक ही maintainer तीन प्लेटफ़ॉर्म पर Rive के runtime updates के साथ तालमेल बनाए रखे।

prototypes, internal tools या ऐसे ऐप के लिए जिनका Kotlin Multiplatform stack पहले से कुछ जोखिम स्वीकार करता है, यह हर जगह स्क्रीन पर कैरेक्टर लाने का तेज़ तरीका है। पुराने पोस्ट से snippets कॉपी करने के बजाय मौजूदा Gradle coordinates और composable names के लिए README देखें।

निर्णय तालिका: UI फ़ीडबैक के लिए built-in API, आइकन के लिए आइकन इफ़ेक्ट, कैरेक्टर के लिए Rive स्टेट मशीन, मार्केटिंग क्लिप के लिए वीडियो
काम के हिसाब से एनिमेशन का तरीका चुनें।

RiveCMP के साथ iOS पर कौन सी सीमाएँ आ सकती हैं?

मुख्य documented सीमा transparency है। iOS पर RiveCMP नेटिव Rive view को UIKitView के ज़रिए Compose के अंदर होस्ट करता है, और इसका README बताता है कि यह ट्रांसपेरेंट बैकग्राउंड रेंडर नहीं कर सकता। जो मैस्कॉट Android पर आपकी स्क्रीन के बैकग्राउंड के ऊपर तैरता दिखता है, वह iOS पर एक solid box में दिख सकता है।

इससे निपटने के तरीके:

  • कैरेक्टर को किसी solid surface पर रखें, जैसे कोई card, जिसका रंग view के बैकग्राउंड से मेल खाता हो।
  • आर्टबोर्ड को उसके अपने बैकग्राउंड shape के साथ डिज़ाइन करें ताकि box जानबूझकर बनाया गया लगे।
  • iOS पर आधिकारिक Apple runtime के साथ expect/actual तरीका इस्तेमाल करें, और अपने setup में transparency टेस्ट करें।

Interop views भी pure Compose content से अलग व्यवहार करते हैं: वे एक अलग layer में ड्रॉ होते हैं, इसलिए ओवरलैप होने वाले Compose elements, clipping और container के एनिमेशन Android से अलग दिख सकते हैं। सिर्फ़ simulator पर नहीं, असली iPhone पर टेस्ट करें, और उन scrolling lists को जाँचें जहाँ कई मैस्कॉट दिखते हैं।

Ionic या Capacitor ऐप में Rive कैसे इस्तेमाल करें?

web runtime को ठीक वैसे ही इस्तेमाल करें जैसे वेबसाइट पर करते हैं। Capacitor आपके web app को प्लेटफ़ॉर्म के WebView के अंदर चलाता है, इसलिए @rive-app/canvas बिना किसी native plugin के काम करता है, चाहे आपका Ionic ऐप Angular, React या Vue इस्तेमाल करे।

import { Rive } from "@rive-app/canvas";

const r = new Rive({
  src: "/assets/character.riv",
  canvas: document.getElementById("mascot"),
  stateMachine: "CharacterViewModelMachine",
  autoplay: true,
  autoBind: true,
  onLoad: () => {
    r.resizeDrawingSurfaceToCanvas();
    r.viewModelInstance.number("mood").value = 0;    // idle
  },
});

// later, from app events
r.viewModelInstance.number("mood").value = 5;        // loading
r.viewModelInstance.trigger("success").trigger();    // one-shot

// when the page or component is destroyed
r.cleanup();

अपने framework के mount hook (ngAfterViewInit, useEffect या onMounted) में instance बनाएँ और पेज destroy होने पर cleanup() कॉल करें। Ionic पेजों को अपने navigation stack में ज़िंदा रखता है, इसलिए जब कोई पेज view से बाहर जाए तो off-screen मैस्कॉट को r.pause() से रोकें और लौटने पर r.play() चलाएँ। Angular और Vue गाइड में पूरे components दिए गए हैं।

क्या offline Capacitor ऐप के लिए rive.wasm को self-host करना चाहिए?

हाँ। Rive के docs बताते हैं कि web runtime डिफ़ॉल्ट रूप से rive.wasm को unpkg से डाउनलोड करता है। ब्राउज़र में यह आमतौर पर ठीक रहता है; mobile app में इसका मतलब है कि बिना connection के पहली बार खोलने पर मैस्कॉट फ़ेल हो जाता है, और restricted network पर app review करने वाले को खाली जगह दिख सकती है। फ़ाइल को bundle करें और कोई भी instance बनाने से पहले runtime को उसकी ओर पॉइंट करें:

import { RuntimeLoader } from "@rive-app/canvas";
import riveWasmUrl from "@rive-app/canvas/rive.wasm?url";

// Run once, before the first new Rive(...)
RuntimeLoader.setWasmUrl(riveWasmUrl);

Vite-based Ionic प्रोजेक्ट में ?url import wasm को आपके build में कॉपी कर देता है, और npx cap sync उसे ऐप के अंदर शिप करता है। दूसरे bundlers में build के दौरान फ़ाइल को node_modules/@rive-app/canvas/rive.wasm से अपने assets में कॉपी करें। Rive के docs के अनुसार wasm का version इंस्टॉल किए गए @rive-app पैकेज के version से मेल खाना चाहिए, इसलिए इसे हमेशा इंस्टॉल किए गए पैकेज से कॉपी करें, कभी किसी डाउनलोड से नहीं।

.riv को भी bundle करें। Charmotion की फ़ाइलों का साइज़ इसके लिए ठीक है: एक .riv में आपके कैरेक्टर या लोगो से बने सभी 17 एनिमेशन होते हैं, साथ में एक Character view model (0 से 9 तक का mood नंबर और छह ट्रिगर) और legacy CharacterStateMachine इनपुट, और एक web index.html example जो Capacitor WebView में बिना बदलाव के चलता है।

कब वीडियो एक्सपोर्ट cross-platform के लिए ज़्यादा सुरक्षित विकल्प है?

जब एनिमेशन को रिएक्ट करने की ज़रूरत न हो, या जब आपके किसी प्लेटफ़ॉर्म पर कोई भी runtime पाथ भरोसेमंद न हो। वीडियो हर उस जगह नेटिव रूप से चलता है जहाँ Compose Multiplatform और Capacitor चलते हैं, और कोई wrapper मेंटेन नहीं करना पड़ता।

  • स्प्लैश और ऑनबोर्डिंग लूप जो हमेशा एक जैसे चलते हैं।
  • मार्केटिंग स्क्रीन जहाँ फ़ाइल साइज़ से ज़्यादा quality मायने रखती है।
  • ऐसे प्लेटफ़ॉर्म जहाँ आपका Rive पाथ experimental है, feature flag के पीछे फ़ॉलबैक के रूप में।

इसका नुकसान flexibility में है: हर स्टेट एक अलग फ़ाइल होती है, और उनके बीच स्विच करने का मतलब है source बदलना और एक दिखने वाला cut स्वीकार करना। ट्रांसपेरेंट वीडियो के लिए दो encode भी चाहिए (Apple प्लेटफ़ॉर्म के लिए alpha वाला HEVC, बाकी जगह VP9 WebM). फ़ॉर्मेट तुलना में साइज़ और सपोर्ट विस्तार से बताए गए हैं।

एक आम hybrid तरीका है: हर प्लेटफ़ॉर्म पर पहली release में वीडियो, फिर उन प्लेटफ़ॉर्म पर Rive जहाँ आपका runtime पाथ स्थिर साबित हो।

एक कैरेक्टर की दस लूपिंग स्टेट, हर एक 0 से 9 तक के मूड नंबर से चुनी जाती है
एक Charmotion Rive file की दस लूपिंग स्टेट, जिन्हें मूड नंबर इनपुट से चुना जाता है।

Capacitor ऐप में Rive को offline कैसे चलाएँ

  1. रनटाइम इंस्टॉल करें. Ionic या Capacitor प्रोजेक्ट में npm install @rive-app/canvas चलाएँ।
  2. wasm को bundle करें. @rive-app/canvas/rive.wasm?url import करें और instances बनाने से पहले इसे RuntimeLoader.setWasmUrl() को पास करें।
  3. .riv को bundle करें. फ़ाइल को अपने app assets में रखें ताकि वह build के साथ शिप हो।
  4. instance बनाएँ. पेज के mount hook में stateMachine: "CharacterViewModelMachine" और autoBind: true इस्तेमाल करें।
  5. चलाएँ और pause करें. मूड सेट करें और ऐप इवेंट्स से ट्रिगर फ़ायर करें; जब पेज दिखना बंद हो जाए, तो एनिमेशन रोक दें।
  6. Sync करें और ऑफ़लाइन टेस्ट करें. npx cap sync चलाएँ और ऐप को एयरप्लेन मोड में लॉन्च करें।

अक्सर पूछे जाने वाले सवाल

क्या मैं Compose Multiplatform में Rive Android Compose API इस्तेमाल कर सकता हूँ?

सिर्फ़ आपके Android source set में। Rive का Android रनटाइम, उसके Compose सपोर्ट समेत, Android लाइब्रेरीज़ पर निर्भर है, इसलिए common code उसे कॉल नहीं कर सकता। इसे Android वाले actual implementation में इस्तेमाल करें, जो एक expect composable का हिस्सा है, और iOS implementation में Apple रनटाइम इस्तेमाल करें, या फिर RiveCMP wrapper अपनाएँ।

क्या Capacitor WebView में Rive का परफ़ॉर्मेंस अच्छा रहता है?

आधुनिक iOS और Android WebView, WebAssembly और canvas रेंडरिंग अच्छी तरह चलाते हैं, इसलिए एक-दो मैस्कॉट वैसा ही परफ़ॉर्म करते हैं जैसा मोबाइल Safari या Chrome में। जब किसी स्क्रीन पर कई एनिमेशन हों, तो @rive-app/canvas इस्तेमाल करें, और जो पेज Ionic के navigation stack में रखे हैं लेकिन दिख नहीं रहे, उन पर instances को pause कर दें।

क्या नेटिव Rive रेंडरिंग के लिए कोई Capacitor plugin है?

Rive ऐसा कोई plugin पब्लिश नहीं करता, और उसके docs में कोई community Capacitor रनटाइम भी लिस्टेड नहीं है। WebView के अंदर web रनटाइम ही सपोर्टेड तरीका है। अगर किसी स्क्रीन पर आपको पूरी तरह नेटिव रेंडरिंग चाहिए, तो ऐप के उस हिस्से के लिए Rive के आधिकारिक iOS या Android रनटाइम वाला नेटिव view बेहतर रहेगा।

इस गाइड से झटपट जवाब

स्रोत

संबंधित गाइड