Easing : fonctions de lissage dans l'animation mobile

Auteur : IT Sectr Publié le : 2026-03-02 Temps de lecture : 8 min
L'Easing (fonction de lissage) est une courbe mathématique qui détermine la vitesse de changement d'un paramètre d'animation dans le temps. Au lieu d'un mouvement linéaire uniformément accéléré, l'easing simule un comportement physique : un objet peut accélérer (ease-in), décélérer (ease-out) ou faire les deux (ease-in-out). Sous iOS, l'easing est implémenté via la classe CAMediaTimingFunction (Core Animation) et les modificateurs SwiftUI (Animation.easeInOut). Sous Android — via PathInterpolator et TimeInterpolator. Selon la Documentation Développeur Apple, une courbe d'easing correctement sélectionnée réduit le temps d'animation perçu de 20–35 % sans modifier la durée réelle. Chez IT Sectr, nous avons standardisé la courbe ease-in-out (0.42, 0.0, 0.58, 1.0) comme standard d'entreprise pour tous les projets mobiles.

Points clés

  • Easing — une fonction de vitesse d'animation qui imite le mouvement physique : accélération, décélération ou une combinaison.
  • CAMediaTimingFunction — la classe Core Animation iOS avec 5 courbes prédéfinies et Bézier cubique personnalisée.
  • SwiftUI Animation — modificateurs .easeIn, .easeOut, .easeInOut, .spring et .timingCurve pour l'easing déclaratif.
  • PathInterpolator — l'équivalent de l'easing sous Android avec une courbe Bézier cubique via deux points de contrôle.
  • Bézier cubique — un format universel pour spécifier les courbes d'easing, commun à iOS, Android et au web.

Qu'est-ce que l'Easing ?

L'Easing (fonction de lissage) est une fonction mathématique f(t) qui mappe le temps linéaire t ∈ [0,1] à une valeur d'animation non linéaire. Si une animation change la position d'un objet de A à B en 500 ms, l'easing détermine comment l'objet se déplace entre ces points à chaque instant. L'easing linéaire (f(t) = t) signifie une vitesse constante — l'objet se déplace mécaniquement. L'easing non linéaire semble naturel : l'objet accélère (ease-in), décélère (ease-out) ou a un début et une fin fluides (ease-in-out).

Les fonctions d'easing sont décrites par des courbes de Bézier cubiques, où l'axe X est le temps normalisé et l'axe Y est la progression normalisée. Deux points de contrôle (P1, P2) définissent la forme de la courbe. Les courbes standard sont fixées par la spécification 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). Ces mêmes valeurs sont utilisées dans CAMediaTimingFunction sous iOS et PathInterpolator sous Android. Selon les Directives de Mouvement de Material Design, les courbes d'easing doivent correspondre au contexte : pour l'apparition — ease-out (départ rapide), pour la disparition — ease-in (fin rapide).

Easing sous iOS : CAMediaTimingFunction

Sous iOS, l'easing fonctionne principalement via la classe CAMediaTimingFunction de Core Animation. Elle accepte une courbe de Bézier cubique comme deux points de contrôle (c1x, c1y, c2x, c2y) et s'applique à CAAnimation (CABasicAnimation, CAKeyframeAnimation). CAMediaTimingFunction prend en charge 5 fonctions prédéfinies : linear, easeIn, easeOut, easeInEaseOut et default (équivalent à easeInEaseOut).

CAMediaTimingFunction fonctionne au niveau CALayer — l'animation s'exécute dans un processus serveur de rendu séparé, garantissant 60fps même avec des transformations complexes. Pour l'animation des propriétés UIView (frame, alpha, transform), UIKit utilise UIView.animate avec le paramètre options : .curveEaseInOut, qui crée également en interne une CAMediaTimingFunction avec la courbe correspondante. Sous iOS 17+, UIViewAnimationCurve.custom avec BlockParameters pour Bézier personnalisée a été ajouté — cela élimine le besoin d'écrire une CAAnimation personnalisée. CAMediaTimingFunction est également utilisée dans UIKit Dynamics et UIScrollView pour la décélération (UIScrollViewDecelerationRate).

Easing dans SwiftUI

Dans SwiftUI, l'easing est défini via la structure Animation avec les modificateurs .easeIn, .easeOut, .easeInOut, .spring et .interpolatingSpring. Contrairement à UIKit, où l'animation est procédurale (beginAnimations/commitAnimations), SwiftUI utilise une approche déclarative : l'animation est une propriété d'état qui change, et le framework détermine lui-même comment animer la transition.

Le modificateur .timingCurve(c0x, c0y, c1x, c1y) accepte les points de contrôle Bézier cubique directement — c'est un analogue complet de CAMediaTimingFunction. SwiftUI Animation prend en charge les courbes prédéfinies comme propriétés statiques : Animation.easeInOut est équivalent à ease-in-out (0.42, 0.0, 0.58, 1.0). Pour l'animation spring, Animation.spring(response:dampingFraction:blendDuration) est utilisée, où dampingFraction < 1 crée un effet de ressort avec amortissement. À la WWDC 2023, Apple a présenté Animation.keyframes — une animation image par image avec un easing personnalisé sur chaque image clé, offrant un contrôle total sur la trajectoire.

Easing sous Android : PathInterpolator

Sous Android, l'easing est implémenté via PathInterpolator (API 21+) — une classe qui accepte un objet Path avec une courbe Bézier cubique. Les points de contrôle sont spécifiés via Path.cubicTo(x1, y1, x2, y2, x3, y3), où (x1,y1) est le premier point de contrôle, (x2,y2) le second, et (x3,y3) le point final (toujours 1,1). PathInterpolator est obligatoire si une courbe personnalisée est nécessaire ; pour les scénarios standard, AccelerateDecelerateInterpolator (ease-in-out), AccelerateInterpolator (ease-in) et DecelerateInterpolator (ease-out) sont disponibles.

Dans Jetpack Compose, l'easing est défini via l'objet Easing du paquet androidx.compose.animation. FastOutSlowInEasing, LinearOutSlowInEasing, FastOutLinearInEasing sont disponibles, ainsi qu'un Easing personnalisé via CubicBezierEasing. L'Easing Compose est appliqué dans animate*AsState, AnimatedVisibility et AnimatedContent. La différence clé par rapport au système View : Compose interpole l'easing côté Kotlin (pas dans RenderNode), ce qui offre plus de flexibilité pour les animations personnalisées mais nécessite une optimisation sur les écrans 120Hz.

Exemples de code

iOS : CAMediaTimingFunction avec CABasicAnimation

Animation de base de position de couche avec une courbe ease-in-out personnalisée. CAMediaTimingFunction accepte les points de contrôle Bézier cubique qui définissent un début et une fin fluides du mouvement.

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

Les points de contrôle (0.42, 0.0, 0.58, 1.0) définissent la courbe standard ease-in-out. SwiftUI utilise les mêmes points pour Animation.easeInOut. Pour ease-in, utilisez (0.42, 0.0, 1.0, 1.0) ; pour ease-out — (0.0, 0.0, 0.58, 1.0). Core Animation exécute l'animation dans le serveur de rendu à 60/120 fps.

SwiftUI : Easing avec timingCurve

Animation déclarative dans SwiftUI avec une courbe personnalisée et un effet spring. Le modificateur d'animation se lie au changement de 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()
            }
        }
    }
}

Le modificateur .timingCurve(c0x, c0y, c1x, c1y, duration) crée une animation d'easing personnalisée dans SwiftUI. Le paramètre value lie l'animation à un état spécifique — lorsque isAnimated change, SwiftUI applique automatiquement la courbe. Pour l'animation spring, utilisez .spring(response: 0.4, dampingFraction: 0.6) au lieu de timingCurve.

Android : PathInterpolator avec Easing personnalisé

L'équivalent ease-in-out sous Android via PathInterpolator. Les points de contrôle (0.42, 0.0, 0.58, 1.0) définissent la même courbe que sous 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 avec les points de contrôle (0.42, 0.0, 0.58, 1.0) est identique à CAMediaTimingFunction ease-in-out sous iOS. Pour les projets multiplateformes, utilisez les mêmes points de contrôle — cela garantit un comportement d'animation visuellement identique. Material Design recommande FastOutSlowInInterpolator (0.4, 0.0, 0.2, 1.0) comme alternative pour les interfaces spécifiques à Android.

Jetpack Compose : Easing avec CubicBezierEasing

Dans Compose, l'easing est défini via CubicBezierEasing avec les mêmes points de contrôle. Le résultat est une apparition fluide de l'élément avec transparence et décalage.

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 dans Compose accepte les mêmes 4 paramètres de points de contrôle. animateFloatAsState interpole automatiquement la valeur alpha avec la courbe spécifiée. Pour comparaison : FastOutSlowInEasing dans Compose est équivalent à (0.4, 0.0, 0.2, 1.0) — la courbe standard de Material Design 3. Les courbes personnalisées via CubicBezierEasing offrent un contrôle total pour les animations de marque.

Foire aux questions

En quoi l'easing diffère-t-il de l'interpolator ?

L'easing est un concept général de fonction de lissage utilisé sous iOS (CAMediaTimingFunction), sur le web (CSS ease-in-out) et en design. L'interpolator est l'implémentation de ce concept sous Android (TimeInterpolator). Essentiellement, c'est la même chose — une courbe mathématique de vitesse d'animation. La différence réside uniquement dans le nom et l'API de la plateforme. Dans les projets multiplateformes, le terme easing est utilisé comme universel.

Quelles fonctions d'easing sont disponibles sous iOS ?

iOS fournit CAMediaTimingFunction avec 5 fonctions prédéfinies : linear, easeIn, easeOut, easeInEaseOut et custom (Bézier cubique). Dans SwiftUI, Animation.easeIn, Animation.easeOut, Animation.easeInOut, Animation.spring et Animation.interpolatingSpring sont disponibles. Pour les courbes personnalisées, utilisez Animation.timingCurve(c0x, c0y, c1x, c1y, duration:).

Peut-on utiliser la même fonction d'easing sur iOS et Android ?

Oui, si la même courbe Bézier cubique est définie. CAMediaTimingFunction sous iOS et PathInterpolator sous Android acceptent les points de contrôle Bézier cubique (x1, y1, x2, y2). Par exemple, la courbe ease-in-out (0.42, 0.0, 0.58, 1.0) donnera un comportement identique sur les deux plateformes. Material Design utilise cette approche pour les animations multiplateformes.

Comment choisir la bonne courbe d'easing pour mon application ?

Utilisez les Directives de Mouvement de Material Design : pour l'apparition d'éléments — ease-out (départ rapide, fin fluide), pour la disparition — ease-in (fin rapide), pour le mouvement entre écrans — ease-in-out. Utilisez l'animation spring pour les éléments interactifs (boutons, cartes). Évitez le linéaire — il semble contre nature.

Pourquoi mon animation avec easing semble-t-elle saccadée ?

Les saccades (jank) se produisent lorsque l'animation n'atteint pas 60fps. Vérifiez : utilisez-vous CAMediaTimingFunction (pas une minuterie) sous iOS, PathInterpolator (pas Handler.post) sous Android. Des calculs lourds sur le thread principal, une hiérarchie de couches complexe ou un drawable volumineux peuvent entraîner des chutes d'images. Sous iOS, utilisez Core Animation avec shouldRasterize pour les couches complexes ; sous Android — l'accélération matérielle et le rendu GPU.

Résumé

  • L'easing est une fonction de vitesse d'animation qui rend le mouvement naturel grâce à des changements non linéaires de paramètres dans le temps.
  • iOS CAMediaTimingFunction et SwiftUI Animation.timingCurve implémentent l'easing via une courbe Bézier cubique avec deux points de contrôle.
  • Android PathInterpolator et Compose CubicBezierEasing sont des analogues complets d'iOS pour les courbes de lissage personnalisées.
  • Les courbes d'easing multiplateformes sont définies par les mêmes points de contrôle — la base de l'unification des animations.
  • Material Design 3 recommande fast-out-slow-in pour l'apparition, linear-out-slow-in pour la disparition.
  • L'animation spring dans SwiftUI (Animation.spring) et Compose (spring()) crée un effet de ressort physique avec dampingFraction.
  • L'easing linéaire n'est pas recommandé pour les animations d'interface — il semble contre nature et mécanique.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi