Timeline — مبانی، مدیریت زمان انیمیشن در برنامه‌ها

نویسنده: IT Sectr منتشر شده: 2026-03-02 زمان مطالعه: 8 دقیقه
Timeline (خط زمانی) — مفهوم بنیادین انیمیشن است که تعیین می‌کند انیمیشن چقدر طول می‌کشد، مراحل آن به چه ترتیبی اجرا می‌شوند و زمان چگونه بر پیشرفت نگاشت می‌شود. در توسعه برنامه‌های موبایل، timeline از طریق مدت (duration)، تأخیر (delay)، تکرار (repeat) و نشانگرهای زمانی مدیریت می‌شود. در iOS، خط زمانی انیمیشن از طریق CACurrentMediaTime و CAMediaTiming پیاده‌سازی شده است، در Android — از طریق ValueAnimator و Animator با پارامترهای duration، startDelay و repeatCount. به گفته مستندات Apple، مدیریت دقیق خط زمانی برای همگام‌سازی انیمیشن‌ها حیاتی است: عدم همگام‌سازی حتی به میزان 16 میلی‌ثانیه (یک فریم در 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 میلی‌ثانیه به‌عنوان انیمیشن درک نمی‌شوند و طولانی‌تر از 500 میلی‌ثانیه — شروع به آزار می‌کنند. مدت بهینه برای انیمیشن‌های رابط کاربری 200–350 میلی‌ثانیه است.

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 میلی‌ثانیه (چرخه vsync) برای 60fps باشد — مدت نادرست می‌تواند باعث افت فریم به دلیل عدم تطابق با نرخ تازه‌سازی صفحه شود.

ترکیب انیمیشن‌ها در زمان

خط زمانی به‌ویژه در ترکیب چندین انیمیشن اهمیت پیدا می‌کند. سه الگوی پایه: آبشاری — انیمیشن‌ها به صورت ترتیبی با جابجایی راه‌اندازی می‌شوند (هر کدام بعدی پس از offset از قبلی شروع می‌شود)، موازی — همه انیمیشن‌ها هم‌زمان با timeline یکسان راه‌اندازی می‌شوند و stagger — انیمیشن‌ها با هم‌پوشانی راه‌اندازی می‌شوند (دومی قبل از پایان اولی شروع می‌شود).

در iOS، آبشار از طریق beginTime هر CAAnimation = beginTime قبلی + duration قبلی پیاده‌سازی می‌شود. برای stagger از CAAnimationGroup با beginTimeهای مختلف در انیمیشن‌های تو در تو استفاده می‌شود. در Android، AnimatorSet از playSequentially و playTogether پشتیبانی می‌کند؛ stagger با تنظیم startDelay برای هر Animator ایجاد می‌شود. در Compose، AnimatedVisibility با enter/exitTransition از stagger در variant staggerChildren برای ظاهر شدن آبشاری عناصر لیست استفاده می‌کند. در WWDC و Google I/O 2024، هر دو پلتفرم ابزارهای تجسم timeline را معرفی کردند: Xcode Animations Inspector و Android Studio Animations Timeline — آنها خط زمانی واقعی و فریم‌های افتاده را در زمان واقعی نشان می‌دهند.

مثال‌های کد

iOS: CABasicAnimation با CAMediaTiming

مثال انیمیشن با timeline سفارشی: تأخیر 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 میلی‌ثانیه می‌دهد. autoreverses = true باعث می‌شود انیمیشن بعد از هر چرخه در جهت مخالف حرکت کند. repeatCount = .infinity یک حلقه بی‌نهایت از اثر "تنفس" ایجاد می‌کند. speed = 1.0 — سرعت عادی؛ انیمیشن را با مقدار 2.0 دو برابر سریع کنید.

iOS: TimelineView برای خط زمانی سفارشی

SwiftUI TimelineView (iOS 15+) به سیستم timeline برای انیمیشن سفارشی دسترسی می‌دهد. نما در هر تیک 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 هر 0.1 ثانیه یک تیک تولید می‌کند. در بسته context.date — زمان جاری است که به فاز سینوسی تبدیل می‌شود. اندازه دایره با فرکانس 1 هرتز نوسان می‌کند. TimelineView تنها راه ایجاد انیمیشن با خط زمانی شخصی در SwiftUI بدون Animation API است.

Android: ValueAnimator با timeline سفارشی

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 میلی‌ثانیه — تأخیر قبل از شروع. repeatMode = REVERSE انیمیشن را به مقدار اولیه برمی‌گرداند. animatedFraction پیشرفت از 0 تا 1 را با در نظر گرفتن repeatMode می‌دهد. addUpdateListener هر فریم (معمولاً 16 میلی‌ثانیه) فراخوانی می‌شود. برای توقف از 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 با تصحیح offset استفاده کنید. iOS از AVAudioSession برای همگام‌سازی timeline صوتی-تصویری با دقت میلی‌ثانیه پشتیبانی می‌کند. از همگام‌سازی بر اساس فریم خودداری کنید — نرخ فریم از 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 میلی‌ثانیه توصیه می‌کند. انیمیشن‌های کوتاه‌تر از 100 میلی‌ثانیه به‌عنوان انیمیشن درک نمی‌شوند، طولانی‌تر از 500 میلی‌ثانیه — آزاردهنده هستند. برای ورود/خروج عناصر: 200–300 میلی‌ثانیه. برای انتقال بین صفحه‌ها: 300–400 میلی‌ثانیه. از مدت‌های کوتاه‌تر برای عناصر کوچک (100–200 میلی‌ثانیه) و طولانی‌تر برای عناصر بزرگ (400–500 میلی‌ثانیه) استفاده کنید.

چرا انیمیشن هنگام پخش لرزش دارد؟

لرزش (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 میلی‌ثانیه طبق توصیه‌های Material Design و HIG.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید