Core Animation: مبانی، CALayer و انیمیشن در iOS

نویسنده: IT Sectr منتشر شده: 2026-03-01 زمان مطالعه: 8 دقیقه

Core Animation یک فریم‌ورک انیمیشن سطح پایین اپل است که در سطح CALayer کار می‌کند و رندر کردن محتوا را روی GPU تضمین می‌کند. Core Animation اساس تمام انیمیشن‌های iOS و macOS است: UIKit، AppKit، SceneKit و SpriteKit بر روی آن ساخته شده‌اند. این مقاله معماری CALayer، CABasicAnimation، CATransaction و تکنیک‌های عملی را توضیح می‌دهد.

نکات کلیدی

  • CALayer کلاس پایه Core Animation برای مدیریت نمایش محتوا روی GPU
  • CABasicAnimation انیمیشن ساده یک ویژگی CALayer از fromValue تا toValue
  • CATransaction گروه‌بندی انیمیشن‌ها در یک تراکنش با duration و completion مشترک
  • CAAnimation کلاس پایه انتزاعی که CABasicAnimation، CAKeyframeAnimation، CAAnimationGroup از آن ارث می‌برند
  • Render server فرآیند جداگانه (backboardd) که فریم‌های انیمیشن را روی GPU درون‌یابی می‌کند

Core Animation چیست؟

Core Animation یک فریم‌ورک گرافیکی اپل است که در Mac OS X 10.5 Leopard (2007) ظاهر شد و از اولین نسخه iPhone OS (2007) به iOS منتقل شد. Core Animation ترکیب، انیمیشن و رندر لایه‌ها (CALayer) را روی GPU مدیریت می‌کند. هر UIView در iOS یک CALayer داخلی دارد (view.layer) که تمام رندر از طریق آن انجام می‌شود.

Core Animation بر اساس اصل implicit animation کار می‌کند: برخی تغییرات ویژگی‌های CALayer به طور خودکار انیمیشن می‌شوند (CABasicAnimation را برای position، bounds، opacity، backgroundColor انیمیشن می‌کند). implicit-انیمیشن‌ها به طور پیش‌فرض از CATransaction با مدت 0.25 ثانیه و منحنی easeInOut استفاده می‌کنند.

بر اساس داده‌های Apple WWDC 2024، Core Animation تا 120 FPS روی دستگاه‌های ProMotion پردازش می‌کند و از Metal برای رندر GPU استفاده می‌کند. اندازه یک لایه معمولی در حافظه 4 بایت بر پیکسل (RGBA) + سربار ~100 بایت بر لایه است. برای 60 FPS پایدار بیش از 1000 لایه روی صفحه توصیه نمی‌شود.

معماری CALayer

CALayer اساس Core Animation است. هر CALayer حاوی محتوای بیت‌مپ (یا ارجاع به بافت GPU) است و هندسه (bounds، position، anchorPoint، transform، cornerRadius، borderWidth، shadow) را تعریف می‌کند. لایه رویدادهای لمسی را پردازش نمی‌کند UIView/UIScrollView مسئول این کار است. لایه‌ها سلسله‌مراتبی (layer tree) تشکیل می‌دهند که نمایانگر سلسله‌مراتب view است.

Core Animation از سه درخت لایه پشتیبانی می‌کند: model layer tree (ویژگی‌های واقعی)، presentation layer tree(نمایش فعلی در طول انیمیشن) و render tree (داده‌های GPU). Presentation layer برای خواندن مقادیر میانی انیمیشن در زمان واقعی استفاده می‌شود.

انواع CALayer

CALayer زیرکلاس‌های تخصصی دارد: CAShapeLayer (گرافیک برداری)، CAGradientLayer (گرادیان)، CATextLayer (متن)، CATiledLayer (تصاویر بزرگ تقسیم شده به کاشی)، CAEAGLLayer/MetalLayer (OpenGL/Metal). CAShapeLayer به دلیل پشتیبانی از CGPath و انیمیشن strokeStart/strokeEnd محبوب‌ترین برای انیمیشن سفارشی است.

CABasicAnimation انیمیشن پایه ویژگی‌ها

CABasicAnimation زیرکلاس CAAnimation است که یک ویژگی CALayer را از مقدار اولیه (fromValue) به مقدار نهایی (toValue) یا تغییر نسبی (byValue) انیمیشن می‌کند. انیمیشن از طریق متد layer.add(animation, forKey:) به لایه اضافه می‌شود و بدون مشارکت برنامه در هر فریم در render server اجرا می‌شود.

کلید (keyPath) رشته‌ای است که به ویژگی اشاره می‌کند: opacity، position، bounds، transform.rotation.z، cornerRadius، shadowOpacity و غیره. Core Animation از 60+ keyPath قابل انیمیشن پشتیبانی می‌کند. برای ویژگی‌های سفارشی از CATransaction و presentation layer استفاده می‌شود.

swift
import QuartzCore

// CABasicAnimation برای opacity و cornerRadius
func animateLayer() {
    let layer = CALayer()
    layer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
    layer.backgroundColor = UIColor.systemBlue.cgColor
    view.layer.addSublayer(layer)

    // 1. انیمیشن شفافیت
    let fadeAnim = CABasicAnimation(keyPath: "opacity")
    fadeAnim.fromValue = 1.0
    fadeAnim.toValue = 0.2
    fadeAnim.duration = 2.0
    fadeAnim.autoreverses = true
    fadeAnim.repeatCount = .infinity

    // 2. انیمیشن گرد کردن گوشه‌ها
    let cornerAnim = CABasicAnimation(keyPath: "cornerRadius")
    cornerAnim.fromValue = 0
    cornerAnim.toValue = 50
    cornerAnim.duration = 2.0
    cornerAnim.autoreverses = true
    cornerAnim.repeatCount = .infinity

    layer.add(fadeAnim, forKey: "fade")
    layer.add(cornerAnim, forKey: "corner")
}

// انیمیشن position با ease-in-out
func moveLayer(_ layer: CALayer, to point: CGPoint) {
    let anim = CABasicAnimation(keyPath: "position")
    anim.fromValue = NSValue(cgPoint: layer.position)
    anim.toValue = NSValue(cgPoint: point)
    anim.duration = 0.6
    anim.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
    anim.isRemovedOnCompletion = false
    anim.fillMode = .forwards
    layer.add(anim, forKey: "move")
    layer.position = point // model layer را به‌روز می‌کنیم
}

مهم: CABasicAnimation یک نمایش موقت است (presentation layer). پس از اتمام انیمیشن، لایه به مقادیر اولیه model layer بازمی‌گردد. برای تثبیت حالت نهایی، isRemovedOnCompletion = false، fillMode = .forwards تنظیم کنید و model layer را به مقادیر نهایی به‌روزرسانی کنید.

CATransaction گروه‌بندی انیمیشن‌ها

CATransaction مکانیزمی برای گروه‌بندی انیمیشن‌های Core Animation در یک تراکنش واحد است. CATransaction.begin() و CATransaction.commit() مرزهای تراکنش را تعریف می‌کنند. در داخل تراکنش می‌توان پارامترهای مشترک تنظیم کرد: duration، timingFunction، completionBlock، disableActions. CATransaction اساس implicit-انیمیشن‌های CALayer است.

Implicit animation زمانی کار می‌کند که ویژگی CALayer خارج از بلوک انیمیشن تغییر کند: layer.opacity = 0.5. Core Animation به طور خودکار CABasicAnimation با duration از CATransaction جاری ایجاد می‌کند (پیش‌فرض 0.25 ثانیه). برای غیرفعال کردن implicit-انیمیشن از CATransaction.setDisableActions(true) استفاده کنید.

swift
// CATransaction گروه‌بندی و completion
func groupedAnimation() {
    CATransaction.begin()
    CATransaction.setAnimationDuration(1.5)
    CATransaction.setAnimationTimingFunction(
        CAMediaTimingFunction(name: .easeOut)
    )
    CATransaction.setCompletionBlock {
        print("All animations completed")
    }

    // تمام تغییرات داخل تراکنش با مدت 1.5 انیمیشن می‌شوند
    layer1.opacity = 0.3
    layer2.position = CGPoint(x: 200, y: 300)
    layer3.backgroundColor = UIColor.systemRed.cgColor

    CATransaction.commit()
}

// غیرفعال کردن implicit-انیمیشن
func updateWithoutAnimation() {
    CATransaction.begin()
    CATransaction.setDisableActions(true)
    layer.frame = newFrame // بدون انیمیشن
    CATransaction.commit()
}

// انیمیشن ویژگی‌های CAShapeLayer
func animateProgress(percentage: CGFloat) {
    CATransaction.begin()
    CATransaction.setAnimationDuration(0.8)
    CATransaction.setCompletionBlock {
        print("Progress updated to (percentage)%")
    }
    progressLayer.strokeEnd = percentage / 100.0
    CATransaction.commit()
}

مثال‌های کد در Swift

Core Animation از طریق لایه UIView با UIKit ادغام می‌شود. مثال زیر انیمیشن CAShapeLayer را نشان می‌دهد یک نوار پیشرفت دایره‌ای با انیمیشن طول قوس و چرخش لایه از طریق CABasicAnimation.

swift
import UIKit
import QuartzCore

class CircularProgressView: UIView {

    private let progressLayer = CAShapeLayer()

    override func layoutSubviews() {
        super.layoutSubviews()

        let path = UIBezierPath(
            arcCenter: CGPoint(x: bounds.midX, y: bounds.midY),
            radius: bounds.width / 2 - 10,
            startAngle: -.pi / 2,
            endAngle: 3 * .pi / 2,
            clockwise: true
        )

        progressLayer.path = path.cgPath
        progressLayer.strokeColor = UIColor.systemBlue.cgColor
        progressLayer.lineWidth = 8
        progressLayer.fillColor = nil
        progressLayer.strokeEnd = 0
        progressLayer.lineCap = .round
        layer.addSublayer(progressLayer)
    }

    func setProgress(_ value: CGFloat, animated: Bool = true) {
        if animated {
            CATransaction.begin()
            CATransaction.setAnimationDuration(0.6)
            CATransaction.setAnimationTimingFunction(
                CAMediaTimingFunction(name: .easeOut)
            )
            progressLayer.strokeEnd = min(max(value, 0), 1)
            CATransaction.commit()
        } else {
            progressLayer.strokeEnd = value
        }
    }
}

CAShapeLayer ویژگی strokeEnd را از 0 تا 1 انیمیشن می‌کند و اثر «پر شدن» نوار پیشرفت دایره‌ای را ایجاد می‌کند. CATransaction با مدت 0.6 و easeOut انیمیشن را روان می‌کند. layer.lineCap = .round برای ظاهری دقیق‌تر انتهای گرد به خط اضافه می‌کند.

سوالات متداول

تفاوت بین Core Animation و UIView.animate چیست؟

Core Animation در سطح CALayer کار می‌کند و از طریق CABasicAnimation، CATransaction مدیریت می‌شود. UIView.animate یک پوشش سطح بالا بر روی Core Animation است که به طور خودکار CABasicAnimation را برای ویژگی‌های UIView ایجاد می‌کند. Core Animation کنترل بیشتری می‌دهد: keyPath، timingFunction، fillMode، گروه‌بندی از طریق CATransaction.

Implicit animation در Core Animation چیست؟

Implicit animation انیمیشن خودکاری است که هنگام تغییر ویژگی قابل انیمیشن CALayer خارج از بلوک انیمیشن رخ می‌دهد. به عنوان مثال، layer.opacity = 0.5 یک CABasicAnimation با مدت 0.25 ثانیه ایجاد می‌کند. implicit-انیمیشن‌ها از طریق CATransaction مدیریت می‌شوند و با setDisableActions(true) غیرفعال می‌شوند.

چگونه یک ویژگی سفارشی CALayer را انیمیشن کنیم؟

برای ویژگی‌های سفارشی action(forKey:) را در CALayer پیاده‌سازی کنید و CAAnimation برگردانید. یا از CALayer.display() برای رندر دستی با انیمیشن از طریق CADisplayLink استفاده کنید. برای ویژگی‌هایی که از CABasicAnimation پشتیبانی می‌کنند، کافی است keyPath را به صورت رشته مشخص کنید.

چرا CALayer برای انیمیشن از UIView کارآمدتر است؟

CALayer سبک‌تر از UIView است: مدیریت‌کننده رویداد (touches، gestures) ندارد، در Auto Layout شرکت نمی‌کند و از accessibility پشتیبانی نمی‌کند. یک CALayer معمولی ~100 بایت در مقابل ~300+ برای UIView اشغال می‌کند. Core Animation لایه‌ها را در render server روی GPU بدون مسدود کردن main thread پردازش می‌کند.

خلاصه

  • Core Animation فریم‌ورک سطح پایین اپل برای انیمیشن CALayer با رندر روی GPU
  • CALayer کلاس پایه با 60+ ویژگی قابل انیمیشن، پشتیبانی از CAShapeLayer، CAGradientLayer، CATextLayer
  • CABasicAnimation انیمیشن یک ویژگی با fromValue/toValue، اضافه شده از طریق layer.add(animation, forKey:)
  • CATransaction گروه‌بندی انیمیشن‌ها با duration، timingFunction، completionBlock مشترک
  • Implicit animation انیمیشن خودکار هنگام تغییر ویژگی‌های CALayer (مدت 0.25 ثانیه)
  • Presentation layer وضعیت فعلی لایه در طول انیمیشن، برای خواندن مقادیر میانی استفاده می‌شود
  • عملکرد تا 120 FPS در ProMotion، تا 1000 لایه در 60 FPS، 4 بایت/پیکسل

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

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

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

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