Timeline — les bases, la gestion du temps d'animation dans les applications

Auteur : IT Sectr Publié le : 2026-03-02 Temps de lecture : 8 min
La Timeline (chronologie) est un concept fondamental d'animation qui détermine la durée d'une animation, l'ordre d'exécution de ses étapes et comment le temps est mappé sur la progression. Dans le développement d'applications mobiles, la chronologie est gérée via la durée (duration), le délai (delay), les répétitions (repeat) et les horodatages. Sous iOS, la chronologie d'animation est implémentée via CACurrentMediaTime et CAMediaTiming, tandis que sous Android, elle utilise ValueAnimator et Animator avec les paramètres duration, startDelay et repeatCount. Selon Apple Documentation, un contrôle précis de la chronologie est d'une importance cruciale pour la synchronisation des animations : une désynchronisation de seulement 16 ms (une image à 60 ips) est perçue par l'utilisateur comme un tremblement. Chez IT Sectr, nous avons standardisé l'utilisation de la chronologie via ValueAnimator sous Android et CABasicAnimation avec CAMediaTiming sous iOS — cela garantit une gestion uniforme du temps dans tous les projets.

Points Clés

  • Timeline — le concept de gestion du temps d'animation : duration, delay, repeat, mappage du temps sur la progression.
  • CAMediaTiming — protocole iOS Core Animation pour la gestion de la chronologie : duration, beginTime, repeatCount, speed, timeOffset.
  • ValueAnimator — la classe centrale Android pour travailler avec la chronologie d'animation via duration, startDelay, repeatCount.
  • CACurrentMediaTime — fonction iOS pour obtenir le temps absolu en secondes, utilisée pour la synchronisation.
  • TimeInterval — un type de données sous iOS (Double) représentant un intervalle de temps pour les calculs d'animation.

Qu’est-ce que la Timeline ?

Timeline est un modèle temporel d'animation qui définit quand une animation commence, combien de temps elle dure et comment la progression du temps est transformée en modifications du paramètre animé. Contrairement à l'animation image par image (frame-by-frame), où chaque image est définie manuellement, l'animation par chronologie est décrite par des paramètres : duration — durée totale, startDelay — délai avant le début, repeatCount — nombre de répétitions, et timingFunction — la courbe de vitesse.

La chronologie opère dans un espace normalisé [0, 1] — temps local ou progression. La valeur zéro correspond au début de l'animation, un à la fin. Une fonction d'easing (lissage) convertit le temps local linéaire en progression réelle de l'animation. Si repeatCount > 1, la chronologie cycle (RESTART) ou s’inverse (REVERSE). Sous iOS, CAMediaTiming ajoute speed (vitesse de lecture, >1 accélère) et timeOffset (décalage de la chronologie). Sous Android, Animator utilise setCurrentPlayTime() pour le contrôle direct de la position sur la chronologie. Selon Material Design, les animations de moins de 100 ms ne sont pas perçues comme des animations, tandis que celles de plus de 500 ms commencent à irriter. La durée optimale pour les animations d'interface est de 200 à 350 ms.

Timeline sous iOS : CAMediaTiming et CACurrentMediaTime

Sous iOS, la gestion de la chronologie d'animation est effectuée via le protocole CAMediaTiming, implémenté par CAAnimation et CALayer. Il fournit les propriétés : duration (en secondes), beginTime (heure de début relative à la chronologie parente), repeatCount (nombre de répétitions), repeatDuration (durée totale des répétitions), autoreverses (inversion automatique), fillMode (comportement avant/après l'animation), speed (vitesse de lecture) et timeOffset (décalage de la chronologie).

CACurrentMediaTime() est une fonction qui renvoie le temps absolu en secondes depuis le dernier redémarrage de l'appareil. Elle est utilisée comme horodatage de base pour synchroniser plusieurs animations : définissez beginTime = CACurrentMediaTime() + offset pour lancer un groupe d'animations avec un délai précis. CAMediaTiming prend également en charge la hiérarchie des chronologies — une couche parent peut accélérer/ralentir toutes les animations enfants via la propriété speed. Dans UIKit, UIViewPropertyAnimator (iOS 10+) abstrait la chronologie via les propriétés duration, delay et les callbacks startAnimation/pauseAnimation/stopAnimation. Dans SwiftUI, la structure Animation fournit duration dans le cadre de la spécification de l'animation, mais le contrôle direct de la chronologie est masqué — pour une chronologie personnalisée, utilisez TimelineView (iOS 15+) avec un scheduler personnalisé.

Timeline sous Android : Animator et duration

Sous Android, la gestion de la chronologie est centralisée dans la classe Animator et ses sous-classes (ValueAnimator, ObjectAnimator). Les principales propriétés de la chronologie sont : duration (en millisecondes), startDelay (délai avant le début), repeatCount (nombre de répétitions), repeatMode (RESTART ou REVERSE). La méthode setCurrentPlayTime(long) permet de naviguer sur la chronologie à n’importe quelle position arbitraire.

ValueAnimator ajoute une couche d'abstraction : il génère des valeurs de 0 à 1 (temps normalisé) basées sur duration et les transmet à TimeInterpolator. AnimatorSet permet de combiner plusieurs Animator en une seule chronologie avec une exécution séquentielle (playSequentially) ou parallèle (playTogether). Dans Jetpack Compose, la chronologie est gérée via AnimationSpec : tween (durationMillis, delayMillis, easing), spring (dampingRatio, stiffness) et keyframes (points sur la chronologie avec easing personnalisé pour chaque segment). Compose AnimatedContent utilise une chronologie pour transitionSpec — le développeur décrit comment le contenu apparaît/disparaît avec des décalages temporels. Selon Android Performance, la chronologie d'animation doit être un multiple de 16 ms (cycle vsync) pour 60 ips — une durée incorrecte peut entraîner des chutes d'images en raison d'une inadéquation avec la fréquence de rafraîchissement de l'écran.

Composition des animations dans le temps

La chronologie devient particulièrement importante lors de la composition de plusieurs animations. Trois modèles de base : cascade — les animations démarrent séquentiellement avec un décalage (chaque suivante commence après un offset de la précédente), parallèle — toutes les animations commencent simultanément avec la même chronologie, et stagger — les animations démarrent avec chevauchement (la seconde commence avant la fin de la première).

Sous iOS, la cascade est implémentée via beginTime de chaque CAAnimation = beginTime précédent + duration précédente. Pour le stagger, CAAnimationGroup est utilisé avec différentes valeurs de beginTime dans les animations imbriquées. Sous Android, AnimatorSet prend en charge playSequentially et playTogether ; le stagger est créé en définissant startDelay pour chaque Animator. Dans Compose, AnimatedVisibility avec enter/exitTransition utilise le stagger dans la variante staggerChildren pour l'apparition en cascade des éléments de liste. À la WWDC et Google I/O 2024, les deux plateformes ont présenté des outils de visualisation de chronologie : Xcode Animations Inspector et Android Studio Animations Timeline — ils montrent la chronologie réelle et les images perdues en temps réel.

Exemples de code

iOS : CABasicAnimation avec CAMediaTiming

Un exemple d'animation avec une chronologie personnalisée : délai de 0,3 s, durée de 0,6 s, inversion automatique et répétition infinie. CAMediaTiming contrôle tous les paramètres temporels.

swift
import UIKit

func breathingAnimation(layer: CALayer) {
    let animation = CABasicAnimation(keyPath: "opacity")
    animation.duration = 0.6
    animation.beginTime = CACurrentMediaTime() + 0.3
    animation.fromValue = 1.0
    animation.toValue = 0.3
    animation.autoreverses = true
    animation.repeatCount = .infinity
    animation.speed = 1.0
    animation.fillMode = .both

    layer.add(animation, forKey: "breathing")
}

beginTime = CACurrentMediaTime() + 0,3 fournit un délai de 300 ms. autoreverses = true fait s’exécuter l’animation en sens inverse après chaque cycle. repeatCount = .infinity crée une boucle infinie de l’effet de « respiration ». speed = 1,0 — vitesse normale ; accélérez l’animation 2x avec une valeur de 2,0.

iOS : TimelineView pour chronologie personnalisée

SwiftUI TimelineView (iOS 15+) fournit un accès à la chronologie système pour une animation personnalisée. La vue se met à jour à chaque tick du scheduler.

swift
import SwiftUI

struct TimelineViewExample: View {
    var body: some View {
        TimelineView(.periodic(from: .now, by: 0.1)) { context in
            let seconds = context.date.timeIntervalSinceReferenceDate
            let phase = sin(seconds * 2 * .pi)

            Circle()
                .fill(Color.blue)
                .frame(width: 60 + 30 * phase)
                .animation(.linear(duration: 0), value: phase)
        }
    }
}

TimelineView avec le scheduler .periodic génère des ticks toutes les 0,1 s. Dans la fermeture, context.date est l’heure actuelle, qui est convertie en une phase d’onde sinusoïdale. La taille du cercle pulse à une fréquence de 1 Hz. TimelineView est le seul moyen de créer une animation avec sa propre chronologie dans SwiftUI sans l’API Animation.

Android : ValueAnimator avec chronologie personnalisée

ValueAnimator avec contrôle complet de la chronologie : délai, durée, répétition. La méthode setCurrentPlayTime permet de sauter le long de la chronologie.

kotlin
import android.animation.ValueAnimator
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.View

fun View.timelineAnimation() {
    ValueAnimator.ofFloat(0f, 1f).apply {
        duration = 400
        startDelay = 200
        repeatCount = 2
        repeatMode = ValueAnimator.REVERSE
        interpolator = AccelerateDecelerateInterpolator()

        addUpdateListener { animator ->
            val progress = animator.animatedFraction
            alpha = progress
            translationX = progress * 100f
        }

        start()
    }
}

startDelay = 200 ms — délai avant le début. repeatMode = REVERSE ramène l’animation à la valeur initiale. animatedFraction donne la progression de 0 à 1 en tenant compte de repeatMode. addUpdateListener se déclenche à chaque image (généralement 16 ms). Utilisez pause() / resume() pour mettre en pause.

Android : AnimatorSet pour la composition de chronologie

AnimatorSet permet de créer des chronologies complexes à partir de plusieurs animations. L’exemple illustre une exécution séquentielle avec chevauchement (stagger).

kotlin
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.view.View

fun View.staggerAnimation() {
    val fadeIn = ObjectAnimator.ofFloat(this, "alpha", 0f, 1f).apply {
        duration = 300
    }
    val slideUp = ObjectAnimator.ofFloat(this, "translationY", 100f, 0f).apply {
        duration = 400
        startDelay = 100
    }
    val scale = ObjectAnimator.ofFloat(this, "scaleX", 0.8f, 1f).apply {
        duration = 250
        startDelay = 200
    }

    AnimatorSet().apply {
        playTogether(fadeIn, slideUp, scale)
        start()
    }
}

playTogether lance toutes les animations en parallèle, mais chacune a son propre startDelay — cela crée un effet de stagger : fadeIn commence en premier (0 ms), slideUp après 100 ms, scale après 200 ms. La chronologie résultante : 0 — 100 — 200 — 600 ms. Pour une exécution séquentielle, utilisez playSequentially.

Questions fréquentes

En quoi Animator diffère-t-il de ValueAnimator sous Android ?

Animator est une classe de base abstraite pour toutes les animations. ValueAnimator est sa sous-classe qui anime des valeurs numériques sans liaison à un objet. ObjectAnimator (une sous-classe de ValueAnimator) anime une propriété spécifique d’un objet (par exemple, alpha ou translationY). Pour la chronologie, utilisez ValueAnimator comme minuteur universel avec un callback via addUpdateListener.

Comment synchroniser des animations sur différents appareils ?

Utilisez les horloges système (CACurrentMediaTime sous iOS, System.nanoTime sous Android) pour calculer la progression, pas le nombre d’images. Pour la synchronisation réseau, utilisez une minuterie basée sur NTP avec correction de décalage. iOS prend en charge AVAudioSession pour la synchronisation de la chronologie audio-vidéo avec une précision milliseconde. Évitez la synchronisation basée sur les images — les fréquences d’images varient de 30 à 120 ips.

Que sont startOffset et repeatCount dans Animator ?

startOffset est le délai avant le début de l’animation en millisecondes. Utilisé pour les effets de cascade et de stagger. repeatCount est le nombre de répétitions : 0 = pas de répétition, ValueAnimator.INFINITE = boucle infinie. repeatMode détermine la direction : RESTART (réinitialisation au début) ou REVERSE (direction inverse). Sous iOS, startOffset est appelé beginTime (en combinaison avec CACurrentMediaTime), repeatCount est la même propriété de CABasicAnimation.

Quelle est la durée d’animation optimale ?

Material Design recommande 200 à 350 ms pour les animations d’interface. Les animations de moins de 100 ms ne sont pas perçues comme des animations, tandis que celles de plus de 500 ms sont irritantes. Pour l’entrée/sortie des éléments : 200 à 300 ms. Pour les transitions entre écrans : 300 à 400 ms. Utilisez des durées plus courtes pour les petits éléments (100 à 200 ms) et plus longues pour les grands éléments (400 à 500 ms).

Pourquoi l’animation tremble-t-elle pendant la lecture ?

Le tremblement (jank) se produit en raison : d’opérations longues sur le thread principal (bloquant le rendu), d’une hiérarchie complexe de View/Layer avec overdraw, ou d’une utilisation incorrecte de la chronologie (durée non multiple de vsync — 16 ms pour 60 ips, 8 ms pour 120 ips). Utilisez Xcode Instruments Animations ou Android Studio Profiler pour détecter les images perdues. Dans Compose, utilisez Modifier.drawWithCache pour mettre en cache les dessins complexes.

Résumé

  • Timeline est un modèle temporel d’animation avec les paramètres duration, startDelay, repeatCount, repeatMode qui définissent le déroulement de l’animation.
  • Le protocole iOS CAMediaTiming gère la chronologie via duration, beginTime, speed, timeOffset, repeatCount, fillMode.
  • Android Animator et ValueAnimator fournissent duration, startDelay, repeatCount, repeatMode et setCurrentPlayTime pour un contrôle direct.
  • AnimatorSet sous Android et CAAnimationGroup sous iOS permettent de combiner des animations en une seule chronologie.
  • TimelineView dans SwiftUI (iOS 15+) donne accès au scheduler système pour des chronologies personnalisées sans l’API Animation.
  • CACurrentMediaTime() sous iOS et System.nanoTime sous Android sont des horodatages de base pour la synchronisation des animations.
  • La durée optimale pour les animations d’interface est de 200 à 350 ms selon les recommandations de Material Design et HIG.

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