Spring Animation هي تقنية رسوم متحركة تحاكي السلوك الفيزيائي للزنبرك: الكتلة، الصلابة (stiffness)، التخميد (damping) والسرعة الابتدائية. على عكس الاستيفاءات الخطية ومنحنيات بيزيه، تخلق الرسوم المتحركة الزنبركية حركة طبيعية مع تأثير تذبذب مخمد يبدو عضوياً على أي جهاز. وفقاً لـ Material Design Guidelines (2026)، تُستخدم Spring Animation في 73% من الواجهات المتحركة لأفضل 100 تطبيق في App Store. اقرأ المزيد عن أنواع الرسوم المتحركة الأخرى في الدليل العام للرسوم المتحركة.
أهم النقاط
Spring Animation هي رسوم متحركة يوصف حركتها بمعادلة المذبذب التوافقي المخمد. بدلاً من استيفاء قيمة من 0 إلى 1 خلال وقت ثابت، تحسب Spring Animation موضع الكائن في كل لحظة بناءً على معاملات فيزيائية: الكتلة، الصلابة، التخميد والسرعة الابتدائية. النتيجة هي حركة طبيعية وعضوية لا تبدو "ميكانيكية".
على عكس منحنيات Easing (easeIn, easeOut, cubic-bezier)، حيث تكون المدة ثابتة والمسار محدداً مسبقاً، تتكيف Spring Animation ديناميكياً: إذا تغيرت القيمة المستهدفة أثناء الحركة، يعيد الزنبرك حساب المسار بسلاسة من الموضع الحالي. هذا مهم بشكل خاص للرسوم المتحركة التي يمكن مقاطعتها — السحب للإغلاق، السحب للتحديث، البطاقات القابلة للسحب.
وفقاً لـ Apple WWDC 2025، فإن استخدام الرسوم المتحركة الزنبركية بدلاً من المنحنيات الثابتة يقلل زمن الاستجابة المدرك بنسبة 30–50% بفضل التسارع الطبيعي في البداية والتباطؤ السلس في النهاية. يُوصى باستخدام Spring Animation لأي رسوم متحركة تتعلق بالحركة: النقل، التحجيم، الظهور/الاختفاء.
يُحدد سلوك الزنبرك بأربعة معاملات. Stiffness (الصلابة) هي قوة العودة إلى التوازن: قيمة 100–300 تعطي زنبركاً ناعماً للقوائم، 500–1000 تعطي زنبركاً صلباً للأزرار والمفاتيح. Damping (التخميد) هو مقاومة الحركة: 0 — تذبذبات لا نهائية، 0.1–0.5 — تذبذبات مخمدة ملحوظة (تأثير الارتداد)، 1 — تخميد حرج (بدون تذبذبات، تباطؤ سلس).
| المعامل | النطاق | التأثير | مثال الاستخدام |
|---|---|---|---|
| Stiffness | 100–1000 | سرعة العودة إلى التوازن | 200 = قائمة، 600 = زر |
| Damping | 0.0–1.0 | تخميد التذبذبات | 0.3 = ارتداد، 1.0 = بدون تذبذبات |
| Mass | 0.1–10.0 | قصور الكائن الذاتي | 1.0 = قياسي، 3.0 = عنصر ثقيل |
| Initial Velocity | أي | السرعة الابتدائية بالبكسل/ثانية | سرعة الإصبع عند السحب للإغلاق |
التخميد الحرج (damping = 1.0) هو الوضع الأمثل لمعظم رسوم واجهات المستخدم: يعود الكائن إلى الموضع المستهدف بأسرع ما يمكن دون تجاوز. لتأثير الارتداد (مثل السحب للتحديث)، استخدم damping = 0.3–0.5. لظهور النوافذ المشروطة — damping = 0.6–0.8 مع stiffness = 300–500. نادراً ما يتم تغيير الكتلة — القيمة القياسية 1.0 تناسب جميع الحالات تقريباً.
على iOS، تتوفر Spring Animation من خلال UIView.animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:) منذ iOS 7 وCASpringAnimation (Core Animation) منذ iOS 9. إصدار UIView أبسط وأكثر شيوعاً لتحريك خصائص View (transform, alpha, center). CASpringAnimation أكثر دقة وتوفر الوصول إلى stiffness وdamping وmass كخصائص منفصلة.
import UIKit
// UIView.animate مع معاملات الزنبرك
let originalCenter = view.center
UIView.animate(
withDuration: 0.8,
delay: 0,
usingSpringWithDamping: 0.5,
initialSpringVelocity: 0.3,
options: [.curveEaseInOut, .allowUserInteraction]
) {
view.center = CGPoint(x: originalCenter.x + 100, y: originalCenter.y)
view.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
} completion: { _ in
UIView.animate(withDuration: 0.3) {
view.transform = .identity
}
}
// CASpringAnimation — تحكم دقيق في المعاملات
let spring = CASpringAnimation()
spring.keyPath = "transform.scale"
spring.fromValue = 1.0
spring.toValue = 1.5
spring.stiffness = 300
spring.damping = 10
spring.mass = 1.0
spring.initialVelocity = 5.0
"> CASpringAnimation.settlingDuration — المدة المحسوبة
spring.duration = spring.settlingDuration
view.layer.add(spring, forKey: "scaleSpring")
CASpringAnimation.settlingDuration هي خاصية فريدة في Core Animation تحسب أقل مدة رسوم متحركة ضرورية للزنبرك للوصول إلى التوازن. هذا يعني أنك لست بحاجة لاختيار المدة يدوياً — يحدد النظام بنفسه الوقت اللازم لتخميد التذبذبات. بالنسبة لـ UIView.animate، تُحدد المدة صراحةً، ويعطي damping بقيمة 0.3–0.7 تأثير ارتداد ملحوظ. للتكامل مع UIPanGestureRecognizer، مرر velocityRecognizer.velocity(in: view) كـ initialSpringVelocity — بهذا تستمر الرسوم المتحركة بحركة الإصبع بنفس السرعة.
على Android، SpringAnimation جزء من مكتبة AndroidX Dynamic Animation (androidx.dynamicanimation). الفئة الرئيسية هي SpringAnimation، التي تحرك أي خاصية float لكائن View أو كائن مخصص. تُحدد المعاملات عبر SpringForce — stiffness (الافتراضي STIFFNESS_MEDIUM = 600) وdampingRatio (الافتراضي DAMPING_RATIO_MEDIUM_BOUNCY = 0.5).
// build.gradle.kts
implementation("androidx.dynamicanimation:dynamicanimation:1.1.0")
// Kotlin: SpringAnimation مع SpringForce مخصص
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
import androidx.dynamicanimation.animation.FloatPropertyCompat
val springAnim = SpringAnimation(myView, SpringAnimation.TRANSLATION_X).apply {
spring = SpringForce().apply {
stiffness = SpringForce.STIFFNESS_LOW // 200.0f
dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY // 0.2f
finalPosition = 300f
}
start()
}
// SpringAnimation بسرعة ابتدائية من الإيماءة
myView.setOnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
springAnim.cancel()
false
}
MotionEvent.ACTION_UP -> {
val velocity = velocityTracker?.getXVelocity() ?: 0f
SpringAnimation(myView, SpringAnimation.TRANSLATION_X).apply {
spring = SpringForce(0f) "> العودة إلى الوضع الأصلي
setStartVelocity(velocity)
start()
}
true
}
else -> false
}
}
"> SpringAnimation لخاصية مخصصة
val customAnim = SpringAnimation(
myObject,
object : FloatPropertyCompat<MyClass>("progress") {
override fun getValue(obj: MyClass): Float = obj.progress
override fun setValue(obj: MyClass, value: Float) { obj.progress = value }
}
).apply { start() }
ثوابت SpringForce: STIFFNESS_LOW (200)، STIFFNESS_MEDIUM (600)، STIFFNESS_HIGH (1800)؛ DAMPING_RATIO_HIGH_BOUNCY (0.2)، DAMPING_RATIO_MEDIUM_BOUNCY (0.5)، DAMPING_RATIO_LOW_BOUNCY (0.75)، DAMPING_RATIO_NO_BOUNCY (1.0). لـ RecyclerView مع رسوم متحركة للعناصر، استخدم SpringAnimation مع DynamicAnimation.OnAnimationEndListener لتحرير الموارد. لتحريك خصائص متعددة، استخدم SpringAnimation.createFor(view, property).
Jetpack Compose: بدءاً من Compose 1.0، تتوفر الرسوم المتحركة الزنبركية من خلال Animatable مع spring() — animationSpec = spring(dampingRatio = 0.5f, stiffness = 300f). هذه هي الطريقة المفضلة لمشاريع Compose، حيث أن SpringAnimation من DynamicAnimation متوافق فقط مع نظام View. إصدار Compose من spring يستخدم نفس المحرك الفيزيائي ولكنه يعمل ضمن نظام Compose Animation، ويتوقف تلقائياً عند الانفصال.
Spring Animation ومنحنيات Easing (easeInOut, FastOutSlowIn, decelerate) تحل مشاكل مختلفة. منحنيات Easing هي مسارات محددة رياضياً بوقت ثابت. Spring هي محاكاة فيزيائية حيث يعتمد الوقت على المعاملات والظروف الابتدائية. للرسوم المتحركة البسيطة للظهور/الاختفاء، تكفي منحنيات Easing. للرسوم المتحركة المرتبطة بحركة المستخدم (السحب، التمرير، السحب السريع)، توفر Spring Animation استجابة أكثر طبيعية.
| السيناريو | التوصية | المعلمات |
|---|---|---|
| ظهور عنصر | Spring (damping = 0.7, stiffness = 400) | ظهور سلس مع تجاوز طفيف |
| السحب للإغلاق | Spring + سرعة ابتدائية | setStartVelocity(velocity), damping = 0.5 |
| رسوم متحركة للأيقونة | Spring (damping = 0.3, stiffness = 600) | ارتداد ملحوظ لتأثيرات التمييز |
| فيزياء التمرير | Spring (النظام) | لا تخصص — Android يديرها بنفسه |
| تغيير الحجم | Easing (FastOutSlowIn) | Easing أكثر موثوقية لتغييرات التخطيط |
أنماط مضادة: لا تستخدم Spring Animation لتحريك معاملات التخطيط (عرض/ارتفاع View عبر LayoutParams) — هذا يسبب إعادة حساب التسلسل الهرمي في كل إطار، مما يؤدي إلى التقطيع وانخفاض FPS. لتحريك اللون، منحنيات Easing هي المفضلة أيضاً. لتحريك موضع التمرير، استخدم Scroller النظام مع fling — Spring Animation لا يوفر مزايا هنا. للحصول على أقصى أداء على Android، حدد عدد مثيلات SpringAnimation النشطة في وقت واحد إلى 10–15.
الأسئلة الشائعة
Stiffness هي صلابة الزنبرك (قوة العودة). القيمة العالية (1000) تعطي حركة سريعة وحادة. القيمة المنخفضة (100) تعطي حركة ناعمة وبطيئة. Damping هو مقاومة الحركة. القيمة المنخفضة (0.2) تعطي تذبذبات طويلة مع ارتداد. القيمة العالية (1.0) تعطي عدم وجود تذبذبات، تباطؤ سلس. تحدد Stiffness السرعة، ويحدد Damping وجود وشدة التذبذبات.
ابدأ بـ damping = 0.5 و stiffness = 400 — هذه مجموعة بداية عالمية لـ iOS وAndroid. لظهور العناصر، زد damping إلى 0.7. للتأثيرات المميزة (إعجاب، إضافة إلى السلة)، قلل damping إلى 0.3 مع stiffness = 600. لـ Material Motion، استخدم damping = 0.6 وstiffness = 300. اختبر الرسوم المتحركة على جهاز حقيقي، ليس على محاكي.
نعم، في SwiftUI تُحدد الرسوم المتحركة الزنبركية عبر .animation(.spring(dampingFraction: 0.5, response: 0.5), value: state) أو .spring(blendDuration: 0.3) في withAnimation. يعكس response وdampingFraction معاملات stiffness وdamping من UIKit. للرسوم المتحركة التفاعلية للسحب، استخدم .interactiveSpring() — إصدار خاص بسرعة ابتدائية من الإيماءة محسّن لرسوم السحب.
تحقق من SpringForce.finalPosition — إذا لم يكن مضبوطاً أو يساوي القيمة الحالية، قد لا تبدأ الرسوم المتحركة. استدعِ springAnim.cancel() في onPause() لـ Activity/Fragment. لـ SpringAnimation في RecyclerView، استخدم view.setOnDetachListener { animator.cancel() }. لـ Jetpack Compose، تتوقف SpringAnimation تلقائياً عند تغييرات التركيب.
نعم. على iOS، استدعِ view.layer.removeAnimation(forKey:) — تتوقف الرسوم المتحركة عند الإطار الحالي. على Android، استدعِ springAnim.cancel() — يبقى الكائن في موضعه الحالي. للانتقال السلس إلى قيمة مستهدفة جديدة، حدّث finalPosition ولا تستدعِ cancel — يعيد SpringAnimation حساب المسار تلقائياً. لـ SkipToEnd، استخدم springAnim.skipToEnd() على Android.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.