Spring Animation — la fisica della molla nelle animazioni

Autore: IT Sectr Pubblicato: 2026-03-01 Tempo di lettura: 10 min

Spring Animation è una tecnica di animazione che simula il comportamento fisico di una molla: massa, rigidità (stiffness), smorzamento (damping) e velocità iniziale. A differenza delle interpolazioni lineari e delle curve di Bézier, l'animazione a molla crea un movimento naturale con un effetto di oscillazione smorzata che appare organico su qualsiasi dispositivo. Secondo le Material Design Guidelines (2026), Spring Animation è utilizzata nel 73% delle interfacce animate delle prime 100 app dell'App Store. Scopri di più sugli altri tipi di animazione nella guida generale all'animazione.

Punti chiave

  • Spring Animation — animazione basata su un modello fisico di molla con massa e smorzamento.
  • Damping — coefficiente di smorzamento delle oscillazioni: 0 = infinite, 1 = senza superamento.
  • Stiffness — rigidità della molla: più alto è il valore, più veloce è il ritorno all'equilibrio.
  • CASpringAnimation — classe iOS per l'animazione a molla di CALayer con calcolo della durata.
  • SpringAnimation — classe Android della libreria AndroidX Dynamic Animation.

Cos'è Spring Animation?

Spring Animation è un'animazione il cui movimento è descritto dall'equazione dell'oscillatore armonico smorzato. Invece di interpolare un valore da 0 a 1 per un tempo fisso, Spring Animation calcola la posizione dell'oggetto in ogni istante sulla base di parametri fisici: massa, rigidità, smorzamento e velocità iniziale. Il risultato è un movimento naturale e organico che non sembra "meccanico".

A differenza delle curve Easing (easeIn, easeOut, cubic-bezier), dove la durata è fissa e la traiettoria è predeterminata, Spring Animation si adatta dinamicamente: se il valore target cambia durante l'animazione, la molla ricalcola dolcemente la traiettoria dalla posizione corrente. Questo è particolarmente importante per le animazioni che possono essere interrotte — drag-to-dismiss, pull-to-refresh, schede scorrevoli (swipeable cards).

Secondo Apple WWDC 2025, l'uso dell'animazione a molla invece delle curve fisse riduce la latenza percepita del 30–50% grazie all'accelerazione naturale all'inizio e alla decelerazione morbida alla fine. Spring Animation è consigliata per qualsiasi animazione legata al movimento: spostamento, ridimensionamento, comparsa/scomparsa.

Parametri fisici della molla: damping e stiffness

Il comportamento della molla è definito da quattro parametri. Stiffness (rigidità) è la forza di ritorno all'equilibrio: un valore di 100–300 dà una molla morbida per le liste, 500–1000 dà una molla rigida per pulsanti e interruttori. Damping (smorzamento) è la resistenza al movimento: 0 — oscillazioni infinite, 0.1–0.5 — oscillazioni smorzate notevoli (effetto rimbalzo), 1 — smorzamento critico (senza oscillazioni, decelerazione morbida).

ParametroIntervalloEffettoEsempio di utilizzo
Stiffness100–1000Velocità di ritorno all'equilibrio200 = lista, 600 = pulsante
Damping0.0–1.0Smorzamento delle oscillazioni0.3 = rimbalzo, 1.0 = senza oscillazioni
Mass0.1–10.0Inerzia dell'oggetto1.0 = standard, 3.0 = elemento pesante
Initial VelocityQualsiasiVelocità iniziale in pixel/sVelocità del dito durante drag-to-dismiss

Smorzamento critico (damping = 1.0) è la modalità ottimale per la maggior parte delle animazioni UI: l'oggetto torna alla posizione target il più velocemente possibile senza superamento. Per l'effetto rimbalzo (ad esempio, pull-to-refresh), utilizzare damping = 0.3–0.5. Per la comparsa di finestre modali — damping = 0.6–0.8 con stiffness = 300–500. La massa viene raramente modificata — il valore standard di 1.0 funziona per quasi tutti i casi.

Spring Animation su iOS (Swift)

Su iOS, Spring Animation è disponibile tramite UIView.animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:) da iOS 7 e CASpringAnimation (Core Animation) da iOS 9. La versione UIView è più semplice e popolare per animare le proprietà della View (transform, alpha, center). CASpringAnimation è più precisa e fornisce accesso a stiffness, damping e mass come proprietà separate.

swift
import UIKit

// UIView.animate con parametri a molla
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 — controllo preciso dei parametri
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 calcolata
spring.duration = spring.settlingDuration
view.layer.add(spring, forKey: "scaleSpring")

CASpringAnimation.settlingDuration è una proprietà unica di Core Animation che calcola la durata minima di animazione necessaria affinché la molla raggiunga l'equilibrio. Ciò significa che non è necessario scegliere manualmente la durata — il sistema determina da solo quanto tempo impiegherà lo smorzamento delle oscillazioni. Per UIView.animate, la durata è impostata esplicitamente e un damping di 0.3–0.7 produce un effetto di rimbalzo notevole. Per l'integrazione con UIPanGestureRecognizer, passare velocityRecognizer.velocity(in: view) come initialSpringVelocity — così l'animazione continua il movimento del dito alla stessa velocità.

Spring Animation su Android (Kotlin)

Su Android, SpringAnimation fa parte della libreria AndroidX Dynamic Animation (androidx.dynamicanimation). La classe principale è SpringAnimation, che anima qualsiasi proprietà float di una View o di un oggetto personalizzato. I parametri vengono impostati tramite SpringForce — stiffness (predefinito STIFFNESS_MEDIUM = 600) e dampingRatio (predefinito DAMPING_RATIO_MEDIUM_BOUNCY = 0.5).

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

// Kotlin: SpringAnimation con SpringForce personalizzato
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 con velocità iniziale dal gesto
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) "> Ritorno alla posizione iniziale
                setStartVelocity(velocity)
                start()
            }
            true
        }
        else -> false
    }
}

"> SpringAnimation per proprietà personalizzata
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() }

Costanti 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). Per RecyclerView con animazione di elementi, utilizzare SpringAnimation con DynamicAnimation.OnAnimationEndListener per rilasciare le risorse. Per animare più proprietà, utilizzare SpringAnimation.createFor(view, property).

Jetpack Compose: a partire da Compose 1.0, l'animazione a molla è disponibile tramite Animatable con spring() — animationSpec = spring(dampingRatio = 0.5f, stiffness = 300f). Questo è l'approccio preferito per i progetti Compose, poiché SpringAnimation di DynamicAnimation è compatibile solo con il sistema View. La versione Compose di spring utilizza lo stesso motore fisico ma opera nel contesto del Compose Animation System, mettendosi automaticamente in pausa al distacco.

Spring Animation vs Easing: quando scegliere cosa

Spring Animation e le curve Easing (easeInOut, FastOutSlowIn, decelerate) risolvono problemi diversi. Le curve Easing sono traiettorie matematicamente definite con un tempo fisso. Spring è una simulazione fisica in cui il tempo dipende dai parametri e dalle condizioni iniziali. Per le semplici animazioni di comparsa/scomparsa, le curve Easing sono sufficienti. Per le animazioni legate al movimento dell'utente (drag, swipe, scroll), Spring Animation fornisce una risposta più naturale.

ScenarioRaccomandazioneParametri
Comparsa di elementoSpring (damping = 0.7, stiffness = 400)Comparsa morbida con leggero superamento
Swipe-to-dismissSpring + velocità inizialesetStartVelocity(velocity), damping = 0.5
Animazione iconaSpring (damping = 0.3, stiffness = 600)Rimbalzo notevole per effetti di accento
Fisica dello scrollSpring (sistema)Non personalizzare — Android gestisce
Cambio di dimensioneEasing (FastOutSlowIn)Easing più affidabile per cambi di layout

Anti-pattern: non utilizzare Spring Animation per animare parametri di layout (larghezza/altezza della View tramite LayoutParams) — ciò causa ricalcoli della gerarchia a ogni frame, portando a scatti e cali di FPS. Per l'animazione del colore, anche le curve Easing sono preferibili. Per l'animazione della posizione di scroll, utilizzare lo Scroller di sistema con fling — Spring Animation non offre vantaggi qui. Per le massime prestazioni su Android, limitare il numero di istanze SpringAnimation attive simultaneamente a 10–15.

Domande frequenti

Qual è la differenza tra damping e stiffness?

Stiffness è la rigidità della molla (forza di ritorno). Un valore alto (1000) produce un movimento veloce e brusco. Un valore basso (100) produce un movimento morbido e lento. Damping è la resistenza al movimento. Un valore basso (0.2) produce lunghe oscillazioni con rimbalzo. Un valore alto (1.0) produce assenza di oscillazioni, decelerazione morbida. Stiffness determina la velocità, damping determina la presenza e l'intensità delle oscillazioni.

Come scegliere i parametri corretti di Spring Animation?

Inizia con damping = 0.5 e stiffness = 400 — questo è un set di partenza universale per iOS e Android. Per la comparsa di elementi, aumenta damping a 0.7. Per effetti di accento (mi piace, aggiungi al carrello), riduci damping a 0.3 con stiffness = 600. Per Material Motion, usa damping = 0.6 e stiffness = 300. Prova l'animazione su un dispositivo reale, non su un simulatore.

Spring Animation funziona in SwiftUI?

Sì, in SwiftUI l'animazione a molla viene impostata tramite .animation(.spring(dampingFraction: 0.5, response: 0.5), value: state) o .spring(blendDuration: 0.3) in withAnimation. I parametri response e dampingFraction rispecchiano stiffness e damping di UIKit. Per le animazioni di trascinamento interattive, usa .interactiveSpring() — una versione speciale con velocità iniziale guidata dal gesto ottimizzata per animazioni di trascinamento.

Perché Spring Animation su Android non si ferma?

Controlla SpringForce.finalPosition — se non è impostato o è uguale al valore corrente, l'animazione potrebbe non iniziare. Chiama springAnim.cancel() in onPause() di Activity/Fragment. Per SpringAnimation in RecyclerView, usa view.setOnDetachListener { animator.cancel() }. Per Jetpack Compose, SpringAnimation si mette automaticamente in pausa ai cambiamenti di composizione.

Si può interrompere Spring Animation dolcemente?

Sì. Su iOS, chiama view.layer.removeAnimation(forKey:) — l'animazione si ferma al fotogramma corrente. Su Android, chiama springAnim.cancel() — l'oggetto rimane nella posizione corrente. Per una transizione morbida a un nuovo valore target, aggiorna finalPosition e non chiamare cancel — SpringAnimation ricalcola automaticamente la traiettoria. Per SkipToEnd, usa springAnim.skipToEnd() su Android.

Riepilogo

  • Spring Animation — animazione basata su un modello fisico di molla con parametri di stiffness e damping.
  • Damping — coefficiente di smorzamento (0 = oscillazioni infinite, 1 = smorzamento critico).
  • Stiffness — rigidità della molla: 200 (morbida), 600 (media), 1800 (alta) su Android.
  • iOS: UIView.animate con usingSpringWithDamping (UIKit) o CASpringAnimation (Core Animation).
  • Android: SpringAnimation + SpringForce da AndroidX Dynamic Animation.
  • Jetpack Compose: animationSpec = spring(dampingRatio, stiffness) tramite Animatable.
  • Spring Animation è preferibile a Easing per animazioni gestuali (swipe, drag, pull-to-refresh).

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche