Spring Animation — فيزياء الزنبرك في الرسوم المتحركة

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

Spring Animation هي تقنية رسوم متحركة تحاكي السلوك الفيزيائي للزنبرك: الكتلة، الصلابة (stiffness)، التخميد (damping) والسرعة الابتدائية. على عكس الاستيفاءات الخطية ومنحنيات بيزيه، تخلق الرسوم المتحركة الزنبركية حركة طبيعية مع تأثير تذبذب مخمد يبدو عضوياً على أي جهاز. وفقاً لـ Material Design Guidelines (2026)، تُستخدم Spring Animation في 73% من الواجهات المتحركة لأفضل 100 تطبيق في App Store. اقرأ المزيد عن أنواع الرسوم المتحركة الأخرى في الدليل العام للرسوم المتحركة.

أهم النقاط

  • Spring Animation — رسوم متحركة تعتمد على نموذج زنبرك فيزيائي مع الكتلة والتخميد.
  • Damping — معامل تخميد التذبذبات: 0 = تذبذبات لا نهائية، 1 = بدون تجاوز.
  • Stiffness — صلابة الزنبرك: كلما زادت القيمة، زادت سرعة العودة إلى التوازن.
  • CASpringAnimation — كلاس iOS للرسوم المتحركة الزنبركية لـ CALayer مع حساب المدة.
  • SpringAnimation — كلاس Android من مكتبة AndroidX Dynamic Animation.

ما هي Spring Animation؟

Spring Animation هي رسوم متحركة يوصف حركتها بمعادلة المذبذب التوافقي المخمد. بدلاً من استيفاء قيمة من 0 إلى 1 خلال وقت ثابت، تحسب Spring Animation موضع الكائن في كل لحظة بناءً على معاملات فيزيائية: الكتلة، الصلابة، التخميد والسرعة الابتدائية. النتيجة هي حركة طبيعية وعضوية لا تبدو "ميكانيكية".

على عكس منحنيات Easing (easeIn, easeOut, cubic-bezier)، حيث تكون المدة ثابتة والمسار محدداً مسبقاً، تتكيف Spring Animation ديناميكياً: إذا تغيرت القيمة المستهدفة أثناء الحركة، يعيد الزنبرك حساب المسار بسلاسة من الموضع الحالي. هذا مهم بشكل خاص للرسوم المتحركة التي يمكن مقاطعتها — السحب للإغلاق، السحب للتحديث، البطاقات القابلة للسحب.

وفقاً لـ Apple WWDC 2025، فإن استخدام الرسوم المتحركة الزنبركية بدلاً من المنحنيات الثابتة يقلل زمن الاستجابة المدرك بنسبة 30–50% بفضل التسارع الطبيعي في البداية والتباطؤ السلس في النهاية. يُوصى باستخدام Spring Animation لأي رسوم متحركة تتعلق بالحركة: النقل، التحجيم، الظهور/الاختفاء.

المعلمات الفيزيائية للزنبرك: damping وstiffness

يُحدد سلوك الزنبرك بأربعة معاملات. Stiffness (الصلابة) هي قوة العودة إلى التوازن: قيمة 100–300 تعطي زنبركاً ناعماً للقوائم، 500–1000 تعطي زنبركاً صلباً للأزرار والمفاتيح. Damping (التخميد) هو مقاومة الحركة: 0 — تذبذبات لا نهائية، 0.1–0.5 — تذبذبات مخمدة ملحوظة (تأثير الارتداد)، 1 — تخميد حرج (بدون تذبذبات، تباطؤ سلس).

المعاملالنطاقالتأثيرمثال الاستخدام
Stiffness100–1000سرعة العودة إلى التوازن200 = قائمة، 600 = زر
Damping0.0–1.0تخميد التذبذبات0.3 = ارتداد، 1.0 = بدون تذبذبات
Mass0.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 تناسب جميع الحالات تقريباً.

Spring Animation في iOS (Swift)

على 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 كخصائص منفصلة.

swift
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 — بهذا تستمر الرسوم المتحركة بحركة الإصبع بنفس السرعة.

Spring Animation في Android (Kotlin)

على Android، SpringAnimation جزء من مكتبة AndroidX Dynamic Animation (androidx.dynamicanimation). الفئة الرئيسية هي SpringAnimation، التي تحرك أي خاصية float لكائن View أو كائن مخصص. تُحدد المعاملات عبر SpringForce — stiffness (الافتراضي STIFFNESS_MEDIUM = 600) وdampingRatio (الافتراضي DAMPING_RATIO_MEDIUM_BOUNCY = 0.5).

kotlin
// 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: متى تختار ماذا

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.

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

ما الفرق بين damping وstiffness؟

Stiffness هي صلابة الزنبرك (قوة العودة). القيمة العالية (1000) تعطي حركة سريعة وحادة. القيمة المنخفضة (100) تعطي حركة ناعمة وبطيئة. Damping هو مقاومة الحركة. القيمة المنخفضة (0.2) تعطي تذبذبات طويلة مع ارتداد. القيمة العالية (1.0) تعطي عدم وجود تذبذبات، تباطؤ سلس. تحدد Stiffness السرعة، ويحدد Damping وجود وشدة التذبذبات.

كيف أختار المعاملات الصحيحة لـ Spring Animation؟

ابدأ بـ damping = 0.5 و stiffness = 400 — هذه مجموعة بداية عالمية لـ iOS وAndroid. لظهور العناصر، زد damping إلى 0.7. للتأثيرات المميزة (إعجاب، إضافة إلى السلة)، قلل damping إلى 0.3 مع stiffness = 600. لـ Material Motion، استخدم damping = 0.6 وstiffness = 300. اختبر الرسوم المتحركة على جهاز حقيقي، ليس على محاكي.

هل تعمل Spring Animation في SwiftUI؟

نعم، في SwiftUI تُحدد الرسوم المتحركة الزنبركية عبر .animation(.spring(dampingFraction: 0.5, response: 0.5), value: state) أو .spring(blendDuration: 0.3) في withAnimation. يعكس response وdampingFraction معاملات stiffness وdamping من UIKit. للرسوم المتحركة التفاعلية للسحب، استخدم .interactiveSpring() — إصدار خاص بسرعة ابتدائية من الإيماءة محسّن لرسوم السحب.

لماذا لا تتوقف Spring Animation على Android؟

تحقق من SpringForce.finalPosition — إذا لم يكن مضبوطاً أو يساوي القيمة الحالية، قد لا تبدأ الرسوم المتحركة. استدعِ springAnim.cancel() في onPause() لـ Activity/Fragment. لـ SpringAnimation في RecyclerView، استخدم view.setOnDetachListener { animator.cancel() }. لـ Jetpack Compose، تتوقف SpringAnimation تلقائياً عند تغييرات التركيب.

هل يمكن مقاطعة Spring Animation بسلاسة؟

نعم. على iOS، استدعِ view.layer.removeAnimation(forKey:) — تتوقف الرسوم المتحركة عند الإطار الحالي. على Android، استدعِ springAnim.cancel() — يبقى الكائن في موضعه الحالي. للانتقال السلس إلى قيمة مستهدفة جديدة، حدّث finalPosition ولا تستدعِ cancel — يعيد SpringAnimation حساب المسار تلقائياً. لـ SkipToEnd، استخدم springAnim.skipToEnd() على Android.

الخلاصة

  • Spring Animation — رسوم متحركة تعتمد على نموذج زنبرك فيزيائي مع معاملات stiffness وdamping.
  • Damping — معامل التخميد (0 = تذبذبات لا نهائية، 1 = تخميد حرج).
  • Stiffness — صلابة الزنبرك: 200 (ناعم)، 600 (متوسط)، 1800 (عالي) على Android.
  • iOS: UIView.animate مع usingSpringWithDamping (UIKit) أو CASpringAnimation (Core Animation).
  • Android: SpringAnimation + SpringForce من AndroidX Dynamic Animation.
  • Jetpack Compose: animationSpec = spring(dampingRatio, stiffness) عبر Animatable.
  • Spring Animation أفضل من Easing للرسوم المتحركة بالإيماءات (التمرير، السحب، السحب للتحديث).

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

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

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

اقرأ أيضًا