Underdamped spring formula changed
Summary
#
                  The formula for SpringDescription changed to correct an earlier error,
                  affecting underdamped springs (damping ratio less than 1)
                  with mass values other than 1.
                  Springs created prior to this change may exhibit
                  different bouncing behaviors after upgrading.
                
Background
#
                  The SpringDescription
                   class describes the behavior of damped springs,
                  enabling Flutter widgets to animate realistically based on provided parameters.
                  The physics of damped springs are widely studied and documented. For an overview
                  of damping, see Wikipedia: Damping.
                
                  Previously, Flutter's formula for calculating underdamped spring behavior was
                  incorrect, as reported in Issue 163858. This error affected all springs with
                  a damping ratio less than 1 and a mass other than 1. Consequently, animations
                  did not match expected real-world physics, and behavior around the critical
                  damping point (damping ratio of exactly 1) exhibited discontinuities.
                  Specifically, when using SpringDescription.withDampingRatio, small
                  differences, such as damping ratios of 1.0001 versus 0.9999, resulted in
                  significantly different animations.
                
The issue was corrected in PR Fix SpringSimulation formula for underdamping, which updated the underlying calculation. As a result, previously affected animations now behave differently, though no explicit errors are reported by the framework.
Migration guide
#Migration is necessary only for springs with damping ratios less than 1 and masses other than 1.
To restore previous animation behavior, update your spring parameters accordingly. You can calculate the required parameter adjustments using the provided JSFiddle for migration. Detailed formulas and explanations follow in the next sections.
Default constructor
#
                  If the SpringDescription was built with the default constructor with
                  mass m, stiffness k, and damping c,
                  then it should be changed with the following formula:
                
new_m = 1
new_c = c * m
new_k = (4 * (k / m) - (c / m)^2 + (c * m)^2) / 4
                    
                    
                    
                  Code before migration:
const spring = SpringDescription(
  mass: 20.0,
  stiffness: 10,
  damping: 1,
);
                    
                    
                    
                  Code after migration:
const spring = SpringDescription(
  mass: 1.0,
  stiffness: 100.499375,
  damping: 20,
);
                    
                    
                    
                  .withDampingRatio constructor
                  #
                
                  If the SpringDescription was built with the .withDampingRatio constructor
                  with mass m, stiffness k, and ratio z, then first calculate damping:
                
c = z * 2 * sqrt(m * k)
                    
                    
                    
                  Then apply the formula above. Optionally, you might convert the result back to damping ratio with:
new_z = new_c / 2 / sqrt(new_m * new_k)
                    
                    
                    
                  Code before migration:
const spring = SpringDescription.withDampingRatio(
  mass: 5.0,
  stiffness: 6.0,
  damping: 0.03,
);
                    
                    
                    
                  Code after migration:
const spring = SpringDescription.withDampingRatio(
  mass: 1,
  stiffness: 1.87392,
  ratio: 0.60017287468545,
);
                    
                    
                    
                  Timeline
#
                  Landed in version: 3.31.0-0.1.pre
                  In stable release: 3.32
                
References
#API documentation:
Relevant issues:
- Issue 163858, where the bug was discovered and more context can be found.
 
Relevant PRs:
Tool:
Unless stated otherwise, the documentation on this site reflects Flutter 3.35.5. Page last updated on 2025-10-28. View source or report an issue.