@@ -108,12 +108,17 @@ export function spring(value, opts = {}) {
108
108
return false ;
109
109
}
110
110
inv_mass = Math . min ( inv_mass + inv_mass_recovery_rate , 1 ) ;
111
+
112
+ // clamp elapsed time to 1/30th of a second, so that longer pauses
113
+ // (blocked thread or inactive tab) don't cause the spring to go haywire
114
+ const elapsed = Math . min ( now - last_time , 1000 / 30 ) ;
115
+
111
116
/** @type {TickContext } */
112
117
const ctx = {
113
118
inv_mass,
114
119
opts : spring ,
115
120
settled : true ,
116
- dt : ( ( now - last_time ) * 60 ) / 1000
121
+ dt : ( elapsed * 60 ) / 1000
117
122
} ;
118
123
// @ts -ignore
119
124
const next_value = tick_spring ( ctx , last_value , value , target_value ) ;
@@ -236,6 +241,10 @@ export class Spring {
236
241
this . #task ??= loop ( ( now ) => {
237
242
this . #inverse_mass = Math . min ( this . #inverse_mass + inv_mass_recovery_rate , 1 ) ;
238
243
244
+ // clamp elapsed time to 1/30th of a second, so that longer pauses
245
+ // (blocked thread or inactive tab) don't cause the spring to go haywire
246
+ const elapsed = Math . min ( now - this . #last_time, 1000 / 30 ) ;
247
+
239
248
/** @type {import('./private').TickContext } */
240
249
const ctx = {
241
250
inv_mass : this . #inverse_mass,
@@ -245,7 +254,7 @@ export class Spring {
245
254
precision : this . #precision. v
246
255
} ,
247
256
settled : true ,
248
- dt : ( ( now - this . #last_time ) * 60 ) / 1000
257
+ dt : ( elapsed * 60 ) / 1000
249
258
} ;
250
259
251
260
var next = tick_spring ( ctx , this . #last_value, this . #current. v , this . #target. v ) ;
0 commit comments