Spring Animation — esența, fizica arcului în animații

Autor: IT Sectr Publicat: 2026-03-01 Timp de citire: 10 min

Spring Animation — tehnică de animație care modelează comportamentul fizic al unui arc: masă, rigiditate (stiffness), amortizare (damping) și viteză inițială. Spre deosebire de interpolările liniare și curbele Bézier, animația cu arc creează o mișcare naturală cu efect de oscilații amortizate, care arată organic pe orice dispozitiv. Conform Material Design Guidelines (2026), Spring Animation este utilizată în 73% din interfețele animate ale primelor 100 de aplicații din App Store. Citiți mai multe despre alte tipuri de animație în ghidul general de animație.

Principalele puncte

  • Spring Animation — animație bazată pe modelul fizic al arcului cu masă și amortizare.
  • Damping — coeficient de amortizare a oscilațiilor: 0 = infinite, 1 = fără depășire.
  • Stiffness — rigiditatea arcului: cu cât este mai mare, cu atât revenirea la echilibru este mai rapidă.
  • CASpringAnimation — clasa iOS pentru animația cu arc a CALayer cu calculul duratei.
  • SpringAnimation — clasa Android din biblioteca AndroidX Dynamic Animation.

Ce este Spring Animation?

Spring Animation — este o animație a cărei mișcare este descrisă de ecuația oscilatorului armonic cu amortizare. În loc să interpoleze valoarea de la 0 la 1 într-un timp fix, Spring Animation calculează poziția obiectului în fiecare moment pe baza parametrilor fizici: masă (mass), rigiditate (stiffness), amortizare (damping) și viteză inițială (initialVelocity). Rezultatul — o mișcare naturală, organică, care nu pare „mecanică”.

Spre deosebire de curbele Easing (easeIn, easeOut, cubic-bezier), unde durata este fixă și traiectoria predeterminată, Spring Animation se adaptează dinamic: dacă schimbați valoarea țintă în timpul animației, arcul recalculează lin traiectoria de la poziția curentă. Acest lucru este deosebit de important pentru animațiile care pot fi întrerupte — drag-to-dismiss, pull-to-refresh, carduri glisabile (swipeable cards).

Conform Apple WWDC 2025, utilizarea animației cu arc în locul curbelor fixe reduce latența percepută (perceived latency) cu 30–50% datorită accelerării naturale la început și decelerației line la sfârșit. Spring Animation este recomandată pentru orice animație legată de mișcare: deplasare, scalare, apariție/dispariție.

Parametrii fizici ai arcului: damping și stiffness

Comportamentul arcului este determinat de patru parametri. Stiffness (rigiditate) — forța de revenire la echilibru: valoarea 100–300 oferă un arc moale pentru liste, 500–1000 — un arc dur pentru butoane și comutatoare. Damping (amortizare) — rezistența la mișcare: 0 — oscilații infinite, 0.1–0.5 — oscilații amortizate vizibile (efect de bounce), 1 — amortizare critică (fără oscilații, frânare lină).

ParametruIntervalEfectExemplu de utilizare
Stiffness100–1000Viteza de revenire la echilibru200 = listă, 600 = buton
Damping0.0–1.0Amortizarea oscilațiilor0.3 = bounce, 1.0 = fără oscilații
Mass0.1–10.0Inerția obiectului1.0 = standard, 3.0 = element greu
Initial VelocityOricareViteza inițială în pixeli/sViteza degetului la drag-to-dismiss

Amortizarea critică (damping = 1.0) — modul optim pentru majoritatea animațiilor UI: obiectul revine la poziția țintă cât mai repede posibil fără depășire. Pentru efectul de bounce (de exemplu, pull-to-refresh) utilizați damping = 0.3–0.5. Pentru apariția ferestrelor modale — damping = 0.6–0.8 cu stiffness = 300–500. Masa se modifică rar — valoarea standard 1.0 este potrivită pentru aproape toate cazurile.

Spring Animation în iOS (Swift)

Pe iOS Spring Animation este disponibilă prin UIView.animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:) din iOS 7 și CASpringAnimation (Core Animation) din iOS 9. Versiunea UIView este mai simplă și mai populară pentru animarea proprietăților View (transform, alpha, center). CASpringAnimation este mai precisă și oferă acces la stiffness, damping și mass ca proprietăți separate.

swift
import UIKit

// UIView.animate cu parametri de arc
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 — control precis asupra parametrilor
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 — durata calculată
spring.duration = spring.settlingDuration
view.layer.add(spring, forKey: "scaleSpring")

CASpringAnimation.settlingDuration — o proprietate unică a Core Animation care calculează durata minimă de animație necesară arcului pentru a atinge echilibrul. Aceasta înseamnă că nu trebuie să alegeți manual duration — sistemul determină singur cât timp va dura amortizarea oscilațiilor. Pentru UIView.animate durata este specificată explicit, iar damping 0.3–0.7 oferă un efect de bounce vizibil. Pentru integrarea cu UIPanGestureRecognizer, transmiteți velocityRecognizer.velocity(in: view) ca initialSpringVelocity — astfel animația continuă mișcarea degetului cu aceeași viteză.

Spring Animation în Android (Kotlin)

Pe Android SpringAnimation face parte din biblioteca AndroidX Dynamic Animation (androidx.dynamicanimation). Clasa principală — SpringAnimation, care animează orice proprietate float a unui View sau obiect personalizat. Parametrii se setează prin SpringForce — stiffness (implicit STIFFNESS_MEDIUM = 600) și dampingRatio (implicit DAMPING_RATIO_MEDIUM_BOUNCY = 0.5).

kotlin
// build.gradle.kts
implementation("androidx.dynamicanimation:dynamicanimation:1.1.0")

// Kotlin: SpringAnimation cu SpringForce personalizat
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 cu viteză inițială din gest
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) "> Revenirea în poziția inițială
                setStartVelocity(velocity)
                start()
            }
            true
        }
        else -> false
    }
}

"> SpringAnimation pentru proprietate personalizată
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() }

Constantele 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). Pentru RecyclerView cu animație de elemente, utilizați SpringAnimation cu DynamicAnimation.OnAnimationEndListener pentru eliberarea resurselor. Pentru animarea mai multor proprietăți, utilizați SpringAnimation.createFor(view, property).

Jetpack Compose: începând cu Compose 1.0, animația cu arc este disponibilă prin Animatable cu spring() — animationSpec = spring(dampingRatio = 0.5f, stiffness = 300f). Aceasta este metoda preferată pentru proiectele Compose, deoarece SpringAnimation din DynamicAnimation este compatibil doar cu sistemul View. Versiunea Compose spring folosește același motor fizic, dar funcționează în contextul Compose Animation System, oprindu-se automat la detachment.

Spring Animation vs Easing: când să alegem ce

Spring Animation și curbele Easing (easeInOut, FastOutSlowIn, decelerate) rezolvă sarcini diferite. Curbele Easing — sunt o traiectorie definită matematic cu timp fix. Spring — simulare fizică, unde timpul depinde de parametri și condițiile inițiale. Pentru animații simple de apariție/dispariție, curbele Easing sunt suficiente. Pentru animații legate de mișcarea utilizatorului (drag, swipe, scroll), Spring Animation oferă un feedback mai natural.

ScenariuRecomandareParametri
Apariția elementuluiSpring (damping = 0.7, stiffness = 400)Apariție lină cu ușoară depășire
Swipe-to-dismissSpring + viteză inițialăsetStartVelocity(velocity), damping = 0.5
Animația pictogrameiSpring (damping = 0.3, stiffness = 600)Bounce vizibil pentru efecte de accent
Fizica scrollSpring (sistemic)Nu personalizați — Android gestionează singur
Modificarea dimensiuniiEasing (FastOutSlowIn)Easing este mai fiabil pentru schimbări de layout

Anti-patterns: nu utilizați Spring Animation pentru animarea parametrilor de layout (lățime/înălțime View prin LayoutParams) — aceasta provoacă recalcularea ierarhiei în fiecare cadru, ducând la tremur și scădere FPS. Pentru animarea culorii, curbele Easing sunt de asemenea mai bune. Pentru animarea poziției de scroll, utilizați Scroller-ul sistemic cu fling — Spring Animation nu oferă avantaje aici. Pentru performanță maximă pe Android, limitați numărul de SpringAnimation active simultan la 10–15.

Întrebări frecvente

Care este diferența dintre damping și stiffness?

Stiffness — rigiditatea arcului (forța de revenire). Valoare mare (1000) — mișcare rapidă, bruscă. Valoare mică (100) — lină, lentă. Damping — amortizarea (rezistența). Scăzut (0.2) — oscilații lungi cu bounce. Ridicat (1.0) — fără oscilații, frânare lină. Stiffness determină viteza, damping — prezența și intensitatea oscilațiilor.

Cum alegem parametrii corecți pentru Spring Animation?

Începeți cu damping = 0.5 și stiffness = 400 — acesta este un set universal de pornire pentru iOS și Android. Pentru apariția elementelor, măriți damping la 0.7. Pentru efecte de accent (like, adăugare în coș), reduceți damping la 0.3 cu stiffness = 600. Pentru Material Motion, utilizați damping = 0.6 și stiffness = 300. Verificați animația pe un dispozitiv real, nu în simulator.

Spring Animation funcționează în SwiftUI?

Da, în SwiftUI animația cu arc se setează prin .animation(.spring(dampingFraction: 0.5, response: 0.5), value: state) sau .spring(blendDuration: 0.3) în withAnimation. response și dampingFraction corespund stiffness și damping din UIKit. Pentru interactiveSpring() utilizați .interactiveSpring() — o versiune specială cu viteză inițială din gest, optimizată pentru animații drag.

De ce Spring Animation pe Android nu se oprește?

Verificați SpringForce.finalPosition — dacă nu este setat sau este egal cu valoarea curentă, animația poate să nu înceapă. Apelați springAnim.cancel() în onPause() al Activity/Fragment. Pentru SpringAnimation în RecyclerView, utilizați view.setOnDetachListener { animator.cancel() }. Pentru Jetpack Compose, SpringAnimation se oprește automat la compoziție.

Se poate întrerupe Spring Animation lin?

Da. Pe iOS apelați view.layer.removeAnimation(forKey:) — animația se va opri pe cadrul curent. Pe Android apelați springAnim.cancel() — obiectul rămâne pe poziția curentă. Pentru o tranziție lină la o nouă valoare țintă, actualizați finalPosition și nu apelați cancel — SpringAnimation va recalcula automat traiectoria. Pentru SkipToEnd, utilizați springAnim.skipToEnd() pe Android.

Rezumat

  • Spring Animation — animație bazată pe modelul fizic al arcului cu parametrii stiffness și damping.
  • Damping — coeficient de amortizare (0 = oscilații infinite, 1 = amortizare critică).
  • Stiffness — rigiditatea arcului: 200 (soft), 600 (medium), 1800 (high) pe Android.
  • iOS: UIView.animate cu usingSpringWithDamping (UIKit) sau CASpringAnimation (Core Animation).
  • Android: SpringAnimation + SpringForce din AndroidX Dynamic Animation.
  • Jetpack Compose: animationSpec = spring(dampingRatio, stiffness) prin Animatable.
  • Spring Animation este preferată față de Easing pentru animații cu gesturi (swipe, drag, pull-to-refresh).

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și