মূল বিষয়
Easing (স্মুথিং ফাংশন) একটি গাণিতিক ফাংশন f(t) যা রৈখিক সময় t ∈ [0,1] কে একটি অ-রৈখিক অ্যানিমেশন মানে ম্যাপ করে। যদি কোনো অ্যানিমেশন 500 ms-এ কোনো বস্তুর অবস্থান A থেকে B-তে পরিবর্তন করে, তাহলে easing নির্ধারণ করে যে বস্তুটি সময়ের প্রতিটি মুহূর্তে এই বিন্দুগুলির মধ্যে কীভাবে চলে। রৈখিক easing (f(t) = t) মানে ধ্রুব গতি — বস্তুটি যান্ত্রিকভাবে চলে। অ-রৈখিক easing স্বাভাবিক মনে হয়: বস্তুটি ত্বরান্বিত হয় (ease-in), মন্দীভূত হয় (ease-out), বা শুরু এবং শেষ মসৃণ হয় (ease-in-out)।
Easing ফাংশনগুলি কিউবিক বেজিয়ার বক্ররেখা দ্বারা বর্ণিত হয়, যেখানে X-অক্ষ হল প্রমিত সময় এবং Y-অক্ষ হল প্রমিত অগ্রগতি। দুটি নিয়ন্ত্রণ বিন্দু (P1, P2) বক্ররেখার আকার নির্ধারণ করে। মানক বক্ররেখাগুলি CSS স্পেসিফিকেশন দ্বারা নির্ধারিত: ease (0.25, 0.1, 0.25, 1.0), ease-in (0.42, 0.0, 1.0, 1.0), ease-out (0.0, 0.0, 0.58, 1.0), ease-in-out (0.42, 0.0, 0.58, 1.0)। এই একই মানগুলি iOS-এ CAMediaTimingFunction এবং Android-এ PathInterpolator-এ ব্যবহৃত হয়। Material Design Motion Guidelines অনুসারে, easing বক্ররেখাগুলি প্রসঙ্গের সাথে মিলিত হওয়া উচিত: উপস্থিতির জন্য — ease-out (দ্রুত শুরু), অদৃশ্যের জন্য — ease-in (দ্রুত শেষ)।
iOS-এ, easing প্রধানত Core Animation-এর CAMediaTimingFunction ক্লাসের মাধ্যমে কাজ করে। এটি দুটি নিয়ন্ত্রণ বিন্দু (c1x, c1y, c2x, c2y) হিসাবে একটি কিউবিক বেজিয়ার বক্ররেখা গ্রহণ করে এবং CAAnimation (CABasicAnimation, CAKeyframeAnimation)-এ প্রয়োগ করে। CAMediaTimingFunction 5টি পূর্বনির্ধারিত ফাংশন সমর্থন করে: linear, easeIn, easeOut, easeInEaseOut, এবং default (easeInEaseOut-এর সমতুল্য)।
CAMediaTimingFunction CALayer স্তরে কাজ করে — অ্যানিমেশনটি একটি পৃথক রেন্ডার সার্ভার প্রক্রিয়ায় চলে, যা জটিল রূপান্তরেও 60fps নিশ্চিত করে। UIView বৈশিষ্ট্য (frame, alpha, transform)-এর অ্যানিমেশনের জন্য, UIKit options প্যারামিটার সহ UIView.animate ব্যবহার করে: .curveEaseInOut, যা অভ্যন্তরীণভাবে সংশ্লিষ্ট বক্ররেখা সহ একটি CAMediaTimingFunction-ও তৈরি করে। iOS 17+-এ, কাস্টম বেজিয়ারের জন্য UIViewAnimationCurve.custom BlockParameters সহ যুক্ত করা হয়েছে — এটি কাস্টম CAAnimation লেখার প্রয়োজনীয়তা দূর করে। CAMediaTimingFunction UIKit Dynamics এবং UIScrollView-এ মন্দন (UIScrollViewDecelerationRate)-এর জন্যও ব্যবহৃত হয়।
SwiftUI-এ, easing Animation কাঠামোর মাধ্যমে মডিফায়ার .easeIn, .easeOut, .easeInOut, .spring এবং .interpolatingSpring-এর সাথে সেট করা হয়। UIKit-এর বিপরীতে, যেখানে অ্যানিমেশন প্রক্রিয়াগত (beginAnimations/commitAnimations), SwiftUI একটি ঘোষণামূলক পদ্ধতি ব্যবহার করে: অ্যানিমেশন একটি অবস্থা বৈশিষ্ট্য যা পরিবর্তিত হয়, এবং ফ্রেমওয়ার্ক নিজেই নির্ধারণ করে কিভাবে রূপান্তরটি অ্যানিমেট করতে হয়।
মডিফায়ার .timingCurve(c0x, c0y, c1x, c1y) সরাসরি কিউবিক বেজিয়ার নিয়ন্ত্রণ বিন্দু গ্রহণ করে — এটি CAMediaTimingFunction-এর একটি সম্পূর্ণ অনুরূপ। SwiftUI Animation পূর্বনির্ধারিত বক্ররেখাগুলিকে স্থিত বৈশিষ্ট্য হিসাবে সমর্থন করে: Animation.easeInOut ease-in-out (0.42, 0.0, 0.58, 1.0)-এর সমতুল্য। স্প্রিং অ্যানিমেশনের জন্য, Animation.spring(response:dampingFraction:blendDuration) ব্যবহার করা হয়, যেখানে dampingFraction < 1 ড্যাম্পিং সহ একটি স্প্রিং প্রভাব তৈরি করে। WWDC 2023-এ, Apple Animation.keyframes উপস্থাপন করেছে — প্রতিটি কীফ্রেমে কাস্টম easing সহ ফ্রেম-বাই-ফ্রেম অ্যানিমেশন, যা ট্রাজেক্টোরির ওপর সম্পূর্ণ নিয়ন্ত্রণ দেয়।
Android-এ, easing PathInterpolator (API 21+)-এর মাধ্যমে বাস্তবায়িত হয় — একটি ক্লাস যা কিউবিক বেজিয়ার বক্ররেখা সহ একটি Path অবজেক্ট গ্রহণ করে। নিয়ন্ত্রণ বিন্দুগুলি Path.cubicTo(x1, y1, x2, y2, x3, y3)-এর মাধ্যমে নির্দিষ্ট করা হয়, যেখানে (x1,y1) প্রথম নিয়ন্ত্রণ বিন্দু, (x2,y2) দ্বিতীয়, এবং (x3,y3) শেষ বিন্দু (সর্বদা 1,1)। কাস্টম বক্ররেখার প্রয়োজন হলে PathInterpolator বাধ্যতামূলক; মানক পরিস্থিতির জন্য, AccelerateDecelerateInterpolator (ease-in-out), AccelerateInterpolator (ease-in), এবং DecelerateInterpolator (ease-out) উপলব্ধ।
Jetpack Compose-এ, easing androidx.compose.animation প্যাকেজ থেকে Easing অবজেক্টের মাধ্যমে সেট করা হয়। FastOutSlowInEasing, LinearOutSlowInEasing, FastOutLinearInEasing, পাশাপাশি CubicBezierEasing-এর মাধ্যমে কাস্টম Easing উপলব্ধ। Compose Easing animate*AsState, AnimatedVisibility এবং AnimatedContent-এ প্রয়োগ করা হয়। View সিস্টেম থেকে মূল পার্থক্য: Compose Kotlin পাশে easing ইন্টারপোলেট করে (RenderNode-তে নয়), যা কাস্টম অ্যানিমেশনের জন্য আরও নমনীয়তা দেয় কিন্তু 120Hz ডিসপ্লেতে অপ্টিমাইজেশন প্রয়োজন।
একটি কাস্টম ease-in-out বক্ররেখা সহ মৌলিক লেয়ার অবস্থান অ্যানিমেশন। CAMediaTimingFunction কিউবিক বেজিয়ার নিয়ন্ত্রণ বিন্দু গ্রহণ করে যা গতির মসৃণ শুরু এবং শেষ নির্ধারণ করে।
import UIKit
func animateLayerPosition() {
let animation = CABasicAnimation(keyPath: "position")
animation.fromValue = CGPoint(x: 0, y: 0)
animation.toValue = CGPoint(x: 300, y: 400)
animation.duration = 0.8
let easing = CAMediaTimingFunction(
controlPoints: 0.42, 0.0, 0.58, 1.0
)
animation.timingFunction = easing
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
layer.add(animation, forKey: "positionAnimation")
}
নিয়ন্ত্রণ বিন্দু (0.42, 0.0, 0.58, 1.0) মানক ease-in-out বক্ররেখা নির্ধারণ করে। SwiftUI Animation.easeInOut-এর জন্য একই বিন্দু ব্যবহার করে। ease-in-এর জন্য, (0.42, 0.0, 1.0, 1.0) ব্যবহার করুন; ease-out-এর জন্য — (0.0, 0.0, 0.58, 1.0)। Core Animation রেন্ডার সার্ভারে 60/120 fps-এ অ্যানিমেশন কার্যকর করে।
কাস্টম বক্ররেখা এবং স্প্রিং প্রভাব সহ SwiftUI-তে ঘোষণামূলক অ্যানিমেশন। অ্যানিমেশন মডিফায়ার isAnimated পরিবর্তনের সাথে বাঁধা।
import SwiftUI
struct EasingExampleView: View {
@State private var isAnimated = false
var body: some View {
VStack {
Circle()
.fill(Color.blue)
.frame(width: 60, height: 60)
.offset(x: isAnimated ? 100 : 0, y: 0)
.animation(
.timingCurve(0.42, 0.0, 0.58, 1.0, duration: 0.6),
value: isAnimated
)
Button("Toggle") {
isAnimated.toggle()
}
}
}
}
মডিফায়ার .timingCurve(c0x, c0y, c1x, c1y, duration) SwiftUI-তে একটি কাস্টম easing অ্যানিমেশন তৈরি করে। প্যারামিটার value অ্যানিমেশনটিকে একটি নির্দিষ্ট অবস্থার সাথে বাঁধে — যখন isAnimated পরিবর্তিত হয়, SwiftUI স্বয়ংক্রিয়ভাবে বক্ররেখা প্রয়োগ করে। স্প্রিং অ্যানিমেশনের জন্য, timingCurve-এর পরিবর্তে .spring(response: 0.4, dampingFraction: 0.6) ব্যবহার করুন।
PathInterpolator-এর মাধ্যমে Android-এ ease-in-out সমতুল্য। নিয়ন্ত্রণ বিন্দু (0.42, 0.0, 0.58, 1.0) iOS-এর মতো একই বক্ররেখা নির্ধারণ করে।
import android.animation.ObjectAnimator
import android.graphics.Path
import android.view.animation.PathInterpolator
import android.view.View
fun View.fadeInWithEase() {
val path = Path().apply {
cubicTo(0.42f, 0.0f, 0.58f, 1.0f, 1.0f, 1.0f)
}
val interpolator = PathInterpolator(path)
ObjectAnimator.ofFloat(this, "alpha", 0f, 1f).apply {
duration = 500
interpolator = interpolator
start()
}
}
নিয়ন্ত্রণ বিন্দু (0.42, 0.0, 0.58, 1.0) সহ PathInterpolator iOS-এ CAMediaTimingFunction ease-in-out-এর অনুরূপ। ক্রস-প্ল্যাটফর্ম প্রকল্পগুলির জন্য, একই নিয়ন্ত্রণ বিন্দু ব্যবহার করুন — এটি দৃশ্যত অভিন্ন অ্যানিমেশন আচরণ নিশ্চিত করে। Material Design Android-নির্দিষ্ট ইন্টারফেসের জন্য বিকল্প হিসাবে FastOutSlowInInterpolator (0.4, 0.0, 0.2, 1.0) সুপারিশ করে।
Compose-এ, easing একই নিয়ন্ত্রণ বিন্দু সহ CubicBezierEasing-এর মাধ্যমে সেট করা হয়। ফলাফল হল স্বচ্ছতা এবং অফসেট সহ একটি মসৃণ উপাদান উপস্থিতি।
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.CubicBezierEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
@Composable
fun EasingComposable() {
var visible by remember { mutableStateOf(false) }
val easing = CubicBezierEasing(0.42f, 0.0f, 0.58f, 1.0f)
val alpha by animateFloatAsState(
targetValue = if (visible) 1f else 0f,
animationSpec = tween(durationMillis = 500, easing = easing)
)
Column {
Button(onClick = { visible = !visible }) {
Text("Toggle")
}
Box(
modifier = Modifier
.size(100.dp)
.graphicsLayer(alpha = alpha)
.background(MaterialTheme.colorScheme.primary)
)
}
}
Compose-এ CubicBezierEasing একই 4টি নিয়ন্ত্রণ বিন্দু প্যারামিটার গ্রহণ করে। animateFloatAsState নির্দিষ্ট বক্ররেখার সাথে alpha মান স্বয়ংক্রিয়ভাবে ইন্টারপোলেট করে। তুলনার জন্য: Compose-এ FastOutSlowInEasing (0.4, 0.0, 0.2, 1.0)-এর সমতুল্য — মানক Material Design 3 বক্ররেখা। CubicBezierEasing-এর মাধ্যমে কাস্টম বক্ররেখা ব্র্যান্ডেড অ্যানিমেশনের জন্য সম্পূর্ণ নিয়ন্ত্রণ দেয়।
সচরাচর জিজ্ঞাসা
Easing হল iOS (CAMediaTimingFunction), ওয়েব (CSS ease-in-out) এবং ডিজাইনে ব্যবহৃত স্মুথিং ফাংশনের একটি সাধারণ ধারণা। Interpolator হল Android (TimeInterpolator)-এ এই ধারণার বাস্তবায়ন। সারমর্মে এগুলি একই জিনিস — অ্যানিমেশন গতির একটি গাণিতিক বক্ররেখা। পার্থক্য শুধুমাত্র নাম এবং প্ল্যাটফর্ম API-তে। ক্রস-প্ল্যাটফর্ম প্রকল্পগুলিতে, easing শব্দটি সার্বজনীন হিসাবে ব্যবহৃত হয়।
iOS 5টি পূর্বনির্ধারিত ফাংশন সহ CAMediaTimingFunction প্রদান করে: linear, easeIn, easeOut, easeInEaseOut, এবং custom (কিউবিক বেজিয়ার)। SwiftUI-তে Animation.easeIn, Animation.easeOut, Animation.easeInOut, Animation.spring এবং Animation.interpolatingSpring উপলব্ধ। কাস্টম বক্ররেখার জন্য, Animation.timingCurve(c0x, c0y, c1x, c1y, duration:) ব্যবহার করুন।
হ্যাঁ, যদি একই কিউবিক বেজিয়ার বক্ররেখা সেট করা হয়। iOS-এ CAMediaTimingFunction এবং Android-এ PathInterpolator কিউবিক বেজিয়ার নিয়ন্ত্রণ বিন্দু (x1, y1, x2, y2) গ্রহণ করে। উদাহরণস্বরূপ, ease-in-out (0.42, 0.0, 0.58, 1.0) বক্ররেখা উভয় প্ল্যাটফর্মে অভিন্ন আচরণ দেবে। Material Design ক্রস-প্ল্যাটফর্ম অ্যানিমেশনের জন্য এই পদ্ধতি ব্যবহার করে।
Material Design Motion Guidelines ব্যবহার করুন: উপাদান উপস্থিতির জন্য — ease-out (দ্রুত শুরু, মসৃণ শেষ), অদৃশ্যের জন্য — ease-in (দ্রুত শেষ), স্ক্রিনের মধ্যে চলাচলের জন্য — ease-in-out। ইন্টারঅ্যাকটিভ উপাদানের (বাটন, কার্ড) জন্য স্প্রিং অ্যানিমেশন ব্যবহার করুন। linear এড়িয়ে চলুন — এটি অপ্রাকৃতিক দেখায়।
ঝাঁকুনি (jank) ঘটে যখন অ্যানিমেশন 60fps-এ পৌঁছাতে পারে না। পরীক্ষা করুন: আপনি কি iOS-এ CAMediaTimingFunction (টাইমার নয়) ব্যবহার করছেন, Android-এ PathInterpolator (Handler.post নয়)। মূল থ্রেডে ভারী গণনা, জটিল লেয়ার হায়ারার্কি, বা বড় drawable ফ্রেম ড্রপের কারণ হতে পারে। iOS-এ, জটিল লেয়ারের জন্য shouldRasterize সহ Core Animation ব্যবহার করুন; Android-এ — Hardware Acceleration এবং GPU রেন্ডারিং।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন