Timeline — βασικές αρχές, διαχείριση χρόνου κινούμενων γραφικών σε εφαρμογές

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-03-02 Χρόνος ανάγνωσης: 8 λεπ
Timeline (χρονογραμμή) — η θεμελιώδης έννοια της κίνησης που καθορίζει πόσο διαρκεί μια κίνηση, με ποια σειρά εκτελούνται τα στάδιά της και πώς ο χρόνος αντιστοιχίζεται στην πρόοδο. Στην ανάπτυξη εφαρμογών για κινητά, το timeline διαχειρίζεται μέσω διάρκειας (duration), καθυστέρησης (delay), επαναλήψεων (repeat) και χρονικών σημάτων. Στο iOS, η χρονογραμμή κίνησης υλοποιείται μέσω CACurrentMediaTime και CAMediaTiming, στο Android — μέσω ValueAnimator και Animator με παραμέτρους duration, startDelay και repeatCount. Σύμφωνα με το Apple Documentation, η ακριβής διαχείριση της χρονογραμμής είναι κρίσιμη για το συγχρονισμό κινήσεων: ο αποσυγχρονισμός ακόμη και 16 ms (ένα καρέ στα 60fps) γίνεται αντιληπτός από το χρήστη ως τραύλισμα. Στην IT Sectr τυποποιήσαμε τη χρήση του timeline μέσω ValueAnimator στο Android και CABasicAnimation με CAMediaTiming στο iOS — αυτό εξασφαλίζει ομοιόμορφη διαχείριση χρόνου σε όλα τα έργα.

Βασικά σημεία

  • Timeline — έννοια διαχείρισης χρόνου κίνησης: duration, delay, repeat, αντιστοίχιση χρόνου σε πρόοδο.
  • CAMediaTiming — πρωτόκολλο iOS Core Animation για διαχείριση timeline: duration, beginTime, repeatCount, speed, timeOffset.
  • ValueAnimator — κεντρική κλάση Android για εργασία με χρονογραμμή κίνησης μέσω duration, startDelay, repeatCount.
  • CACurrentMediaTime — συνάρτηση iOS για λήψη απόλυτου χρόνου σε δευτερόλεπτα, χρησιμοποιείται για συγχρονισμό.
  • TimeInterval — τύπος δεδομένων στο iOS (Double) που αντιπροσωπεύει χρονικό διάστημα για υπολογισμούς κίνησης.

Τι είναι το Timeline;

Timeline — είναι το μοντέλο χρόνου της κίνησης που καθορίζει πότε ξεκινά η κίνηση, πόσο διαρκεί και πώς η πάροδος του χρόνου μετατρέπεται σε αλλαγή της παραμέτρου που κινείται. Σε αντίθεση με την κίνηση καρέ-προς-καρέ (frame-by-frame), όπου κάθε καρέ ορίζεται χειροκίνητα, η κίνηση timeline περιγράφεται από παραμέτρους: duration — συνολική διάρκεια, startDelay — καθυστέρηση πριν την έναρξη, repeatCount — αριθμός επαναλήψεων και timingFunction — καμπύλη ταχύτητας.

Η χρονογραμμή λειτουργεί σε κανονικοποιημένο χώρο [0, 1] — local time ή progress. Η τιμή μηδέν αντιστοιχεί στην αρχή της κίνησης, ένα — στην ολοκλήρωση. Η συνάρτηση easing μετατρέπει τον γραμμικό local time σε πραγματική πρόοδο κίνησης. Αν repeatCount > 1, το timeline επαναφέρεται κυκλικά (RESTART) ή αντιστρέφεται (REVERSE). Στο iOS, το CAMediaTiming προσθέτει παραμέτρους speed (ταχύτητα αναπαραγωγής, >1 επιταχύνει) και timeOffset (μετατόπιση χρονογραμμής). Στο Android, το Animator χρησιμοποιεί setCurrentPlayTime() για άμεσο έλεγχο της θέσης στη χρονογραμμή. Σύμφωνα με το Material Design, κινήσεις μικρότερες από 100 ms δεν γίνονται αντιληπτές ως κίνηση, ενώ μεγαλύτερες από 500 ms αρχίζουν να ενοχλούν. Η βέλτιστη διάρκεια για κινήσεις διεπαφής είναι 200–350 ms.

Timeline στο iOS: CAMediaTiming και CACurrentMediaTime

Στο iOS, η διαχείριση της χρονογραμμής κίνησης γίνεται μέσω του πρωτοκόλλου CAMediaTiming, το οποίο υλοποιούν τα CAAnimation και CALayer. Παρέχει τις ιδιότητες: duration (διάρκεια σε δευτερόλεπτα), beginTime (χρόνος έναρξης σε σχέση με το γονικό timeline), repeatCount (αριθμός επαναλήψεων), repeatDuration (συνολική διάρκεια επαναλήψεων), autoreverses (αυτόματη αντιστροφή), fillMode (συμπεριφορά πριν/μετά την κίνηση), speed (ταχύτητα αναπαραγωγής) και timeOffset (μετατόπιση στη χρονογραμμή).

CACurrentMediaTime() — συνάρτηση που επιστρέφει τον απόλυτο χρόνο σε δευτερόλεπτα από την τελευταία επανεκκίνηση της συσκευής. Χρησιμοποιείται ως βασική χρονική σήμανση για το συγχρονισμό πολλαπλών κινήσεων: ορίστε beginTime = CACurrentMediaTime() + offset για να ξεκινήσετε μια ομάδα κινήσεων με ακριβή καθυστέρηση. Το CAMediaTiming υποστηρίζει επίσης ιεραρχία timeline — το γονικό επίπεδο μπορεί να επιταχύνει/επιβραδύνει όλες τις θυγατρικές κινήσεις μέσω της ιδιότητας speed. Στο UIKit, το UIViewPropertyAnimator (iOS 10+) αφαιρεί την πολυπλοκότητα της χρονογραμμής μέσω των ιδιοτήτων duration, delay και των callback startAnimation/pauseAnimation/stopAnimation. Στο SwiftUI, η δομή Animation παρέχει το duration ως μέρος της προδιαγραφής κίνησης, αλλά ο άμεσος έλεγχος της χρονογραμμής είναι κρυμμένος — για προσαρμοσμένο timeline χρησιμοποιήστε το TimelineView (iOS 15+) με δικό σας scheduler.

Timeline στο Android: Animator και duration

Στο Android, η διαχείριση της χρονογραμμής είναι συγκεντρωμένη στην κλάση Animator και τις υποκλάσεις της (ValueAnimator, ObjectAnimator). Οι κύριες ιδιότητες του timeline: duration (διάρκεια σε χιλιοστά του δευτερολέπτου), startDelay (καθυστέρηση πριν την έναρξη), repeatCount (αριθμός επαναλήψεων), repeatMode (RESTART ή REVERSE). Η μέθοδος setCurrentPlayTime(long) επιτρέπει την κίνηση κατά μήκος της χρονογραμμής σε οποιαδήποτε θέση.

Το ValueAnimator προσθέτει ένα επίπεδο αφαίρεσης: δημιουργεί τιμές από 0 έως 1 (normalized time) βάσει του duration και τις μεταβιβάζει στο TimeInterpolator. Το AnimatorSet επιτρέπει το συνδυασμό πολλαπλών Animator σε μια ενιαία χρονογραμμή με σειριακή (playSequentially) ή παράλληλη (playTogether) εκτέλεση. Στο Jetpack Compose, η χρονογραμμή διαχειρίζεται μέσω AnimationSpec: tween (durationMillis, delayMillis, easing), spring (dampingRatio, stiffness) και keyframes (σημεία στη χρονογραμμή με προσαρμοσμένο easing για κάθε τμήμα). Το Compose AnimatedContent χρησιμοποιεί timeline για transitionSpec — ο προγραμματιστής περιγράφει πώς το περιεχόμενο εμφανίζεται/εξαφανίζεται με χρονικές μετατοπίσεις. Σύμφωνα με το Android Performance, η χρονογραμμή κίνησης πρέπει να είναι πολλαπλάσιο των 16 ms (κύκλος vsync) για 60fps — η λανθασμένη διάρκεια μπορεί να προκαλέσει απώλεια καρέ λόγω αναντιστοιχίας με το ρυθμό ανανέωσης της οθόνης.

Σύνθεση κινήσεων στο χρόνο

Η χρονογραμμή γίνεται ιδιαίτερα σημαντική κατά τη σύνθεση πολλαπλών κινήσεων. Τρία βασικά μοτίβα: καταρράκτης — οι κινήσεις ξεκινούν σειριακά με μετατόπιση (κάθε επόμενη ξεκινά μετά από offset από την προηγούμενη), παράλληλο — όλες οι κινήσεις ξεκινούν ταυτόχρονα με την ίδια χρονογραμμή και stagger — οι κινήσεις ξεκινούν με επικάλυψη (η δεύτερη ξεκινά πριν την ολοκλήρωση της πρώτης).

Στο iOS, ο καταρράκτης υλοποιείται μέσω beginTime κάθε CAAnimation = προηγούμενο beginTime + προηγούμενο duration. Για stagger χρησιμοποιείται CAAnimationGroup με διαφορετικά beginTime στις ένθετες κινήσεις. Στο Android, το AnimatorSet υποστηρίζει playSequentially και playTogether· το stagger δημιουργείται με ρύθμιση startDelay για κάθε Animator. Στο Compose, το AnimatedVisibility με enter/exitTransition χρησιμοποιεί stagger στην παραλλαγή staggerChildren για καταρρακτώδη εμφάνιση στοιχείων λίστας. Στο WWDC και το Google I/O 2024, και οι δύο πλατφόρμες παρουσίασαν εργαλεία οπτικοποίησης χρονογραμμής: Xcode Animations Inspector και Android Studio Animations Timeline — δείχνουν την πραγματική χρονογραμμή και τα χαμένα καρέ σε πραγματικό χρόνο.

Παραδείγματα κώδικα

iOS: CABasicAnimation με CAMediaTiming

Παράδειγμα κίνησης με προσαρμοσμένη χρονογραμμή: καθυστέρηση 0.3 δευτ., διάρκεια 0.6 δευτ., autoreverse και ατελείωτη επανάληψη. Το CAMediaTiming διαχειρίζεται όλες τις χρονικές παραμέτρους.

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 δίνει καθυστέρηση 300 ms. autoreverses = true κάνει την κίνηση να πηγαίνει προς την αντίθετη κατεύθυνση μετά από κάθε κύκλο. repeatCount = .infinity δημιουργεί έναν ατελείωτο βρόχο του εφέ «αναπνοής». speed = 1.0 — κανονική ταχύτητα; επιταχύνετε την κίνηση 2 φορές με τιμή 2.0.

iOS: TimelineView για προσαρμοσμένη χρονογραμμή

Το SwiftUI TimelineView (iOS 15+) παρέχει πρόσβαση στη χρονογραμμή συστήματος για προσαρμοσμένη κίνηση. Η προβολή ενημερώνεται σε κάθε tick του 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 με .periodic scheduler δημιουργεί tick κάθε 0.1 δευτ. Στο closure, το context.date — η τρέχουσα ώρα που μετατρέπεται σε φάση ημιτονοειδούς. Το μέγεθος του κύκλου παλμών με συχνότητα 1 Hz. Το TimelineView είναι ο μόνος τρόπος δημιουργίας κίνησης με δική της χρονογραμμή στο SwiftUI χωρίς Animation API.

Android: ValueAnimator με προσαρμοσμένη χρονογραμμή

ValueAnimator με πλήρη έλεγχο χρονογραμμής: καθυστέρηση, διάρκεια, επανάληψη. Η μέθοδος setCurrentPlayTime επιτρέπει άλματα κατά μήκος της χρονογραμμής.

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 — καθυστέρηση πριν την έναρξη. repeatMode = REVERSE επιστρέφει την κίνηση στην αρχική τιμή. Το animatedFraction δίνει πρόοδο από 0 έως 1 λαμβάνοντας υπόψη το repeatMode. Το addUpdateListener ενεργοποιείται κάθε καρέ (συνήθως 16 ms). Για παύση, χρησιμοποιήστε pause() / resume().

Android: AnimatorSet για σύνθεση timeline

Το AnimatorSet επιτρέπει τη δημιουργία σύνθετων χρονογραμμών από πολλαπλές κινήσεις. Στο παράδειγμα — σειριακή εκτέλεση με επικάλυψη (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 ξεκινά όλες τις κινήσεις παράλληλα, αλλά η καθεμία έχει τη δική της startDelay — αυτό δημιουργεί εφέ stagger: το fadeIn ξεκινά πρώτο (0 ms), το slideUp μετά από 100 ms, το scale μετά από 200 ms. Τελική χρονογραμμή: 0 — 100 — 200 — 600 ms. Για σειριακή εκτέλεση χρησιμοποιήστε playSequentially.

Συχνές ερωτήσεις

Σε τι διαφέρει το Animator από το ValueAnimator στο Android;

Το Animator — αφηρημένη βασική κλάση για όλες τις κινήσεις. Το ValueAnimator είναι η υποκλάση του που κινεί αριθμητικές τιμές χωρίς σύνδεση με αντικείμενο. Το ObjectAnimator (κληρονόμος του ValueAnimator) κινεί μια συγκεκριμένη ιδιότητα αντικειμένου (π.χ. alpha ή translationY). Για timeline, χρησιμοποιήστε το ValueAnimator ως καθολικό χρονοδιακόπτη με callback μέσω addUpdateListener.

Πώς συγχρονίζονται οι κινήσεις σε διαφορετικές συσκευές;

Χρησιμοποιήστε ρολόγια συστήματος (CACurrentMediaTime στο iOS, System.nanoTime στο Android) για τον υπολογισμό προόδου, όχι τον αριθμό καρέ. Για συγχρονισμό δικτύου, εφαρμόστε χρονοδιακόπτη NTP-based με διόρθωση offset. Το iOS υποστηρίζει AVAudioSession για συγχρονισμό χρονογραμμής ήχου-βίντεο με ακρίβεια χιλιοστού του δευτερολέπτου. Αποφύγετε το συγχρονισμό βάσει καρέ — ο ρυθμός καρέ κυμαίνεται από 30 έως 120 fps.

Τι είναι τα startOffset και repeatCount στο Animator;

startOffset — καθυστέρηση πριν την έναρξη της κίνησης σε χιλιοστά του δευτερολέπτου. Χρησιμοποιείται για εφέ καταρράκτη και stagger. repeatCount — αριθμός επαναλήψεων: 0 = χωρίς επανάληψη, ValueAnimator.INFINITE = ατελείωτος βρόχος. Το repeatMode καθορίζει την κατεύθυνση: RESTART (επαναφορά στην αρχή) ή REVERSE (αντίστροφη κίνηση). Στο iOS, το startOffset ονομάζεται beginTime (σε συνδυασμό με CACurrentMediaTime), repeatCount — η ομώνυμη ιδιότητα του CABasicAnimation.

Ποια είναι η βέλτιστη διάρκεια κίνησης;

Το Material Design συνιστά 200–350 ms για κινήσεις διεπαφής. Κινήσεις μικρότερες από 100 ms δεν γίνονται αντιληπτές ως κίνηση, μεγαλύτερες από 500 ms — ενοχλούν. Για είσοδο/έξοδο στοιχείων: 200–300 ms. Για μεταβάσεις μεταξύ οθονών: 300–400 ms. Χρησιμοποιήστε μικρότερες διάρκειες για μικρά στοιχεία (100–200 ms) και μεγαλύτερες για μεγάλα (400–500 ms).

Γιατί η κίνηση τραυλίζει κατά την αναπαραγωγή;

Το τραύλισμα (jank) προκύπτει λόγω: μεγάλων λειτουργιών στο κύριο νήμα (μπλοκάρουν την απόδοση), σύνθετης ιεραρχίας View/Layer με overdraw ή λανθασμένης χρήσης timeline (η διάρκεια δεν είναι πολλαπλάσιο vsync — 16ms για 60fps, 8ms για 120fps). Χρησιμοποιήστε Xcode Instruments Animations ή Android Studio Profiler για ανίχνευση χαμένων καρέ. Στο Compose, εφαρμόστε Modifier.drawWithCache για προσωρινή αποθήκευση σύνθετων σχεδίων.

Σύνοψη

  • Timeline — το μοντέλο χρόνου κίνησης με παραμέτρους duration, startDelay, repeatCount, repeatMode, που καθορίζει την πορεία της κίνησης.
  • Το πρωτόκολλο iOS CAMediaTiming διαχειρίζεται τη χρονογραμμή μέσω duration, beginTime, speed, timeOffset, repeatCount, fillMode.
  • Το Android Animator και ValueAnimator παρέχουν duration, startDelay, repeatCount, repeatMode και setCurrentPlayTime για άμεσο έλεγχο.
  • Το AnimatorSet στο Android και το CAAnimationGroup στο iOS επιτρέπουν το συνδυασμό κινήσεων σε μια ενιαία χρονογραμμή.
  • Το TimelineView στο SwiftUI (iOS 15+) δίνει πρόσβαση στο scheduler συστήματος για προσαρμοσμένες χρονογραμμές χωρίς Animation API.
  • CACurrentMediaTime() στο iOS και System.nanoTime στο Android — βασικές χρονικές σημάνσεις για συγχρονισμό κινήσεων.
  • Βέλτιστη διάρκεια κινήσεων διεπαφής — 200-350 ms σύμφωνα με τις συστάσεις Material Design και HIG.

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης