CAAnimation — المفاهيم الأساسية، CAAnimationGroup ورسوم الطبقات المتحركة

المؤلف: IT Sectr نُشر: 2026-03-01 وقت القراءة: 8 دق

CAAnimation هي فئة أساسية مجردة من Core Animation تحدد الواجهة المشتركة لجميع أنواع الرسوم المتحركة: CABasicAnimation، CAKeyframeAnimation، CAAnimationGroup، CATransition. تشرح المقالة التسلسل الهرمي للفئات، الخصائص الرئيسية، تجميع الرسوم المتحركة وأمثلة عملية بلغة Swift.

الخلاصة

  • CAAnimation — فئة أساسية مجردة من Core Animation، ترث منها CABasicAnimation، CAKeyframeAnimation، CAAnimationGroup، CATransition
  • CAAnimationGroup — تنفيذ متوازي لرسوم متحركة متعددة مع duration وtimingFunction مشتركين
  • CAKeyframeAnimation — رسم متحرك بإطارات مفتاحية مع مصفوفات من القيم والطوابع الزمنية
  • CAMediaTiming — بروتوكول إدارة الوقت: duration، repeatCount، autoreverses، timeOffset
  • CATransition — انتقالات محددة مسبقاً بين حالات الطبقة (fade، push، moveIn، reveal)

ما هي CAAnimation؟

CAAnimation هي فئة مجردة من Core Animation تحدد الواجهة المشتركة لجميع الرسوم المتحركة. تنفذ بروتوكول CAMediaTiming (المدة، التكرار، العكس التلقائي) وCAMediaTimingFillMode (السلوك قبل/بعد الرسم المتحرك). لا يمكن إنشاء مثيل لـ CAAnimation مباشرة — استخدم إحدى الفئات الفرعية: CABasicAnimation، CAKeyframeAnimation، CAAnimationGroup، CATransition أو CAAnimation (عبر animationForKeyPath).

تضاف كل CAAnimation إلى CALayer باستخدام طريقة add(_:forKey:). المعامل forKey هو معرف فريد للرسم المتحرك على الطبقة. يمكن أن يكون لكل keyPath رسم متحرك نشط واحد فقط. لاستبدال رسم متحرك، استخدم removeAnimation(forKey:) قبل إضافة رسم جديد.

وفقاً لـ Apple، CAAnimation هي تغيير "مؤقت" للطبقة. بعد اكتمال الرسم المتحرك، تعود طبقة العرض إلى قيم طبقة النموذج إذا لم يتم تعيين fillMode وisRemovedOnCompletion.

التسلسل الهرمي لفئات CAAnimation

توفر Core Animation أربع فئات فرعية رئيسية لـ CAAnimation، كل منها لسيناريو رسم متحرك خاص بها. فهم التسلسل الهرمي يساعد في اختيار النوع المناسب للمهمة.

الفئةالغرضالميزات الرئيسية
CABasicAnimationتحريك خاصية واحدة من أ إلى بfromValue، toValue، byValue، keyPath
CAKeyframeAnimationرسم متحرك عبر إطارات مفتاحية متعددةvalues، keyTimes، path، calculationMode
CAAnimationGroupتجميع رسوم متحركة متعددةمصفوفة animations، duration واحد
CATransitionانتقال بين حالات الطبقةtype (fade/push/moveIn/reveal)، subtype، startProgress

CABasicAnimation هي الفئة الفرعية الأبسط والأكثر شيوعاً. تستخدم CAKeyframeAnimation للمسارات المعقدة (مثل الحركة على طول منحنى Bezier). تنفذ CAAnimationGroup رسوماً متحركة متعددة بالتوازي. CATransition هي انتقال جاهز بين الصور أو حالات المحتوى.

CAMediaTiming — إدارة الوقت

بروتوكول CAMediaTiming هو جزء أساسي من CAAnimation. يحدد خصائص الوقت الأساسية: duration، repeatCount، repeatDuration، autoreverses، beginTime (وقت البداية نسبة إلى الأصل)، timeOffset (الإزاحة ضمن دورة واحدة)، speed (سرعة التشغيل).

خاصية fillMode (CAMediaTimingFillMode) تحدد عرض الطبقة قبل (backwards) وبعد (forwards) الرسم المتحرك. القيم: removed (افتراضي — العودة إلى طبقة النموذج)، forwards (البقاء في الحالة النهائية)، backwards (عرض الحالة الأولية قبل البداية)، both (يجمع كلا السلوكين). يعمل fillMode فقط عندما يكون isRemovedOnCompletion = false.

ترث CAAnimation من CAMediaTiming ويمكن تضمينها في رسم متحرك أب (CAAnimationGroup). في هذه الحالة، يحسب beginTime نسبة إلى بداية الأصل، وتكون duration محدودة بمدة الأصل. Speed = 2.0 يضاعف سرعة الرسم المتحرك.

CAAnimationGroup وCAKeyframeAnimation

CAAnimationGroup يجمع مثيلات متعددة من CAAnimation في مجموعة واحدة. تبدأ جميع الرسوم المتحركة الفرعية بالتوازي ما لم يتم تعيين beginTime لكل منها. للمجموعة duration خاص بها، يحدد أقصى مدة للرسوم المتحركة الفرعية. يستخدم timingFunction للمجموعة كقيمة افتراضية إذا لم تحدد الرسوم المتحركة الفرعية خاصتها.

CAKeyframeAnimation يحول خاصية عبر إطارات مفتاحية متعددة، محددة بمصفوفة من values. المعامل keyTimes (مصفوفة NSNumber من 0 إلى 1) يحدد الطوابع الزمنية لكل إطار. calculationMode يحدد الاستيفاء: linear، discrete (بدون استيفاء)، paced (سرعة موحدة)، cubic (spline)، cubicPaced.

swift
import QuartzCore

// CAAnimationGroup — دمج الرسوم المتحركة
func complexLayerAnimation(_ layer: CALayer) {
    let fade = CABasicAnimation(keyPath: "opacity")
    fade.fromValue = 1.0
    fade.toValue = 0.3

    let scale = CABasicAnimation(keyPath: "transform.scale")
    scale.fromValue = 1.0
    scale.toValue = 1.5

    let rotate = CABasicAnimation(keyPath: "transform.rotation.z")
    rotate.fromValue = 0
    rotate.toValue = Double.pi * 2

    let group = CAAnimationGroup()
    group.animations = [fade, scale, rotate]
    group.duration = 2.0
    group.repeatCount = .infinity
    group.autoreverses = true

    layer.add(group, forKey: "pulse")
}

// CAKeyframeAnimation — الحركة على المسار
func animateAlongPath(_ layer: CALayer) {
    let path = UIBezierPath()
    path.move(to: CGPoint(x: 0, y: 0))
    path.addCurve(
        to: CGPoint(x: 200, y: 300),
        controlPoint1: CGPoint(x: 100, y: 0),
        controlPoint2: CGPoint(x: 100, y: 300)
    )

    let anim = CAKeyframeAnimation(keyPath: "position")
    anim.path = path.cgPath
    anim.duration = 1.5
    anim.calculationMode = .cubicPaced
    anim.rotationMode = .auto
    anim.fillMode = .forwards
    anim.isRemovedOnCompletion = false

    layer.add(anim, forKey: "pathAnim")
    layer.position = CGPoint(x: 200, y: 300)
}

// CAKeyframeAnimation بقيم مخصصة
func bounceAnimation(_ layer: CALayer) {
    let bounce = CAKeyframeAnimation(keyPath: "position.y")
    bounce.values = [0, -50, 0, -25, 0, -10, 0]
    bounce.keyTimes = [0, 0.15, 0.3, 0.45, 0.6, 0.8, 1.0]
    bounce.duration = 0.8
    bounce.timingFunction = CAMediaTimingFunction(name: .easeOut)
    bounce.isAdditive = true // نسبة إلى الموضع الحالي
    layer.add(bounce, forKey: nil)
}

تنفذ CAAnimationGroup عمليات fade وscale وrotate بالتوازي بمدة 2.0. توفر CAKeyframeAnimation مع path وcalculationMode = .cubicPaced حركة موحدة على طول منحنى Bezier مع دوران تلقائي (rotationMode = .auto). تستخدم bounceAnimation isAdditive للإزاحة النسبية.

أمثلة كود بلغة Swift

مثال كامل لـ CAAnimation لرسم متحرك معقد للطبقة باستخدام CATransition لتبديل المحتوى وCAAnimationGroup لتأثيرات النبض.

swift
import UIKit
import QuartzCore

class AnimationDemoView: UIView {

    private let demoLayer = CALayer()
    private var currentColor: CGColor = UIColor.systemBlue.cgColor

    override func layoutSubviews() {
        super.layoutSubviews()
        demoLayer.frame = CGRect(x: bounds.midX - 40, y: bounds.midY - 40,
                                 width: 80, height: 80)
        demoLayer.backgroundColor = currentColor
        demoLayer.cornerRadius = 12
        layer.addSublayer(demoLayer)
    }

    func animateTransition() {
        // CATransition — انتقال بين الحالات
        let transition = CATransition()
        transition.type = .fade
        transition.duration = 0.5
        transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        demoLayer.add(transition, forKey: nil)

        // تغيير المحتوى عبر المعاملة
        currentColor = currentColor == UIColor.systemBlue.cgColor
            ? UIColor.systemRed.cgColor
            : UIColor.systemBlue.cgColor
        demoLayer.backgroundColor = currentColor
    }

    func startPulse() {
        let scaleUp = CABasicAnimation(keyPath: "transform.scale")
        scaleUp.fromValue = 1.0
        scaleUp.toValue = 1.3

        let fadeOut = CABasicAnimation(keyPath: "opacity")
        fadeOut.fromValue = 1.0
        fadeOut.toValue = 0.6

        let glow = CABasicAnimation(keyPath: "shadowOpacity")
        glow.fromValue = 0.0
        glow.toValue = 0.8

        let group = CAAnimationGroup()
        group.animations = [scaleUp, fadeOut, glow]
        group.duration = 1.2
        group.autoreverses = true
        group.repeatCount = .infinity
        group.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)

        demoLayer.add(group, forKey: "pulse")
    }

    func stopAnimations() {
        demoLayer.removeAllAnimations()
        demoLayer.transform = CATransform3DIdentity
        demoLayer.opacity = 1.0
        demoLayer.shadowOpacity = 0.0
    }
}

تنشئ CATransition مع type: .fade انتقالاً سلساً بين حالتي backgroundColor. تجمع CAAnimationGroup بين scale وopacity وshadowOpacity لتأثير النبض. removeAllAnimations() تلغي جميع الرسوم المتحركة وتعيد الطبقة إلى قيم طبقة النموذج الأصلية.

الأسئلة الشائعة

ما الفرق بين CABasicAnimation وCAKeyframeAnimation؟

CABasicAnimation يحول خاصية من قيمة أولية (fromValue) إلى قيمة نهائية (toValue) باستيفاء موحد. CAKeyframeAnimation يسمح بتحديد مصفوفة من القيم الوسيطة (values) والطوابع الزمنية (keyTimes) لرسم متحرك غير خطي بإطارات مفتاحية، بما في ذلك الحركة المنحنية عبر path.

متى تستخدم CAAnimationGroup؟

CAAnimationGroup ضروري عندما يجب تنفيذ رسوم متحركة متعددة بالتوازي مع ضمان المزامنة: مدة المجموعة تحد من جميع الرسوم المتحركة الفرعية. استخدم group للتأثيرات المركبة: تغيير الحجم + تغيير الشفافية + الدوران في وقت واحد.

ما هو fillMode في CAAnimation؟

fillMode يحدد عرض الطبقة قبل (backwards) وبعد (forwards) الرسم المتحرك. القيمة .forwards تبقي الطبقة في الحالة النهائية بعد اكتمال الرسم المتحرك (تتطلب isRemovedOnCompletion = false). .both يجمع بين backwards (الحالة الأولية قبل البداية) وforwards.

كيف تختلف CAAnimation عن رسم CALayer المتحرك؟

CAAnimation هي كائن رسم متحرك (تعليمة) يضاف إلى CALayer عبر layer.add(animation, forKey:). الرسم المتحرك موجود ككائن منفصل، يمكن إعادة استخدامه (مع النسخ) ويتم إدارته من خلال CAMediaTiming. يمكن أن تحتوي الطبقة على رسوم متحركة متعددة بمفاتيح مختلفة.

الملخص

  • CAAnimation — فئة أساسية مجردة من Core Animation تنفذ CAMediaTiming وCAMediaTimingFillMode
  • التسلسل الهرمي للفئات — CABasicAnimation (خاصية واحدة)، CAKeyframeAnimation (إطارات متعددة)، CAAnimationGroup (تجميع)، CATransition (انتقالات)
  • CAMediaTiming — بروتوكول مع duration، repeatCount، autoreverses، beginTime، timeOffset، speed، fillMode
  • CAAnimationGroup — تنفيذ متوازي للرسوم المتحركة مع duration وtimingFunction واحد
  • CAKeyframeAnimation — رسم متحرك عبر values/keyTimes أو path (منحنى Bezier) مع calculationMode
  • CATransition — أنواع محددة مسبقاً: fade، push، moveIn، reveal مع إعداد subtype
  • الإدارة — layer.add(animation, forKey:)، removeAnimation(forKey:)، removeAllAnimations()

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا