ऐनिमेशन को पसंद के मुताबिक बनाएं

ज़्यादातर ऐनिमेशन एपीआई, अपने व्यवहार को पसंद के मुताबिक बनाने के लिए पैरामीटर स्वीकार करते हैं.

AnimationSpec पैरामीटर की मदद से ऐनिमेशन को पसंद के मुताबिक बनाना

ज़्यादातर ऐनिमेशन एपीआई, डेवलपर को ऐनिमेशन की खास बातों को पसंद के मुताबिक बनाने की सुविधा देते हैं. इसके लिए, वे AnimationSpec पैरामीटर का इस्तेमाल करते हैं. हालांकि, यह पैरामीटर इस्तेमाल करना ज़रूरी नहीं है.

val alpha: Float by animateFloatAsState(
    targetValue = if (enabled) 1f else 0.5f,
    // Configure the animation duration and easing.
    animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing),
    label = "alpha"
)

अलग-अलग तरह के ऐनिमेशन बनाने के लिए, अलग-अलग तरह के AnimationSpec होते हैं.

spring की मदद से, फ़िज़िक्स पर आधारित ऐनिमेशन बनाना

spring, शुरू और खत्म होने की वैल्यू के बीच फ़िज़िक्स पर आधारित ऐनिमेशन बनाता है. इसमें दो पैरामीटर होते हैं: dampingRatio और stiffness.

dampingRatio से यह तय होता है कि स्प्रिंग कितना उछाल मारेगा. डिफ़ॉल्ट वैल्यू Spring.DampingRatioNoBouncy है.

पहली इमेज. स्प्रिंग के डैंपिंग रेशियो को अलग-अलग सेट करना.

stiffness से यह तय होता है कि स्प्रिंग को आखिरी वैल्यू की ओर कितनी तेज़ी से बढ़ना चाहिए. डिफ़ॉल्ट वैल्यू Spring.StiffnessMedium है.

दूसरी इमेज. स्प्रिंग की स्टिफ़नेस अलग-अलग सेट करना.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = spring(
        dampingRatio = Spring.DampingRatioHighBouncy,
        stiffness = Spring.StiffnessMedium
    ),
    label = "spring spec"
)

spring, अवधि के हिसाब से तय किए गए AnimationSpec टाइप की तुलना में रुकावटों को ज़्यादा आसानी से मैनेज कर सकता है. ऐसा इसलिए, क्योंकि यह ऐनिमेशन के दौरान टारगेट वैल्यू में बदलाव होने पर भी वेलोसिटी को बनाए रखने की गारंटी देता है. spring का इस्तेमाल, कई ऐनिमेशन एपीआई में डिफ़ॉल्ट AnimationSpec के तौर पर किया जाता है. जैसे, animate*AsState और updateTransition.

उदाहरण के लिए, अगर हम उपयोगकर्ता के टच से चलने वाले इस ऐनिमेशन पर spring कॉन्फ़िगरेशन लागू करते हैं, तो ऐनिमेशन के दौरान उसे रोकने पर, आपको दिखेगा कि tween का इस्तेमाल करने पर, ऐनिमेशन उतना स्मूद नहीं दिखता जितना spring का इस्तेमाल करने पर दिखता है.

तीसरी इमेज. ऐनिमेशन के लिए tween बनाम spring स्पेसिफ़िकेशन सेट करना और उसे रोकना.

tween की मदद से, ईज़िंग कर्व के साथ शुरू और खत्म होने वाली वैल्यू के बीच ऐनिमेशन बनाएं

tween, ईज़िंग कर्व का इस्तेमाल करके, तय किए गए durationMillis के दौरान, शुरू और खत्म होने की वैल्यू के बीच ऐनिमेशन करता है. tween, between शब्द का छोटा रूप है. ऐसा इसलिए, क्योंकि यह दो वैल्यू के बीच की वैल्यू दिखाता है.

ऐनिमेशन को शुरू होने में देरी करने के लिए, delayMillis भी तय किया जा सकता है.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = tween(
        durationMillis = 300,
        delayMillis = 50,
        easing = LinearOutSlowInEasing
    ),
    label = "tween delay"
)

ज़्यादा जानकारी के लिए, Easing देखें.

keyframes की मदद से, किसी तय समय पर कुछ खास वैल्यू को ऐनिमेट करना

keyframes, ऐनिमेशन की अवधि में अलग-अलग टाइमस्टैंप पर बताई गई स्नैपशॉट वैल्यू के आधार पर ऐनिमेट होता है. किसी भी समय, ऐनिमेशन की वैल्यू को दो मुख्य फ़्रेम की वैल्यू के बीच इंटरपोलेट किया जाएगा. इनमें से हर कीफ़्रेम के लिए, ईज़िंग तय की जा सकती है. इससे इंटरपोलेशन कर्व तय किया जा सकता है.

0 मि॰से॰ और अवधि के समय पर वैल्यू तय करना ज़रूरी नहीं है. अगर इन वैल्यू को तय नहीं किया जाता है, तो ये वैल्यू डिफ़ॉल्ट रूप से ऐनिमेशन की शुरू और खत्म होने की वैल्यू पर सेट हो जाती हैं.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = keyframes {
        durationMillis = 375
        0.0f at 0 using LinearOutSlowInEasing // for 0-15 ms
        0.2f at 15 using FastOutLinearInEasing // for 15-75 ms
        0.4f at 75 // ms
        0.4f at 225 // ms
    },
    label = "keyframe"
)

keyframesWithSplines की मदद से, मुख्य फ़्रेम के बीच आसानी से ऐनिमेशन बनाएं

अगर आपको ऐसा ऐनिमेशन बनाना है जो वैल्यू के बीच ट्रांज़िशन करते समय, स्मूद कर्व को फ़ॉलो करे, तो keyframes ऐनिमेशन स्पेसिफ़िकेशन के बजाय keyframesWithSplines का इस्तेमाल करें.

val offset by animateOffsetAsState(
    targetValue = Offset(300f, 300f),
    animationSpec = keyframesWithSpline {
        durationMillis = 6000
        Offset(0f, 0f) at 0
        Offset(150f, 200f) atFraction 0.5f
        Offset(0f, 100f) atFraction 0.7f
    }
)

स्प्लैन पर आधारित कीफ़्रेम, स्क्रीन पर आइटम के 2D मूवमेंट के लिए खास तौर पर उपयोगी होते हैं.

यहां दिए गए वीडियो में, एक ही सेट के x, y कोऑर्डिनेट के हिसाब से keyframes और keyframesWithSpline के बीच के अंतर को दिखाया गया है. ये कोऑर्डिनेट, एक सर्कल को फ़ॉलो करने चाहिए.

keyframes keyframesWithSplines

जैसा कि आप देख सकते हैं, स्प्लाइन पर आधारित कीफ़्रेम, पॉइंट के बीच ज़्यादा स्मूद ट्रांज़िशन देते हैं. ऐसा इसलिए, क्योंकि वे आइटम के बीच स्मूद ऐनिमेशन के लिए बेज़ियर कर्व का इस्तेमाल करते हैं. यह स्पेसिफ़िकेशन, पहले से सेट किए गए ऐनिमेशन के लिए काम का है. हालांकि, अगर आपको उपयोगकर्ता के हिसाब से पॉइंट तय करने हैं, तो हमारा सुझाव है कि आप स्प्रिंग का इस्तेमाल करें. इससे पॉइंट के बीच एक जैसा स्मूद ट्रांज़िशन मिलता है, क्योंकि स्प्रिंग को बीच में रोका जा सकता है.

repeatable की मदद से, किसी ऐनिमेशन को दोहराना

repeatable, अवधि के हिसाब से चलने वाले ऐनिमेशन (जैसे कि tween या keyframes) को तब तक बार-बार चलाता है, जब तक कि यह तय की गई पुनरावृति की संख्या तक न पहुंच जाए. repeatMode पैरामीटर का इस्तेमाल करके, यह तय किया जा सकता है कि ऐनिमेशन को शुरू से (RepeatMode.Restart) या आखिर से (RepeatMode.Reverse) दोहराया जाना चाहिए.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = repeatable(
        iterations = 3,
        animation = tween(durationMillis = 300),
        repeatMode = RepeatMode.Reverse
    ),
    label = "repeatable spec"
)

infiniteRepeatable की मदद से, किसी ऐनिमेशन को बार-बार चलाएं

infiniteRepeatable, repeatable की तरह ही होता है. हालांकि, यह कई बार दोहराया जाता है.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = infiniteRepeatable(
        animation = tween(durationMillis = 300),
        repeatMode = RepeatMode.Reverse
    ),
    label = "infinite repeatable"
)

ComposeTestRule का इस्तेमाल करके किए जाने वाले टेस्ट में, infiniteRepeatable का इस्तेमाल करने वाले ऐनिमेशन नहीं चलते हैं. इस कॉम्पोनेंट को, ऐनिमेशन वाली हर वैल्यू की शुरुआती वैल्यू का इस्तेमाल करके रेंडर किया जाएगा.

snap की मदद से, तुरंत आखिरी वैल्यू पर पहुंचना

snap एक खास AnimationSpec है, जो वैल्यू को तुरंत बदलकर आखिरी वैल्यू पर सेट कर देता है. ऐनिमेशन शुरू होने में देरी करने के लिए, delayMillis तय किया जा सकता है.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = snap(delayMillis = 50),
    label = "snap spec"
)

कस्टम ईज़िंग फ़ंक्शन सेट करना

अवधि के आधार पर होने वाली AnimationSpec कार्रवाइयों (जैसे कि tween या keyframes) में, Easing का इस्तेमाल किया जाता है. इससे ऐनिमेशन के फ़्रैक्शन को अडजस्ट किया जाता है. इससे ऐनिमेशन की वैल्यू को एक जैसी स्पीड से मूव करने के बजाय, तेज़ और धीमा किया जा सकता है. फ़्रैक्शन, 0 (शुरुआत) और 1.0 (आखिरी) के बीच की वैल्यू होती है. इससे ऐनिमेशन में मौजूदा पॉइंट का पता चलता है.

ईज़िंग, असल में एक ऐसा फ़ंक्शन है जो 0 और 1.0 के बीच की फ़्रैक्शन वैल्यू लेता है और फ़्लोट दिखाता है. यह ज़रूरी नहीं है कि दिखाई गई वैल्यू, तय सीमा के अंदर ही हो. यह सीमा से ज़्यादा या कम हो सकती है. नीचे दिए गए कोड की तरह, कस्टम ईज़िंग बनाई जा सकती है.

val CustomEasing = Easing { fraction -> fraction * fraction }

@Composable
fun EasingUsage() {
    val value by animateFloatAsState(
        targetValue = 1f,
        animationSpec = tween(
            durationMillis = 300,
            easing = CustomEasing
        ),
        label = "custom easing"
    )
    // ……
}

Compose में कई Easing फ़ंक्शन पहले से मौजूद होते हैं. ये फ़ंक्शन, इस्तेमाल के ज़्यादातर उदाहरणों पर काम करते हैं. अपने इस्तेमाल के हिसाब से, कौनसी ईज़िंग का इस्तेमाल करना है, इस बारे में ज़्यादा जानकारी के लिए, स्पीड - Material Design देखें.

कस्टम डेटा टाइप को AnimationVector में बदलकर और उससे वापस बदलकर ऐनिमेशन बनाएं

ज़्यादातर Compose ऐनिमेशन एपीआई, डिफ़ॉल्ट रूप से ऐनिमेशन वैल्यू के तौर पर Float, Color, Dp, और अन्य बुनियादी डेटा टाइप के साथ काम करते हैं. हालांकि, कभी-कभी आपको अपने कस्टम डेटा टाइप के साथ-साथ अन्य डेटा टाइप को भी ऐनिमेट करने की ज़रूरत होती है. ऐनिमेशन के दौरान, ऐनिमेट की जा रही किसी भी वैल्यू को AnimationVector के तौर पर दिखाया जाता है. वैल्यू को AnimationVector में बदल दिया जाता है और इसके उलट भी किया जाता है. ऐसा TwoWayConverter की मदद से किया जाता है, ताकि कोर ऐनिमेशन सिस्टम उन्हें एक जैसा बना सके. उदाहरण के लिए, Int को AnimationVector1D के तौर पर दिखाया जाता है. इसमें फ़्लोट वैल्यू होती है. Int के लिए TwoWayConverter इस तरह दिखता है:

val IntToVector: TwoWayConverter<Int, AnimationVector1D> =
    TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })

Color में मुख्य रूप से चार वैल्यू होती हैं: लाल, हरा, नीला, और ऐल्फ़ा. इसलिए, Color को AnimationVector4D में बदल दिया जाता है. इसमें चार फ़्लोट वैल्यू होती हैं. इस तरह, ऐनिमेशन में इस्तेमाल किए गए हर डेटा टाइप को उसकी डाइमेंशनलिटी के आधार पर AnimationVector1D, AnimationVector2D, AnimationVector3D या AnimationVector4D में बदल दिया जाता है. इससे ऑब्जेक्ट के अलग-अलग कॉम्पोनेंट को अलग-अलग ऐनिमेट किया जा सकता है. साथ ही, हर कॉम्पोनेंट की वेलोसिटी को ट्रैक किया जा सकता है. बेसिक डेटा टाइप के लिए, बिल्ट-इन कन्वर्टर को Color.VectorConverter या Dp.VectorConverter जैसे कन्वर्टर का इस्तेमाल करके ऐक्सेस किया जा सकता है.

अगर आपको ऐनिमेशन वाली वैल्यू के तौर पर, किसी नए डेटा टाइप के लिए सहायता जोड़नी है, तो अपना खुद का TwoWayConverter बनाएं और उसे एपीआई को दें. उदाहरण के लिए, अपने कस्टम डेटा टाइप को इस तरह ऐनिमेट करने के लिए, animateValueAsState का इस्तेमाल किया जा सकता है:

data class MySize(val width: Dp, val height: Dp)

@Composable
fun MyAnimation(targetSize: MySize) {
    val animSize: MySize by animateValueAsState(
        targetSize,
        TwoWayConverter(
            convertToVector = { size: MySize ->
                // Extract a float value from each of the `Dp` fields.
                AnimationVector2D(size.width.value, size.height.value)
            },
            convertFromVector = { vector: AnimationVector2D ->
                MySize(vector.v1.dp, vector.v2.dp)
            }
        ),
        label = "size"
    )
}

यहां दी गई सूची में, कुछ पहले से मौजूद VectorConverter शामिल हैं: