CAAnimation هي فئة أساسية مجردة من Core Animation تحدد الواجهة المشتركة لجميع أنواع الرسوم المتحركة: CABasicAnimation، CAKeyframeAnimation، CAAnimationGroup، CATransition. تشرح المقالة التسلسل الهرمي للفئات، الخصائص الرئيسية، تجميع الرسوم المتحركة وأمثلة عملية بلغة Swift.
الخلاصة
CAAnimation هي فئة مجردة من Core Animation تحدد الواجهة المشتركة لجميع الرسوم المتحركة. تنفذ بروتوكول CAMediaTiming (المدة، التكرار، العكس التلقائي) وCAMediaTimingFillMode (السلوك قبل/بعد الرسم المتحرك). لا يمكن إنشاء مثيل لـ CAAnimation مباشرة — استخدم إحدى الفئات الفرعية: CABasicAnimation، CAKeyframeAnimation، CAAnimationGroup، CATransition أو CAAnimation (عبر animationForKeyPath).
تضاف كل CAAnimation إلى CALayer باستخدام طريقة add(_:forKey:). المعامل forKey هو معرف فريد للرسم المتحرك على الطبقة. يمكن أن يكون لكل keyPath رسم متحرك نشط واحد فقط. لاستبدال رسم متحرك، استخدم removeAnimation(forKey:) قبل إضافة رسم جديد.
وفقاً لـ Apple، CAAnimation هي تغيير "مؤقت" للطبقة. بعد اكتمال الرسم المتحرك، تعود طبقة العرض إلى قيم طبقة النموذج إذا لم يتم تعيين fillMode وisRemovedOnCompletion.
توفر 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 هو جزء أساسي من 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 يجمع مثيلات متعددة من CAAnimation في مجموعة واحدة. تبدأ جميع الرسوم المتحركة الفرعية بالتوازي ما لم يتم تعيين beginTime لكل منها. للمجموعة duration خاص بها، يحدد أقصى مدة للرسوم المتحركة الفرعية. يستخدم timingFunction للمجموعة كقيمة افتراضية إذا لم تحدد الرسوم المتحركة الفرعية خاصتها.
CAKeyframeAnimation يحول خاصية عبر إطارات مفتاحية متعددة، محددة بمصفوفة من values. المعامل keyTimes (مصفوفة NSNumber من 0 إلى 1) يحدد الطوابع الزمنية لكل إطار. calculationMode يحدد الاستيفاء: linear، discrete (بدون استيفاء)، paced (سرعة موحدة)، cubic (spline)، cubicPaced.
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 للإزاحة النسبية.
مثال كامل لـ CAAnimation لرسم متحرك معقد للطبقة باستخدام CATransition لتبديل المحتوى وCAAnimationGroup لتأثيرات النبض.
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 يحول خاصية من قيمة أولية (fromValue) إلى قيمة نهائية (toValue) باستيفاء موحد. CAKeyframeAnimation يسمح بتحديد مصفوفة من القيم الوسيطة (values) والطوابع الزمنية (keyTimes) لرسم متحرك غير خطي بإطارات مفتاحية، بما في ذلك الحركة المنحنية عبر path.
CAAnimationGroup ضروري عندما يجب تنفيذ رسوم متحركة متعددة بالتوازي مع ضمان المزامنة: مدة المجموعة تحد من جميع الرسوم المتحركة الفرعية. استخدم group للتأثيرات المركبة: تغيير الحجم + تغيير الشفافية + الدوران في وقت واحد.
fillMode يحدد عرض الطبقة قبل (backwards) وبعد (forwards) الرسم المتحرك. القيمة .forwards تبقي الطبقة في الحالة النهائية بعد اكتمال الرسم المتحرك (تتطلب isRemovedOnCompletion = false). .both يجمع بين backwards (الحالة الأولية قبل البداية) وforwards.
CAAnimation هي كائن رسم متحرك (تعليمة) يضاف إلى CALayer عبر layer.add(animation, forKey:). الرسم المتحرك موجود ككائن منفصل، يمكن إعادة استخدامه (مع النسخ) ويتم إدارته من خلال CAMediaTiming. يمكن أن تحتوي الطبقة على رسوم متحركة متعددة بمفاتيح مختلفة.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا