Easing: lényege, simítófüggvények a mobil animációban

Szerző: IT Sectr Megjelenés: 2026-03-02 Olvasási idő: 8 perc
Easing (simítófüggvény) — egy matematikai görbe, amely meghatározza az animációs paraméter időbeli változásának sebességét. A lineáris egyenletesen gyorsuló mozgás helyett az easing fizikai viselkedést utánoz: az objektum gyorsulhat (ease-in), lassulhat (ease-out), vagy mindkettőt végezheti (ease-in-out). iOS-ben az easing a CAMediaTimingFunction (Core Animation) osztályon és a SwiftUI módosítókon (Animation.easeInOut) keresztül van implementálva. Android-ban — a PathInterpolator és TimeInterpolator segítségével. A Apple Developer dokumentáció szerint a megfelelően kiválasztott easing görbe az animáció észlelt idejét 20–35%-kal csökkenti a tényleges időtartam megváltoztatása nélkül. Az IT Sectr-nél szabványosítottuk az ease-in-out (0.42, 0.0, 0.58, 1.0) görbét vállalati szabványként minden mobil projekthez.

Főbb pontok

  • Easing — az animáció sebességfüggvénye, amely fizikai mozgást utánoz: gyorsulás, lassulás vagy kombináció.
  • CAMediaTimingFunction — iOS Core Animation osztály 5 előre definiált görbével és egyéni köbös Bézier görbével.
  • SwiftUI Animation — .easeIn, .easeOut, .easeInOut, .spring és .timingCurve módosítók a deklaratív easinghez.
  • PathInterpolator — az easing megfelelője Android-ban köbös Bézier görbével két kontrollponton keresztül.
  • Köbös Bézier — az easing görbe meghatározásának univerzális formátuma, közös iOS, Android és web számára.

Mi az Easing?

Easing (simítófüggvény) — egy f(t) matematikai függvény, amely a t ∈ [0,1] idő lineáris lefutását egy nemlineáris animációs értékre képezi le. Ha egy animáció egy objektum pozícióját A-ról B-re változtatja 500 ms alatt, az easing meghatározza, hogy az objektum hogyan mozog e pontok között minden időpillanatban. A lineáris easing (f(t) = t) állandó sebességet jelent — az objektum mechanikusan mozog. A nemlineáris easing — természetes: az objektum gyorsul (ease-in), lassul (ease-out), vagy sima kezdéssel és véggel rendelkezik (ease-in-out).

Az easing függvényeket köbös Bézier görbékkel (Cubic Bézier) írjuk le, ahol az X tengely a normalizált idő, az Y tengely a normalizált előrehaladás. Két kontrollpont (P1, P2) határozza meg a görbe alakját. A standard görbéket a CSS specifikáció rögzíti: 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). Ugyanezek az értékek használatosak a CAMediaTimingFunction-ben iOS-ben és a PathInterpolator-ban Android-ban. A Material Design Motion irányelvek szerint az easing görbéknek meg kell felelniük a kontextusnak: megjelenéshez — ease-out (gyors kezdés), eltűnéshez — ease-in (gyors befejezés).

Easing iOS-ben: CAMediaTimingFunction

iOS-ben az easinggel való fő munka a CAMediaTimingFunction osztályon keresztül történik a Core Animation-ből. Ez egy köbös Bézier görbét fogad két kontrollpont (c1x, c1y, c2x, c2y) formájában, és alkalmazza a CAAnimation-re (CABasicAnimation, CAKeyframeAnimation). A CAMediaTimingFunction 5 előre definiált függvényt támogat: linear, easeIn, easeOut, easeInEaseOut és default (az easeInEaseOut megfelelője).

A CAMediaTimingFunction a CALayer szintjén működik — az animáció egy külön folyamatban, a render server-ben fut, ami 60fps-t garantál még összetett transzformációk esetén is. Az UIView tulajdonságok (frame, alpha, transform) animálásához az UIKit a UIView.animate-et használja az options: .curveEaseInOut paraméterrel, ami belsőleg szintén létrehoz egy CAMediaTimingFunction-t a megfelelő görbével. iOS 17+-ban hozzáadták a UIViewAnimationCurve.custom-t BlockParameters-szel az egyéni Bézierhez — ez kiküszöböli a saját CAAnimation írásának szükségességét. A CAMediaTimingFunction az UIKit Dynamics-ben és UIScrollView-ben is használatos a lassításhoz (UIScrollViewDecelerationRate).

Easing SwiftUI-ban

SwiftUI-ban az easing a Animation struktúrán keresztül van definiálva .easeIn, .easeOut, .easeInOut, .spring és .interpolatingSpring módosítókkal. Ellentétben az UIKit-kel, ahol az animáció procedurális (beginAnimations/commitAnimations), a SwiftUI deklaratív megközelítést használ: az animáció egy állapot tulajdonság, amely változik, és a keretrendszer maga határozza meg, hogyan animálja az átmenetet.

A .timingCurve(c0x, c0y, c1x, c1y) módosító közvetlenül fogadja a köbös Bézier kontrollpontjait — ez a CAMediaTimingFunction teljes megfelelője. A SwiftUI Animation támogatja az előre definiált görbéket statikus tulajdonságként: az Animation.easeInOut megfelel az ease-in-out (0.42, 0.0, 0.58, 1.0) görbének. Rugó animációhoz az Animation.spring(response:dampingFraction:blendDuration) használatos, ahol a dampingFraction < 1 csillapításos rugóhatást hoz létre. A WWDC 2023-ban az Apple bemutatta az Animation.keyframes-t — képkockánkénti animációt egyéni easinggel minden kulcskockán, ami teljes kontrollt biztosít a pálya felett.

Easing Android-ban: PathInterpolator

Android-ban az easing a PathInterpolator (API 21+) osztályon keresztül van implementálva — ez egy Path objektumot fogad köbös Bézier görbével. A kontrollpontok a Path.cubicTo(x1, y1, x2, y2, x3, y3) segítségével vannak meghatározva, ahol (x1,y1) az első kontrollpont, (x2,y2) a második, (x3,y3) a végpont (mindig 1,1). A PathInterpolator kötelező, ha egyéni görbére van szükség; standard forgatókönyvekhez az AccelerateDecelerateInterpolator (ease-in-out), AccelerateInterpolator (ease-in) és DecelerateInterpolator (ease-out) áll rendelkezésre.

A Jetpack Compose-ban az easing az Easing objektumon keresztül van definiálva az androidx.compose.animation csomagból. Elérhető a FastOutSlowInEasing, LinearOutSlowInEasing, FastOutLinearInEasing, valamint egyéni Easing a CubicBezierEasing segítségével. A Compose Easing az animate*AsState, AnimatedVisibility és AnimatedContent függvényekben alkalmazható. A legfontosabb különbség a View rendszerhez képest: a Compose az easinget a Kotlin oldalon interpolálja (nem a RenderNode-ban), ami nagyobb rugalmasságot biztosít az egyéni animációkhoz, de optimalizálást igényel 120Hz-es kijelzőkön.

Kód példák

iOS: CAMediaTimingFunction CABasicAnimation-nel

Alap animáció a réteg pozíciójához egyéni ease-in-out görbével. A CAMediaTimingFunction a köbös Bézier kontrollpontjait fogadja, amelyek a mozgás sima kezdetét és végét határozzák meg.

swift
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")
}

A (0.42, 0.0, 0.58, 1.0) kontrollpontok a standard ease-in-out görbét határozzák meg. A SwiftUI ugyanezeket a pontokat használja az Animation.easeInOut-hoz. Az ease-in-hez használja a (0.42, 0.0, 1.0, 1.0), az ease-out-hoz — a (0.0, 0.0, 0.58, 1.0) pontokat. A Core Animation a render server-ben hajtja végre az animációt 60/120 fps frekvenciával.

SwiftUI: Easing timingCurve-val

Deklaratív animáció SwiftUI-ban egyéni görbével és rugóhatással. Az animation módosító az isAnimated változásához van kötve.

swift
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()
            }
        }
    }
}

A .timingCurve(c0x, c0y, c1x, c1y, duration) módosító egyéni easing animációt hoz létre SwiftUI-ban. A value paraméter az animációt egy adott állapothoz köti — az isAnimated változásakor a SwiftUI automatikusan alkalmazza a görbét. Rugó animációhoz a timingCurve helyett használja a .spring(response: 0.4, dampingFraction: 0.6) függvényt.

Android: PathInterpolator egyéni easinggel

Az ease-in-out megfelelője Android-ban PathInterpolator segítségével. A (0.42, 0.0, 0.58, 1.0) kontrollpontok ugyanazt a görbét határozzák meg, mint iOS-ben.

kotlin
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()
    }
}

A PathInterpolator a (0.42, 0.0, 0.58, 1.0) kontrollpontokkal megegyezik a CAMediaTimingFunction ease-in-out-val iOS-ben. Platformokon átívelő projektekhez használja ugyanazokat a kontrollpontokat — ez garantálja a vizuálisan azonos animációs viselkedést. A Material Design a FastOutSlowInInterpolator (0.4, 0.0, 0.2, 1.0) ajánlja alternatívaként Android-specifikus felületekhez.

Jetpack Compose: Easing CubicBezierEasinggel

Compose-ban az easing a CubicBezierEasing segítségével van definiálva ugyanazokkal a kontrollpontokkal. Az eredmény — egy elem sima megjelenése átlátszósággal és elmozdulással.

kotlin
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)
        )
    }
}

A CubicBezierEasing Compose-ban ugyanazt a 4 kontrollpont paramétert fogadja. Az animateFloatAsState automatikusan interpolálja az alpha értéket a megadott görbével. Összehasonlításképpen: a FastOutSlowInEasing Compose-ban megfelel a (0.4, 0.0, 0.2, 1.0) görbének — a Material Design 3 standard görbéjének. Az egyéni görbék a CubicBezierEasing segítségével teljes kontrollt biztosítanak a márka animációkhoz.

Gyakran ismételt kérdések

Miben különbözik az easing az interpolatortól?

Az Easing — a simítófüggvény általános fogalma, használatos iOS-ben (CAMediaTimingFunction), weben (CSS ease-in-out) és designban. Az Interpolator — ennek a koncepciónak a megvalósítása Android-ban (TimeInterpolator). Lényegében ugyanaz — az animáció sebességének matematikai görbéje. A különbség csak a névben és a platform API-jában van. Platformokon átívelő projektekben az easing kifejezés univerzálisan használatos.

Milyen easing függvények érhetők el iOS-ben?

Az iOS a CAMediaTimingFunction-t biztosítja 5 előre definiált függvénnyel: linear, easeIn, easeOut, easeInEaseOut és custom (köbös Bézier). SwiftUI-ban elérhetők a Animation.easeIn, Animation.easeOut, Animation.easeInOut, Animation.spring és Animation.interpolatingSpring. Egyéni görbékhez használja az Animation.timingCurve(c0x, c0y, c1x, c1y, duration:) függvényt.

Használhatom ugyanazt az easing függvényt iOS-en és Android-on?

Igen, ha ugyanazt a köbös Bézier görbét állítja be. A CAMediaTimingFunction iOS-ben és a PathInterpolator Android-ban elfogadják a köbös Bézier kontrollpontjait (x1, y1, x2, y2). Például az ease-in-out (0.42, 0.0, 0.58, 1.0) görbe azonos viselkedést fog mutatni mindkét platformon. A Material Design ezt a megközelítést használja platformokon átívelő animációkhoz.

Hogyan válasszam ki a megfelelő easing görbét az alkalmazásomhoz?

Használja a Material Design Motion irányelveit: elemek megjelenéséhez — ease-out (gyors kezdés, sima befejezés), eltűnéséhez — ease-in (gyors befejezés), képernyők közötti mozgáshoz — ease-in-out. Használjon rugó animációt interaktív elemekhez (gombok, kártyák). Kerülje a linear-t — természetellenesnek tűnik.

Miért néz ki rángatózónak az easing animációm?

A rángatózás (jank) akkor fordul elő, amikor az animáció nem éri el a 60fps-t. Ellenőrizze: használja-e a CAMediaTimingFunction-t (nem timert) iOS-ben, PathInterpolator-t (nem Handler.post-t) Android-ban. A fő szálon végzett nehéz számítások, összetett réteghierarchia vagy nagy drawable képkocka kihagyást okozhat. iOS-ben használja a Core Animation-t shouldRasterize-val összetett rétegekhez; Android-ban — Hardware Acceleration-t és GPU renderinget.

Összefoglalás

  • Az Easing az animáció sebességfüggvénye, amely a paraméterek nemlineáris időbeli változásával természetessé teszi a mozgást.
  • Az iOS CAMediaTimingFunction és SwiftUI Animation.timingCurve az easinget köbös Bézier görbén keresztül implementálja két kontrollponttal.
  • Az Android PathInterpolator és Compose CubicBezierEasing — az iOS teljes megfelelői egyéni simító görbékhez.
  • A platformokon átívelő easing görbék azonos kontrollpontokkal vannak meghatározva — az animációk egységesítésének alapja.
  • A Material Design 3 a fast-out-slow-in-t ajánlja megjelenéshez, a linear-out-slow-in-t eltűnéshez.
  • A rugó animáció SwiftUI-ban (Animation.spring) és Compose-ban (spring()) fizikai rugóhatást hoz létre dampingFraction-nel.
  • A lineáris easing nem ajánlott felületi animációkhoz — természetellenesnek és mechanikusnak tűnik.

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is