অ্যানিমেশন কাস্টমাইজ করা

অনেক অ্যানিমেশন API সাধারণত সেগুলির আচরণ কাস্টমাইজ করার জন্য প্যারামিটার গ্রহণ করে।

AnimationSpec প্যারামিটার দিয়ে অ্যানিমেশন কাস্টমাইজ করা

বেশিরভাগ অ্যানিমেশন API, ডেভেলপারদের একটি ঐচ্ছিক 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-এর মতো অনেক অ্যানিমেশন API ব্যবহার করে।

যেমন, আমরা যদি নিম্নলিখিত অ্যানিমেশনে spring কনফিগারেশন প্রয়োগ করি, যা ব্যবহারকারীর টাচ দ্বারা পরিচালিত হয়, তাহলে অ্যানিমেশনটি চলাকালীন বাধা দিলে, আপনি দেখতে পাবেন যে tween ব্যবহার করলে spring ব্যবহার করার মতো মসৃণভাবে প্রতিক্রিয়া পাওয়া যায় না।

ছবি ৩. tween বনাম spring স্পেক্স সেট করা এবং তা বাধা দেওয়া।

tween-এর সাথে ইজিং কার্ভ ব্যবহার করে শুরু ও শেষের ভ্যালুর মধ্যে অ্যানিমেট করা

tween ইজিং কার্ভ ব্যবহার করে নির্দিষ্ট durationMillis-এর মধ্যে শুরু ও শেষের ভ্যালু অ্যানিমেট করে। tween হল - শব্দের সংক্ষিপ্ত রূপ, কারণ এটি দুটি ভ্যালুর মাঝখানে থাকে।

এছাড়াও, অ্যানিমেশন শুরু হওয়া পিছিয়ে দিতে delayMillis নির্দিষ্ট করতে পারেন।

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

আরও তথ্যের জন্য ইজিং দেখুন।

keyframes-এর মাধ্যমে নির্দিষ্ট সময়ে নির্দিষ্ট ভ্যালু অ্যানিমেট করা

keyframes অ্যানিমেশনের সময়সীমার মধ্যে বিভিন্ন টাইমস্ট্যাম্পে নির্দিষ্ট করা স্ন্যাপশট ভ্যালুর উপর ভিত্তি করে অ্যানিমেট করে। যেকোনও সময়, অ্যানিমেশন ভ্যালু দুটি কীফ্রেম ভ্যালুর মধ্যে ইন্টারপোলেট করা হবে। এইসব কীফ্রেমের প্রত্যেকটির জন্য, ইন্টারপোলেশন কার্ভ নির্ধারণ করতে ইজিং নির্দিষ্ট করা যেতে পারে।

০ মিলিসেকেন্ডে এবং সময়সীমার শেষে ভ্যালু নির্দিষ্ট করা ঐচ্ছিক। আপনি এইসব ভ্যালু নির্দিষ্ট না করলে, অ্যানিমেশনের শুরু ও শেষের ভ্যালু ডিফল্ট হিসেবে সেট হয়ে যায়।

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 মুভমেন্টের জন্য বিশেষভাবে উপযোগী।

নিচের ভিডিওতে keyframes ও keyframesWithSpline-এর মধ্যে পার্থক্য দেখানো হয়েছে। এক্ষেত্রে, একই x, y কোঅর্ডিনেট ব্যবহার করা হয়েছে যা একটি বৃত্তকে অনুসরণ করতে হয়।

keyframes keyframesWithSplines

আপনি দেখতে পাচ্ছেন যে স্প্লাইন-ভিত্তিক কীফ্রেমগুলি পয়েন্টের মধ্যে আরও মসৃণ ট্রানজিশন অফার করে, কারণ সেগুলি আইটেমগুলির মধ্যে মসৃণভাবে অ্যানিমেট করার জন্য বেজিয়ার কার্ভ ব্যবহার করে। প্রিসেট অ্যানিমেশনের জন্য এই স্পেক উপযোগী। তবে, আপনি যদি ব্যবহারকারী-চালিত পয়েন্ট নিয়ে কাজ করেন, তাহলে পয়েন্টগুলির মধ্যে একই ধরনের মসৃণতা পেতে স্প্রিং ব্যবহার করা ভাল, কারণ সেগুলি ইন্টারাপ্ট করা যায়।

repeatable-এর মাধ্যমে কোনও অ্যানিমেশন রিপিট করা

repeatable নির্দিষ্ট ইটারেশন সংখ্যায় না পৌঁছানো পর্যন্ত বারবার সময়সীমা-ভিত্তিক অ্যানিমেশন (যেমন tween বা keyframes) চালায়। অ্যানিমেশনটি শুরু (RepeatMode.Restart) থেকে নাকি শেষ (RepeatMode.Reverse) থেকে আবার শুরু হবে তা নির্দিষ্ট করতে repeatMode প্যারামিটার ব্যবহার করতে পারেন।

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 ব্যবহার করে। এর ফলে অ্যানিমেট করা ভ্যালু ধীরে ধীরে বাড়তে বা কমতে পারে, পরিবর্তে একই হারে চলতে থাকে। ফ্র্যাকশন হল ০ (শুরু) ও ১.০ (শেষ)-এর মধ্যে একটি ভ্যালু যা অ্যানিমেশনের বর্তমান পয়েন্ট নির্দেশ করে।

ইজিং আসলে এমন একটি ফাংশন যা ০ থেকে ১.০-এর মধ্যে ফ্র্যাকশন ভ্যালু নেয় এবং ফ্লোট রিটার্ন করে। ওভারশুট বা আন্ডারশুট বোঝাতে রিটার্ন করা ভ্যালু সীমার বাইরে থাকতে পারে। নিচের কোডের মতো কাস্টম ইজিং তৈরি করা যেতে পারে।

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 ফাংশন আছে যা বেশিরভাগ ব্যবহারের ক্ষেত্রে প্রযোজ্য। আপনার পরিস্থিতি অনুযায়ী কোন ইজিং ব্যবহার করবেন সেই সম্পর্কে আরও তথ্য পেতে স্পিড - মেটেরিয়াল ডিজাইন দেখুন।

AnimationVector-এ কনভার্ট করে এবং থেকে কনভার্ট করে কাস্টম ডেটা টাইপ অ্যানিমেট করা

বেশিরভাগ কম্পোজ অ্যানিমেশন API ডিফল্ট হিসেবে অ্যানিমেশন ভ্যালু হিসেবে Float, Color, Dp এবং অন্যান্য প্রাথমিক ডেটা টাইপ কাজ করে, কিন্তু কখনও কখনও আপনাকে কাস্টম ডেটা সহ অন্যান্য ডেটা টাইপ অ্যানিমেট করতে হতে পারে। অ্যানিমেশনের সময়, কোনও অ্যানিমেটিং ভ্যালুকে AnimationVector হিসেবে দেখানো হয়। ভ্যালুকে সংশ্লিষ্ট TwoWayConverter-এর মাধ্যমে AnimationVector-এ এবং এর বিপরীতভাবে কনভার্ট করা হয় যাতে কোর অ্যানিমেশন সিস্টেম সেগুলিকে একই পদ্ধতিতে ম্যানেজ করতে পারে। যেমন, একটি 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 তৈরি করে API-কে দিতে পারেন। যেমন, আপনি 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"
    )
}

নিচে দেওয়া তালিকায় কিছু বিল্ট-ইন VectorConverters অন্তর্ভুক্ত আছে: