Poin-poin utama
Easing (fungsi pelunakan) — fungsi matematika f(t) yang memetakan jalur linear waktu t ∈ [0,1] ke nilai animasi non-linear. Jika animasi mengubah posisi objek dari A ke B dalam 500 ms, easing menentukan bagaimana objek bergerak di antara titik-titik ini pada setiap saat. Easing linear (f(t) = t) berarti kecepatan konstan — objek bergerak secara mekanis. Easing non-linear — alami: objek mempercepat (ease-in), memperlambat (ease-out), atau memiliki awal dan akhir yang halus (ease-in-out).
Fungsi easing digambarkan dengan kurva Bézier kubik (Cubic Bézier), di mana sumbu X adalah waktu yang dinormalisasi dan sumbu Y adalah kemajuan yang dinormalisasi. Dua titik kontrol (P1, P2) menentukan bentuk kurva. Kurva standar ditetapkan oleh spesifikasi 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). Nilai yang sama digunakan dalam CAMediaTimingFunction di iOS dan PathInterpolator di Android. Menurut pedoman Material Design Motion, kurva easing harus sesuai dengan konteks: untuk kemunculan — ease-out (start cepat), untuk penghilangan — ease-in (finish cepat).
Di iOS, pekerjaan utama dengan easing dilakukan melalui kelas CAMediaTimingFunction dari Core Animation. Kelas ini menerima kurva Bézier kubik dalam bentuk dua titik kontrol (c1x, c1y, c2x, c2y) dan diterapkan ke CAAnimation (CABasicAnimation, CAKeyframeAnimation). CAMediaTimingFunction mendukung 5 fungsi yang telah ditentukan: linear, easeIn, easeOut, easeInEaseOut, dan default (setara dengan easeInEaseOut).
CAMediaTimingFunction bekerja pada tingkat CALayer — animasi dijalankan dalam proses terpisah, render server, yang menjamin 60fps bahkan pada transformasi yang kompleks. Untuk animasi properti UIView (frame, alpha, transform), UIKit menggunakan UIView.animate dengan parameter options: .curveEaseInOut, yang secara internal juga membuat CAMediaTimingFunction dengan kurva yang sesuai. Di iOS 17+, telah ditambahkan UIViewAnimationCurve.custom dengan BlockParameters untuk Bézier kustom — ini menghilangkan kebutuhan untuk menulis CAAnimation sendiri. CAMediaTimingFunction juga digunakan di UIKit Dynamics dan UIScrollView untuk deselerasi (UIScrollViewDecelerationRate).
Di SwiftUI, easing didefinisikan melalui struktur Animation dengan modifier .easeIn, .easeOut, .easeInOut, .spring dan .interpolatingSpring. Berbeda dengan UIKit di mana animasi bersifat prosedural (beginAnimations/commitAnimations), SwiftUI menggunakan pendekatan deklaratif: animasi adalah properti status yang berubah dan framework sendiri yang menentukan cara menganimasikan transisi.
Modifier .timingCurve(c0x, c0y, c1x, c1y) menerima langsung titik kontrol Bézier kubik — ini adalah analog lengkap dari CAMediaTimingFunction. SwiftUI Animation mendukung kurva yang telah ditentukan sebagai properti statis: Animation.easeInOut setara dengan ease-in-out (0.42, 0.0, 0.58, 1.0). Untuk animasi pegas, digunakan Animation.spring(response:dampingFraction:blendDuration), di mana dampingFraction < 1 menciptakan efek pegas dengan redaman. Di WWDC 2023, Apple memperkenalkan Animation.keyframes — animasi bingkai demi bingkai dengan easing kustom pada setiap bingkai kunci, yang memberikan kontrol penuh atas lintasan.
Di Android, easing diimplementasikan melalui PathInterpolator (API 21+) — kelas yang menerima objek Path dengan kurva Bézier kubik. Titik kontrol didefinisikan melalui Path.cubicTo(x1, y1, x2, y2, x3, y3), di mana (x1,y1) adalah titik kontrol pertama, (x2,y2) kedua, (x3,y3) titik akhir (selalu 1,1). PathInterpolator wajib jika diperlukan kurva kustom; untuk skenario standar, tersedia AccelerateDecelerateInterpolator (ease-in-out), AccelerateInterpolator (ease-in), dan DecelerateInterpolator (ease-out).
Di Jetpack Compose, easing didefinisikan melalui objek Easing dari paket androidx.compose.animation. Tersedia FastOutSlowInEasing, LinearOutSlowInEasing, FastOutLinearInEasing, serta Easing kustom melalui CubicBezierEasing. Compose Easing diterapkan di animate*AsState, AnimatedVisibility, dan AnimatedContent. Perbedaan utama dari sistem View: Compose menginterpolasi easing di sisi Kotlin (bukan di RenderNode), yang memberikan fleksibilitas lebih untuk animasi kustom, tetapi memerlukan optimasi pada layar 120Hz.
Animasi dasar posisi layer dengan kurva ease-in-out kustom. CAMediaTimingFunction menerima titik kontrol Bézier kubik yang mendefinisikan awal dan akhir gerakan yang halus.
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")
}
Titik kontrol (0.42, 0.0, 0.58, 1.0) mendefinisikan kurva standar ease-in-out. SwiftUI menggunakan titik yang sama untuk Animation.easeInOut. Untuk ease-in, gunakan (0.42, 0.0, 1.0, 1.0), untuk ease-out — (0.0, 0.0, 0.58, 1.0). Core Animation menjalankan animasi di render server dengan frekuensi 60/120 fps.
Animasi deklaratif di SwiftUI dengan kurva kustom dan efek pegas. Modifier animation terikat pada perubahan 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()
}
}
}
}
Modifier .timingCurve(c0x, c0y, c1x, c1y, duration) membuat animasi easing kustom di SwiftUI. Parameter value menghubungkan animasi dengan status tertentu — saat isAnimated berubah, SwiftUI secara otomatis menerapkan kurva. Untuk animasi pegas, gunakan .spring(response: 0.4, dampingFraction: 0.6) sebagai pengganti timingCurve.
Ekuivalen ease-in-out di Android melalui PathInterpolator. Titik kontrol (0.42, 0.0, 0.58, 1.0) mendefinisikan kurva yang sama seperti di 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()
}
}
PathInterpolator dengan titik kontrol (0.42, 0.0, 0.58, 1.0) identik dengan CAMediaTimingFunction ease-in-out di iOS. Untuk proyek lintas platform, gunakan titik kontrol yang sama — ini menjamin perilaku animasi yang identik secara visual. Material Design merekomendasikan FastOutSlowInInterpolator (0.4, 0.0, 0.2, 1.0) sebagai alternatif untuk antarmuka khusus Android.
Di Compose, easing didefinisikan melalui CubicBezierEasing dengan titik kontrol yang sama. Hasilnya — kemunculan elemen yang halus dengan transparansi dan pergeseran.
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)
)
}
}
CubicBezierEasing di Compose menerima 4 parameter titik kontrol yang sama. animateFloatAsState secara otomatis menginterpolasi nilai alpha dengan kurva yang diberikan. Sebagai perbandingan: FastOutSlowInEasing di Compose setara dengan (0.4, 0.0, 0.2, 1.0) — kurva standar Material Design 3. Kurva kustom melalui CubicBezierEasing memberikan kontrol penuh untuk animasi merek.
Pertanyaan yang sering diajukan
Easing — konsep umum fungsi pelunakan, digunakan di iOS (CAMediaTimingFunction), web (CSS ease-in-out) dan desain. Interpolator — implementasi konsep ini di Android (TimeInterpolator). Pada dasarnya ini hal yang sama — kurva matematika kecepatan animasi. Perbedaannya hanya pada nama dan API platform. Dalam proyek lintas platform, istilah easing digunakan sebagai istilah universal.
iOS menyediakan CAMediaTimingFunction dengan 5 fungsi yang telah ditentukan: linear, easeIn, easeOut, easeInEaseOut, dan custom (Bézier kubik). Di SwiftUI tersedia Animation.easeIn, Animation.easeOut, Animation.easeInOut, Animation.spring dan Animation.interpolatingSpring. Untuk kurva kustom, gunakan Animation.timingCurve(c0x, c0y, c1x, c1y, duration:).
Ya, jika Anda mengatur kurva Bézier kubik yang sama. CAMediaTimingFunction di iOS dan PathInterpolator di Android menerima titik kontrol Bézier kubik (x1, y1, x2, y2). Misalnya, kurva ease-in-out (0.42, 0.0, 0.58, 1.0) akan memberikan perilaku yang identik di kedua platform. Material Design menggunakan pendekatan ini untuk animasi lintas platform.
Gunakan pedoman Material Design Motion: untuk kemunculan elemen — ease-out (start cepat, finish halus), untuk penghilangan — ease-in (finish cepat), untuk perpindahan antar layar — ease-in-out. Gunakan animasi pegas untuk elemen interaktif (tombol, kartu). Hindari linear — terlihat tidak alami.
Tersendat (jank) terjadi ketika animasi tidak mencapai 60fps. Periksa: apakah Anda menggunakan CAMediaTimingFunction (bukan timer) di iOS, PathInterpolator (bukan Handler.post) di Android. Perhitungan berat di thread utama, hierarki layer yang kompleks, atau drawable besar dapat menyebabkan hilangnya bingkai. Di iOS, gunakan Core Animation dengan shouldRasterize untuk layer yang kompleks; di Android — Hardware Acceleration dan GPU rendering.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga