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

অনেক অ্যানিমেশন 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 হিসেবে অনেক অ্যানিমেশন API-এর মাধ্যমে ব্যবহার করা হয়, যেমন animate*AsState এবং updateTransition।

যেমন, ব্যবহারকারীর স্পর্শে চলে এমন নিম্নলিখিত অ্যানিমেশনে আমরা 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"
)

keyframesWithSpline-এর মাধ্যমে কীফ্রেমের মধ্যে মসৃণভাবে অ্যানিমেট করুন

এমন একটি অ্যানিমেশন তৈরি করতে যা মসৃণ কার্ভ অনুসরণ করে, আপনি keyframes অ্যানিমেশন স্পেকের পরিবর্তে keyframesWithSpline ব্যবহার করতে পারেন।

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 keyframesWithSpline

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

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 ব্যবহার করে অ্যানিমেশনের ফ্র্যাকশন অ্যাডজাস্ট করে। এটি অ্যানিমেটিং মানকে ধ্রুবক হারে সরানোর পরিবর্তে গতি বাড়াতে এবং কমাতে দেয়। ভগ্নাংশ হল ০ (শুরু) এবং ১.০ (শেষ) এর মধ্যে একটি মান যা অ্যানিমেশনের বর্তমান পয়েন্ট নির্দেশ করে।

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

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-এ এবং থেকে কনভার্ট করে কাস্টম ডেটার ধরন অ্যানিমেট করুন

বেশিরভাগ Compose অ্যানিমেশন API ডিফল্ট হিসেবে 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 তৈরি করে 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"
    )
}

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