Easing: essentie, verzachtingsfuncties in mobiele animatie

Auteur: IT Sectr Gepubliceerd: 2026-03-02 Leestijd: 8 min
Easing (verzachtingsfunctie) — een wiskundige curve die de snelheid van verandering van een animatieparameter in de tijd bepaalt. In plaats van lineaire eenparig versnelde beweging imiteert easing fysiek gedrag: een object kan versnellen (ease-in), vertragen (ease-out) of beide doen (ease-in-out). In iOS wordt easing geïmplementeerd via de klasse CAMediaTimingFunction (Core Animation) en SwiftUI-modifiers (Animation.easeInOut). In Android — via PathInterpolator en TimeInterpolator. Volgens Apple Developer-documentatie verkort een goed gekozen easing-curve de waargenomen animatietijd met 20–35% zonder de werkelijke duur te wijzigen. Bij IT Sectr hebben we de ease-in-out-curve (0.42, 0.0, 0.58, 1.0) gestandaardiseerd als bedrijfsstandaard voor alle mobiele projecten.

Belangrijkste punten

  • Easing — de snelheidsfunctie van animatie die fysieke beweging imiteert: versnelling, vertraging of combinatie.
  • CAMediaTimingFunction — iOS Core Animation-klasse met 5 vooraf gedefinieerde curves en aangepaste kubische Bézier.
  • SwiftUI Animation — modifiers .easeIn, .easeOut, .easeInOut, .spring en .timingCurve voor declaratieve easing.
  • PathInterpolator — de analogie van easing in Android met een kubische Bézier-curve via twee controlepunt.
  • Kubische Bézier — het universele formaat voor het definiëren van een easing-curve, gemeenschappelijk voor iOS, Android en web.

Wat is Easing?

Easing (verzachtingsfunctie) — een wiskundige functie f(t) die het lineaire verloop van tijd t ∈ [0,1] afbeeldt op een niet-lineaire animatiewaarde. Als een animatie de positie van een object van A naar B verandert in 500 ms, bepaalt easing hoe het object tussen deze punten beweegt op elk moment. Lineaire easing (f(t) = t) betekent constante snelheid — het object beweegt mechanisch. Niet-lineaire easing — natuurlijk: het object versnelt (ease-in), vertraagt (ease-out) of heeft een vloeiend begin en einde (ease-in-out).

Easing-functies worden beschreven door kubische Bézier-curves (Cubic Bézier), waarbij de X-as de genormaliseerde tijd is en de Y-as de genormaliseerde voortgang. Twee controlepunt (P1, P2) bepalen de vorm van de curve. Standaardcurves zijn vastgelegd door de CSS-specificatie: 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). Deze zelfde waarden worden gebruikt in CAMediaTimingFunction in iOS en PathInterpolator in Android. Volgens Material Design Motion-richtlijnen moeten easing-curves overeenkomen met de context: voor verschijnen — ease-out (snelle start), voor verdwijnen — ease-in (snelle finish).

Easing in iOS: CAMediaTimingFunction

In iOS gebeurt het belangrijkste werk met easing via de klasse CAMediaTimingFunction uit Core Animation. Deze ontvangt een kubische Bézier-curve in de vorm van twee controlepunt (c1x, c1y, c2x, c2y) en wordt toegepast op CAAnimation (CABasicAnimation, CAKeyframeAnimation). CAMediaTimingFunction ondersteunt 5 vooraf gedefinieerde functies: linear, easeIn, easeOut, easeInEaseOut en default (equivalent van easeInEaseOut).

CAMediaTimingFunction werkt op het niveau van CALayer — de animatie wordt uitgevoerd in een apart proces, de render server, wat 60fps garandeert, zelfs bij complexe transformaties. Voor de animatie van UIView-eigenschappen (frame, alpha, transform) gebruikt UIKit UIView.animate met de parameter options: .curveEaseInOut, die intern ook CAMediaTimingFunction met de bijbehorende curve aanmaakt. In iOS 17+ is UIViewAnimationCurve.custom met BlockParameters voor aangepaste Bézier toegevoegd — dit elimineert de noodzaak om een eigen CAAnimation te schrijven. CAMediaTimingFunction wordt ook gebruikt in UIKit Dynamics en UIScrollView voor deceleratie (UIScrollViewDecelerationRate).

Easing in SwiftUI

In SwiftUI wordt easing gedefinieerd via de structuur Animation met modifiers .easeIn, .easeOut, .easeInOut, .spring en .interpolatingSpring. In tegenstelling tot UIKit, waar animatie procedureel is (beginAnimations/commitAnimations), gebruikt SwiftUI een declaratieve benadering: animatie is een toestandseigenschap die verandert en het framework bepaalt zelf hoe de overgang te animeren.

De modifier .timingCurve(c0x, c0y, c1x, c1y) ontvangt rechtstreeks de controlepunt van de kubische Bézier — dit is de volledige analogie van CAMediaTimingFunction. SwiftUI Animation ondersteunt vooraf gedefinieerde curves als statische eigenschappen: Animation.easeInOut is equivalent aan ease-in-out (0.42, 0.0, 0.58, 1.0). Voor veeranimatie wordt Animation.spring(response:dampingFraction:blendDuration) gebruikt, waarbij dampingFraction < 1 een veereffect met demping creëert. Op WWDC 2023 introduceerde Apple Animation.keyframes — frame-voor-frame animatie met aangepaste easing op elk sleutelframe, wat volledige controle over het traject geeft.

Easing in Android: PathInterpolator

In Android wordt easing geïmplementeerd via PathInterpolator (API 21+) — een klasse die een Path-object met een kubische Bézier-curve ontvangt. De controlepunt worden gedefinieerd via Path.cubicTo(x1, y1, x2, y2, x3, y3), waarbij (x1,y1) het eerste controlepunt is, (x2,y2) het tweede en (x3,y3) het eindpunt (altijd 1,1). PathInterpolator is verplicht als een aangepaste curve nodig is; voor standaard scenario's zijn AccelerateDecelerateInterpolator (ease-in-out), AccelerateInterpolator (ease-in) en DecelerateInterpolator (ease-out) beschikbaar.

In Jetpack Compose wordt easing gedefinieerd via het object Easing uit het pakket androidx.compose.animation. FastOutSlowInEasing, LinearOutSlowInEasing, FastOutLinearInEasing en ook aangepaste Easing via CubicBezierEasing zijn beschikbaar. Compose Easing wordt toegepast in animate*AsState, AnimatedVisibility en AnimatedContent. Het belangrijkste verschil met het View-systeem: Compose interpoleert easing aan de Kotlin-kant (niet in RenderNode), wat meer flexibiliteit biedt voor aangepaste animaties, maar optimalisatie vereist bij 120Hz-schermen.

Codevoorbeelden

iOS: CAMediaTimingFunction met CABasicAnimation

Basisanimatie van de laagpositie met een aangepaste ease-in-out-curve. CAMediaTimingFunction ontvangt de controlepunt van de kubische Bézier, die een vloeiend begin en einde van de beweging definiëren.

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

De controlepunt (0.42, 0.0, 0.58, 1.0) definiëren de standaard ease-in-out-curve. SwiftUI gebruikt dezelfde punten voor Animation.easeInOut. Voor ease-in gebruikt u (0.42, 0.0, 1.0, 1.0), voor ease-out — (0.0, 0.0, 0.58, 1.0). Core Animation voert de animatie uit in de render server met een frequentie van 60/120 fps.

SwiftUI: Easing met timingCurve

Declaratieve animatie in SwiftUI met een aangepaste curve en veereffect. De animation-modifier is gekoppeld aan de verandering van isAnimated.

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

De modifier .timingCurve(c0x, c0y, c1x, c1y, duration) creëert een aangepaste easing-animatie in SwiftUI. De parameter value koppelt de animatie aan een specifieke toestand — bij wijziging van isAnimated past SwiftUI automatisch de curve toe. Gebruik voor veeranimatie .spring(response: 0.4, dampingFraction: 0.6) in plaats van timingCurve.

Android: PathInterpolator met aangepaste easing

Equivalent van ease-in-out in Android via PathInterpolator. De controlepunt (0.42, 0.0, 0.58, 1.0) definiëren dezelfde curve als in iOS.

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

PathInterpolator met controlepunt (0.42, 0.0, 0.58, 1.0) is identiek aan CAMediaTimingFunction ease-in-out op iOS. Gebruik voor cross-platform projecten dezelfde controlepunt — dit garandeert visueel identiek animatiegedrag. Material Design beveelt FastOutSlowInInterpolator (0.4, 0.0, 0.2, 1.0) aan als alternatief voor Android-specifieke interfaces.

Jetpack Compose: Easing met CubicBezierEasing

In Compose wordt easing gedefinieerd via CubicBezierEasing met dezelfde controlepunt. Het resultaat — een vloeiende verschijning van een element met transparantie en verschuiving.

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

CubicBezierEasing in Compose ontvangt dezelfde 4 parameters van de controlepunt. animateFloatAsState interpoleert automatisch de alpha-waarde met de gegeven curve. Ter vergelijking: FastOutSlowInEasing in Compose is equivalent aan (0.4, 0.0, 0.2, 1.0) — de standaardcurve van Material Design 3. Aangepaste curves via CubicBezierEasing bieden volledige controle voor merk-animaties.

Veelgestelde vragen

Wat is het verschil tussen easing en interpolator?

Easing — het algemene concept van een verzachtingsfunctie, gebruikt in iOS (CAMediaTimingFunction), web (CSS ease-in-out) en design. Interpolator — de implementatie van dit concept in Android (TimeInterpolator). In wezen is het hetzelfde — een wiskundige curve van animatiesnelheid. Het verschil zit alleen in de naam en het platform-API. In cross-platform projecten wordt de term easing als universeel gebruikt.

Welke easing-functies zijn beschikbaar in iOS?

iOS biedt CAMediaTimingFunction met 5 vooraf gedefinieerde functies: linear, easeIn, easeOut, easeInEaseOut en custom (kubische Bézier). In SwiftUI zijn Animation.easeIn, Animation.easeOut, Animation.easeInOut, Animation.spring en Animation.interpolatingSpring beschikbaar. Gebruik voor aangepaste curves Animation.timingCurve(c0x, c0y, c1x, c1y, duration:).

Kan ik dezelfde easing-functie gebruiken op iOS en Android?

Ja, als u dezelfde kubische Bézier-curve instelt. CAMediaTimingFunction in iOS en PathInterpolator in Android accepteren de controlepunt van de kubische Bézier (x1, y1, x2, y2). Bijvoorbeeld, de curve ease-in-out (0.42, 0.0, 0.58, 1.0) geeft identiek gedrag op beide platforms. Material Design gebruikt deze benadering voor cross-platform animaties.

Hoe kies ik de juiste easing-curve voor mijn applicatie?

Gebruik de Material Design Motion-richtlijnen: voor verschijnen van elementen — ease-out (snelle start, vloeiende finish), voor verdwijnen — ease-in (snelle finish), voor verplaatsing tussen schermen — ease-in-out. Gebruik veeranimatie voor interactieve elementen (knoppen, kaarten). Vermijd linear — het ziet er onnatuurlijk uit.

Waarom ziet mijn animatie met easing er schokkerig uit?

Schokkerigheid (jank) treedt op wanneer de animatie geen 60fps haalt. Controleer: gebruikt u CAMediaTimingFunction (geen timer) in iOS, PathInterpolator (geen Handler.post) in Android. Zware berekeningen in de hoofdthread, complexe laaghiërarchie of een grote drawable kunnen frameverlies veroorzaken. Gebruik in iOS Core Animation met shouldRasterize voor complexe lagen; in Android — Hardware Acceleration en GPU rendering.

Samenvatting

  • Easing — de snelheidsfunctie van animatie die beweging natuurlijk maakt door niet-lineaire verandering van parameters in de tijd.
  • iOS CAMediaTimingFunction en SwiftUI Animation.timingCurve implementeren easing via een kubische Bézier-curve met twee controlepunt.
  • Android PathInterpolator en Compose CubicBezierEasing — volledige analogen van iOS voor aangepaste verzachtingscurves.
  • Cross-platform easing-curves worden gedefinieerd door identieke controlepunt — de basis voor uniformering van animaties.
  • Material Design 3 beveelt fast-out-slow-in aan voor verschijnen, linear-out-slow-in voor verdwijnen.
  • Veeranimatie in SwiftUI (Animation.spring) en Compose (spring()) creëert een fysiek veereffect met dampingFraction.
  • Lineaire easing wordt niet aanbevolen voor interface-animaties — het ziet er onnatuurlijk en mechanisch uit.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook