coily 0.12.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -185
- package/dist/index.d.ts +2 -2
- package/dist/index.js +78 -2
- package/dist/nuxt.d.ts +42 -1
- package/dist/nuxt.js +24 -10
- package/dist/system-BXxAHM2a.js +1758 -0
- package/dist/system-Ci-R4RaI.d.ts +1032 -0
- package/dist/vue.d.ts +240 -25
- package/dist/vue.js +166 -270
- package/package.json +16 -16
- package/dist/system-Bzrx4uso.js +0 -976
- package/dist/system-coAFNYnb.d.ts +0 -350
package/dist/system-Bzrx4uso.js
DELETED
|
@@ -1,976 +0,0 @@
|
|
|
1
|
-
//#region src/motion-set.ts
|
|
2
|
-
var MotionSet = class {
|
|
3
|
-
#motions = /* @__PURE__ */ new Set();
|
|
4
|
-
#debug;
|
|
5
|
-
#lastSize = 0;
|
|
6
|
-
constructor(debug = false) {
|
|
7
|
-
this.#debug = debug;
|
|
8
|
-
}
|
|
9
|
-
add(motion) {
|
|
10
|
-
this.#motions.add(motion);
|
|
11
|
-
}
|
|
12
|
-
remove(motion) {
|
|
13
|
-
this.#motions.delete(motion);
|
|
14
|
-
}
|
|
15
|
-
tick(dt) {
|
|
16
|
-
for (const motion of this.#motions) {
|
|
17
|
-
motion.tick(dt);
|
|
18
|
-
if (motion.isResting) this.#motions.delete(motion);
|
|
19
|
-
}
|
|
20
|
-
if (this.#debug && this.#motions.size !== this.#lastSize) {
|
|
21
|
-
this.#lastSize = this.#motions.size;
|
|
22
|
-
console.log(`coily: ${this.#lastSize} active motions`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
//#endregion
|
|
27
|
-
//#region src/util.ts
|
|
28
|
-
function invariant(condition, message) {
|
|
29
|
-
if (condition) return;
|
|
30
|
-
throw new Error(message ?? "Invariant Failed");
|
|
31
|
-
}
|
|
32
|
-
//#endregion
|
|
33
|
-
//#region src/config.ts
|
|
34
|
-
/**
|
|
35
|
-
* Immutable spring configuration.
|
|
36
|
-
*/
|
|
37
|
-
var SpringConfig = class SpringConfig {
|
|
38
|
-
static default = new SpringConfig({
|
|
39
|
-
dampingRatio: 1,
|
|
40
|
-
duration: 500
|
|
41
|
-
});
|
|
42
|
-
/** @internal Incremented by `assign` to signal mutations. Do not read or write directly. */
|
|
43
|
-
_version = 0;
|
|
44
|
-
mass;
|
|
45
|
-
tension;
|
|
46
|
-
damping;
|
|
47
|
-
precision;
|
|
48
|
-
naturalFrequency;
|
|
49
|
-
criticalDamping;
|
|
50
|
-
dampingRatio;
|
|
51
|
-
precisionMultiplier;
|
|
52
|
-
restingMagnitude;
|
|
53
|
-
constructor(input) {
|
|
54
|
-
const raw = input;
|
|
55
|
-
const mass = raw.mass;
|
|
56
|
-
const tension = raw.tension;
|
|
57
|
-
const damping = raw.damping;
|
|
58
|
-
const bounce = raw.bounce;
|
|
59
|
-
const duration = raw.duration !== void 0 ? raw.duration / 1e3 : void 0;
|
|
60
|
-
const displacement = raw.displacement ?? 1;
|
|
61
|
-
const precision = raw.precision ?? 2;
|
|
62
|
-
if (mass !== void 0) invariant(mass > 0, "Mass must be greater than 0");
|
|
63
|
-
if (tension !== void 0) invariant(tension > 0, "Tension must be greater than 0");
|
|
64
|
-
if (damping !== void 0) invariant(damping >= 0, "Damping must be greater than or equal to 0");
|
|
65
|
-
if (bounce !== void 0) invariant(bounce >= -1 && bounce <= 1, "Bounce must be between -1 and 1");
|
|
66
|
-
const dampingRatio = raw.dampingRatio ?? (bounce !== void 0 ? Math.max(1e-4, 1 - bounce) : void 0);
|
|
67
|
-
if (dampingRatio !== void 0) invariant(dampingRatio >= 0, "Damping ratio must be greater than or equal to 0");
|
|
68
|
-
if (duration !== void 0) invariant(duration > 0, "Duration must be greater than 0");
|
|
69
|
-
invariant(displacement !== 0, "Displacement must not be 0");
|
|
70
|
-
invariant(precision >= 0, "Precision must be greater than or equal to 0");
|
|
71
|
-
this.precision = precision;
|
|
72
|
-
this.precisionMultiplier = 10 ** precision;
|
|
73
|
-
this.restingMagnitude = .5 / this.precisionMultiplier;
|
|
74
|
-
const hasM = mass !== void 0;
|
|
75
|
-
const hasK = tension !== void 0;
|
|
76
|
-
const hasC = damping !== void 0;
|
|
77
|
-
const hasZ = dampingRatio !== void 0;
|
|
78
|
-
const hasT = duration !== void 0;
|
|
79
|
-
if (hasK && hasC && !hasZ && !hasT) {
|
|
80
|
-
this.mass = mass ?? 1;
|
|
81
|
-
this.tension = tension;
|
|
82
|
-
this.damping = damping;
|
|
83
|
-
} else if (hasK && hasZ && !hasC && !hasT) {
|
|
84
|
-
this.mass = mass ?? 1;
|
|
85
|
-
this.tension = tension;
|
|
86
|
-
this.damping = 2 * dampingRatio * Math.sqrt(this.mass * tension);
|
|
87
|
-
} else if (hasC && hasZ && !hasK && !hasT) {
|
|
88
|
-
invariant(dampingRatio > 0, "dampingRatio must be > 0 to derive tension");
|
|
89
|
-
this.mass = mass ?? 1;
|
|
90
|
-
this.tension = damping ** 2 / (4 * dampingRatio ** 2 * this.mass);
|
|
91
|
-
this.damping = damping;
|
|
92
|
-
} else if (hasK && hasC && hasZ && !hasT) {
|
|
93
|
-
invariant(dampingRatio > 0, "dampingRatio must be > 0 to derive mass");
|
|
94
|
-
this.mass = damping ** 2 / (4 * dampingRatio ** 2 * tension);
|
|
95
|
-
this.tension = tension;
|
|
96
|
-
this.damping = damping;
|
|
97
|
-
} else if (hasZ && hasT) {
|
|
98
|
-
const threshold = .005;
|
|
99
|
-
const x0 = Math.abs(displacement);
|
|
100
|
-
invariant(x0 > threshold, "displacement must be greater than the precision threshold");
|
|
101
|
-
let sigmaCoeff;
|
|
102
|
-
if (dampingRatio < 1) sigmaCoeff = dampingRatio;
|
|
103
|
-
else if (dampingRatio === 1) sigmaCoeff = 1;
|
|
104
|
-
else sigmaCoeff = dampingRatio - Math.sqrt(dampingRatio ** 2 - 1);
|
|
105
|
-
invariant(sigmaCoeff > 0, "dampingRatio must be > 0 for duration-based config");
|
|
106
|
-
const wn = 2 * Math.log(x0 / threshold) / (sigmaCoeff * duration);
|
|
107
|
-
if (!hasK && !hasC) {
|
|
108
|
-
this.mass = mass ?? 1;
|
|
109
|
-
this.tension = wn ** 2 * this.mass;
|
|
110
|
-
this.damping = 2 * dampingRatio * this.mass * wn;
|
|
111
|
-
} else if (hasK && !hasM && !hasC) {
|
|
112
|
-
this.mass = tension / wn ** 2;
|
|
113
|
-
this.tension = tension;
|
|
114
|
-
this.damping = 2 * dampingRatio * this.mass * wn;
|
|
115
|
-
} else if (hasC && !hasM && !hasK) {
|
|
116
|
-
this.mass = damping / (2 * dampingRatio * wn);
|
|
117
|
-
this.tension = wn ** 2 * this.mass;
|
|
118
|
-
this.damping = damping;
|
|
119
|
-
} else throw new Error("Invalid spring config: provide one of the supported input shapes.");
|
|
120
|
-
} else throw new Error("Invalid spring config: provide one of the supported input shapes.");
|
|
121
|
-
this.naturalFrequency = Math.sqrt(this.tension / this.mass);
|
|
122
|
-
this.criticalDamping = 2 * this.mass * this.naturalFrequency;
|
|
123
|
-
this.dampingRatio = this.damping / this.criticalDamping;
|
|
124
|
-
}
|
|
125
|
-
/** @internal Copies physical parameters from `source` onto this config and bumps `_version`. */
|
|
126
|
-
assign(source) {
|
|
127
|
-
this._version++;
|
|
128
|
-
const t = this;
|
|
129
|
-
t.mass = source.mass;
|
|
130
|
-
t.tension = source.tension;
|
|
131
|
-
t.damping = source.damping;
|
|
132
|
-
t.precision = source.precision;
|
|
133
|
-
t.naturalFrequency = source.naturalFrequency;
|
|
134
|
-
t.criticalDamping = source.criticalDamping;
|
|
135
|
-
t.dampingRatio = source.dampingRatio;
|
|
136
|
-
t.precisionMultiplier = source.precisionMultiplier;
|
|
137
|
-
t.restingMagnitude = source.restingMagnitude;
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Analytically estimates the time remaining for a spring to come to rest,
|
|
141
|
-
* given the current displacement and velocity.
|
|
142
|
-
*
|
|
143
|
-
* Uses the exponential decay envelope common to all three damping regimes.
|
|
144
|
-
* The decay rate depends on the regime:
|
|
145
|
-
* - Underdamped (ζ < 1): σ = ζωₙ
|
|
146
|
-
* - Critically damped (ζ = 1): σ = ωₙ
|
|
147
|
-
* - Overdamped (ζ > 1): σ = (ζ - √(ζ²-1))ωₙ (the slower eigenvalue)
|
|
148
|
-
*
|
|
149
|
-
* The effective initial amplitude accounts for both displacement and velocity,
|
|
150
|
-
* since kinetic energy can convert to additional displacement:
|
|
151
|
-
* A₀ = |x₀| + |v₀| / ωₙ
|
|
152
|
-
*
|
|
153
|
-
* Settling time: t = ln(A₀ / threshold) / σ, with a 2× safety factor
|
|
154
|
-
* to account for polynomial terms in the critically damped solution.
|
|
155
|
-
*
|
|
156
|
-
* Returns the estimated time in milliseconds.
|
|
157
|
-
*/
|
|
158
|
-
computeTimeRemaining(state) {
|
|
159
|
-
const { position, velocity } = state;
|
|
160
|
-
const a0 = Math.abs(position) + Math.abs(velocity) / this.naturalFrequency;
|
|
161
|
-
if (a0 <= this.restingMagnitude) return 0;
|
|
162
|
-
let sigma;
|
|
163
|
-
if (this.dampingRatio < 1) sigma = this.dampingRatio * this.naturalFrequency;
|
|
164
|
-
else if (this.dampingRatio === 1) sigma = this.naturalFrequency;
|
|
165
|
-
else sigma = (this.dampingRatio - Math.sqrt(this.dampingRatio * this.dampingRatio - 1)) * this.naturalFrequency;
|
|
166
|
-
if (sigma <= 0) return Infinity;
|
|
167
|
-
return 2 * Math.log(a0 / this.restingMagnitude) / sigma * 1e3;
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
function defineSpring(input) {
|
|
171
|
-
return new SpringConfig(input);
|
|
172
|
-
}
|
|
173
|
-
//#endregion
|
|
174
|
-
//#region src/emitter.ts
|
|
175
|
-
var Emitter = class {
|
|
176
|
-
#update = [];
|
|
177
|
-
#start = [];
|
|
178
|
-
#stop = [];
|
|
179
|
-
on(type, handler) {
|
|
180
|
-
this.#list(type).push(handler);
|
|
181
|
-
return () => {
|
|
182
|
-
this.off(type, handler);
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
off(type, handler) {
|
|
186
|
-
const list = this.#list(type);
|
|
187
|
-
if (handler) list.splice(list.indexOf(handler) >>> 0, 1);
|
|
188
|
-
else list.length = 0;
|
|
189
|
-
}
|
|
190
|
-
clear() {
|
|
191
|
-
this.#update.length = 0;
|
|
192
|
-
this.#start.length = 0;
|
|
193
|
-
this.#stop.length = 0;
|
|
194
|
-
}
|
|
195
|
-
emit(type) {
|
|
196
|
-
const list = this.#list(type);
|
|
197
|
-
if (list.length === 1) list[0]();
|
|
198
|
-
else if (list.length > 1) for (const handler of list.slice()) handler();
|
|
199
|
-
}
|
|
200
|
-
#list(type) {
|
|
201
|
-
switch (type) {
|
|
202
|
-
case "update": return this.#update;
|
|
203
|
-
case "start": return this.#start;
|
|
204
|
-
case "stop": return this.#stop;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
//#endregion
|
|
209
|
-
//#region src/state.ts
|
|
210
|
-
var State = class {
|
|
211
|
-
#config;
|
|
212
|
-
#position;
|
|
213
|
-
#velocity;
|
|
214
|
-
constructor(config, position, velocity) {
|
|
215
|
-
this.#config = config;
|
|
216
|
-
this.#position = position;
|
|
217
|
-
this.#velocity = velocity;
|
|
218
|
-
}
|
|
219
|
-
configure(config) {
|
|
220
|
-
this.#config = config;
|
|
221
|
-
}
|
|
222
|
-
/** Returns the position rounded to the configured precision. */
|
|
223
|
-
get position() {
|
|
224
|
-
return Math.round(this.#position * this.#config.precisionMultiplier) / this.#config.precisionMultiplier;
|
|
225
|
-
}
|
|
226
|
-
set position(value) {
|
|
227
|
-
this.#position = value;
|
|
228
|
-
}
|
|
229
|
-
/** Returns the velocity rounded to the configured precision. */
|
|
230
|
-
get velocity() {
|
|
231
|
-
return Math.round(this.#velocity * this.#config.precisionMultiplier) / this.#config.precisionMultiplier;
|
|
232
|
-
}
|
|
233
|
-
set velocity(value) {
|
|
234
|
-
this.#velocity = value;
|
|
235
|
-
}
|
|
236
|
-
/** A spring is resting when its rounded position and velocity are both zero. */
|
|
237
|
-
get isResting() {
|
|
238
|
-
return this.position === 0 && this.velocity === 0;
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
//#endregion
|
|
242
|
-
//#region src/solver.ts
|
|
243
|
-
var UnderdampedSolver = class {
|
|
244
|
-
#state;
|
|
245
|
-
#dampedFrequency = 0;
|
|
246
|
-
#decayRate = 0;
|
|
247
|
-
#t = 0;
|
|
248
|
-
#c1 = 0;
|
|
249
|
-
#c2 = 0;
|
|
250
|
-
constructor(state) {
|
|
251
|
-
this.#state = state;
|
|
252
|
-
}
|
|
253
|
-
configure(config) {
|
|
254
|
-
if (config) {
|
|
255
|
-
this.#decayRate = config.dampingRatio * config.naturalFrequency;
|
|
256
|
-
this.#dampedFrequency = config.naturalFrequency * Math.sqrt(1 - config.dampingRatio ** 2);
|
|
257
|
-
}
|
|
258
|
-
this.#t = 0;
|
|
259
|
-
this.#c1 = this.#state.position;
|
|
260
|
-
this.#c2 = (this.#state.velocity + this.#decayRate * this.#state.position) / this.#dampedFrequency;
|
|
261
|
-
}
|
|
262
|
-
tick(dt) {
|
|
263
|
-
this.#t += dt;
|
|
264
|
-
const sin = Math.sin(this.#dampedFrequency * this.#t);
|
|
265
|
-
const cos = Math.cos(this.#dampedFrequency * this.#t);
|
|
266
|
-
const decay = Math.exp(-this.#decayRate * this.#t);
|
|
267
|
-
const decayVelocity = -this.#decayRate * decay;
|
|
268
|
-
const oscillation = this.#c1 * cos + this.#c2 * sin;
|
|
269
|
-
const oscillationVelocity = -this.#c1 * this.#dampedFrequency * sin + this.#c2 * this.#dampedFrequency * cos;
|
|
270
|
-
this.#state.position = decay * oscillation;
|
|
271
|
-
this.#state.velocity = decay * oscillationVelocity + decayVelocity * oscillation;
|
|
272
|
-
}
|
|
273
|
-
};
|
|
274
|
-
var CriticallyDampedSolver = class {
|
|
275
|
-
#state;
|
|
276
|
-
#naturalFrequency = 0;
|
|
277
|
-
#t = 0;
|
|
278
|
-
#c1 = 0;
|
|
279
|
-
#c2 = 0;
|
|
280
|
-
constructor(state) {
|
|
281
|
-
this.#state = state;
|
|
282
|
-
}
|
|
283
|
-
configure(config) {
|
|
284
|
-
if (config) this.#naturalFrequency = config.naturalFrequency;
|
|
285
|
-
this.#t = 0;
|
|
286
|
-
this.#c1 = this.#state.position;
|
|
287
|
-
this.#c2 = this.#state.velocity + this.#naturalFrequency * this.#state.position;
|
|
288
|
-
}
|
|
289
|
-
tick(dt) {
|
|
290
|
-
this.#t += dt;
|
|
291
|
-
const decay = Math.exp(-this.#naturalFrequency * this.#t);
|
|
292
|
-
const decayVelocity = -this.#naturalFrequency * decay;
|
|
293
|
-
const scale = this.#c1 + this.#c2 * this.#t;
|
|
294
|
-
const scaleVelocity = this.#c2;
|
|
295
|
-
this.#state.position = scale * decay;
|
|
296
|
-
this.#state.velocity = scaleVelocity * decay + decayVelocity * scale;
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
var OverdampedSolver = class {
|
|
300
|
-
#state;
|
|
301
|
-
#dampedFrequency = 0;
|
|
302
|
-
#decayRate = 0;
|
|
303
|
-
#t = 0;
|
|
304
|
-
#c1 = 0;
|
|
305
|
-
#c2 = 0;
|
|
306
|
-
constructor(state) {
|
|
307
|
-
this.#state = state;
|
|
308
|
-
}
|
|
309
|
-
configure(config) {
|
|
310
|
-
if (config) {
|
|
311
|
-
this.#decayRate = config.dampingRatio * config.naturalFrequency;
|
|
312
|
-
this.#dampedFrequency = config.naturalFrequency * Math.sqrt(config.dampingRatio ** 2 - 1);
|
|
313
|
-
}
|
|
314
|
-
this.#t = 0;
|
|
315
|
-
this.#c1 = this.#state.velocity + this.#decayRate * this.#state.position;
|
|
316
|
-
this.#c2 = this.#state.position * this.#dampedFrequency;
|
|
317
|
-
}
|
|
318
|
-
tick(dt) {
|
|
319
|
-
this.#t += dt;
|
|
320
|
-
const decay = Math.exp(-this.#decayRate * this.#t);
|
|
321
|
-
const decayVelocity = -this.#decayRate * decay;
|
|
322
|
-
const clamped = Math.min(this.#dampedFrequency * this.#t, 300);
|
|
323
|
-
const sinh = Math.sinh(clamped);
|
|
324
|
-
const cosh = Math.cosh(clamped);
|
|
325
|
-
const scale = this.#c1 * sinh + this.#c2 * cosh;
|
|
326
|
-
const scaleVelocity = this.#c1 * this.#dampedFrequency * cosh + this.#c2 * this.#dampedFrequency * sinh;
|
|
327
|
-
this.#state.position = scale * decay / this.#dampedFrequency;
|
|
328
|
-
this.#state.velocity = (scale * decayVelocity + scaleVelocity * decay) / this.#dampedFrequency;
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
//#endregion
|
|
332
|
-
//#region src/motion.ts
|
|
333
|
-
var Motion = class {
|
|
334
|
-
#config;
|
|
335
|
-
#state;
|
|
336
|
-
#underdampedSolver = null;
|
|
337
|
-
#criticallyDampedSolver = null;
|
|
338
|
-
#overdampedSolver = null;
|
|
339
|
-
#currentSolver = null;
|
|
340
|
-
#needsUpdate = false;
|
|
341
|
-
#needsReset = false;
|
|
342
|
-
#configVersion = 0;
|
|
343
|
-
#timeRemaining = 0;
|
|
344
|
-
#emitter;
|
|
345
|
-
constructor(config, position, velocity) {
|
|
346
|
-
this.#config = config;
|
|
347
|
-
this.#state = new State(config, position, velocity);
|
|
348
|
-
this.#emitter = new Emitter();
|
|
349
|
-
this.#updateSolver();
|
|
350
|
-
this.#timeRemaining = this.#config.computeTimeRemaining(this.#state);
|
|
351
|
-
}
|
|
352
|
-
get position() {
|
|
353
|
-
return this.#state.position;
|
|
354
|
-
}
|
|
355
|
-
set position(value) {
|
|
356
|
-
this.#state.position = value;
|
|
357
|
-
this.#needsReset = true;
|
|
358
|
-
if (!this.#state.isResting) this.#emitter.emit("start");
|
|
359
|
-
}
|
|
360
|
-
get velocity() {
|
|
361
|
-
return this.#state.velocity;
|
|
362
|
-
}
|
|
363
|
-
set velocity(value) {
|
|
364
|
-
this.#state.velocity = value;
|
|
365
|
-
this.#needsReset = true;
|
|
366
|
-
}
|
|
367
|
-
get timeRemaining() {
|
|
368
|
-
return this.#timeRemaining;
|
|
369
|
-
}
|
|
370
|
-
get isResting() {
|
|
371
|
-
return this.#state.isResting;
|
|
372
|
-
}
|
|
373
|
-
configure(config) {
|
|
374
|
-
this.#config = config;
|
|
375
|
-
this.#state.configure(config);
|
|
376
|
-
this.#configVersion = config._version;
|
|
377
|
-
this.#needsUpdate = true;
|
|
378
|
-
}
|
|
379
|
-
tick(dt, emit = true) {
|
|
380
|
-
invariant(this.#currentSolver, "Cannot tick a disposed motion");
|
|
381
|
-
if (this.#config._version !== this.#configVersion) {
|
|
382
|
-
this.#state.configure(this.#config);
|
|
383
|
-
this.#configVersion = this.#config._version;
|
|
384
|
-
this.#needsUpdate = true;
|
|
385
|
-
}
|
|
386
|
-
const needsTimeRemaining = this.#needsUpdate || this.#needsReset;
|
|
387
|
-
if (this.#needsUpdate) {
|
|
388
|
-
this.#updateSolver();
|
|
389
|
-
this.#needsUpdate = false;
|
|
390
|
-
this.#needsReset = false;
|
|
391
|
-
} else if (this.#needsReset) {
|
|
392
|
-
this.#currentSolver.configure();
|
|
393
|
-
this.#needsReset = false;
|
|
394
|
-
}
|
|
395
|
-
if (needsTimeRemaining) this.#timeRemaining = this.#config.computeTimeRemaining(this.#state);
|
|
396
|
-
this.#currentSolver.tick(dt);
|
|
397
|
-
this.#timeRemaining = Math.max(0, this.#timeRemaining - dt * 1e3);
|
|
398
|
-
if (emit) {
|
|
399
|
-
this.#emitter.emit("update");
|
|
400
|
-
if (this.#state.isResting) {
|
|
401
|
-
this.#timeRemaining = 0;
|
|
402
|
-
this.#emitter.emit("stop");
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
onUpdate(callback) {
|
|
407
|
-
return this.#emitter.on("update", callback);
|
|
408
|
-
}
|
|
409
|
-
onStart(callback) {
|
|
410
|
-
return this.#emitter.on("start", callback);
|
|
411
|
-
}
|
|
412
|
-
onStop(callback) {
|
|
413
|
-
return this.#emitter.on("stop", callback);
|
|
414
|
-
}
|
|
415
|
-
dispose() {
|
|
416
|
-
this.#emitter.clear();
|
|
417
|
-
this.#underdampedSolver = null;
|
|
418
|
-
this.#criticallyDampedSolver = null;
|
|
419
|
-
this.#overdampedSolver = null;
|
|
420
|
-
this.#currentSolver = null;
|
|
421
|
-
}
|
|
422
|
-
#updateSolver() {
|
|
423
|
-
if (this.#config.dampingRatio < 1) {
|
|
424
|
-
this.#underdampedSolver ||= new UnderdampedSolver(this.#state);
|
|
425
|
-
this.#currentSolver = this.#underdampedSolver;
|
|
426
|
-
} else if (this.#config.dampingRatio === 1) {
|
|
427
|
-
this.#criticallyDampedSolver ||= new CriticallyDampedSolver(this.#state);
|
|
428
|
-
this.#currentSolver = this.#criticallyDampedSolver;
|
|
429
|
-
} else {
|
|
430
|
-
this.#overdampedSolver ||= new OverdampedSolver(this.#state);
|
|
431
|
-
this.#currentSolver = this.#overdampedSolver;
|
|
432
|
-
}
|
|
433
|
-
this.#currentSolver.configure(this.#config);
|
|
434
|
-
}
|
|
435
|
-
};
|
|
436
|
-
//#endregion
|
|
437
|
-
//#region src/spring.ts
|
|
438
|
-
function normalizeTarget(target) {
|
|
439
|
-
if (target instanceof Spring) return {
|
|
440
|
-
spring: target,
|
|
441
|
-
offset: 0
|
|
442
|
-
};
|
|
443
|
-
if (typeof target === "object" && target !== null && "spring" in target && target.spring instanceof Spring) return {
|
|
444
|
-
spring: target.spring,
|
|
445
|
-
offset: target.offset ?? 0
|
|
446
|
-
};
|
|
447
|
-
return null;
|
|
448
|
-
}
|
|
449
|
-
var Spring = class {
|
|
450
|
-
#target;
|
|
451
|
-
#config;
|
|
452
|
-
#motion;
|
|
453
|
-
#motions;
|
|
454
|
-
#leader = null;
|
|
455
|
-
#offset = 0;
|
|
456
|
-
#ownsConfig;
|
|
457
|
-
#unsubLeader = null;
|
|
458
|
-
constructor(motions, position, config) {
|
|
459
|
-
this.#motions = motions;
|
|
460
|
-
let numericTarget;
|
|
461
|
-
let value;
|
|
462
|
-
let normalized = null;
|
|
463
|
-
if (typeof position === "number") {
|
|
464
|
-
numericTarget = position;
|
|
465
|
-
value = position;
|
|
466
|
-
} else {
|
|
467
|
-
normalized = normalizeTarget(position.target);
|
|
468
|
-
if (normalized) {
|
|
469
|
-
numericTarget = normalized.spring.#target + normalized.spring.#motion.position + normalized.offset;
|
|
470
|
-
value = position.value ?? numericTarget;
|
|
471
|
-
} else {
|
|
472
|
-
numericTarget = position.target ?? position.value ?? 0;
|
|
473
|
-
value = position.value ?? numericTarget;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
const hasOverride = config !== void 0;
|
|
477
|
-
this.#ownsConfig = hasOverride || !normalized;
|
|
478
|
-
if (normalized && !hasOverride) this.#config = normalized.spring.#config;
|
|
479
|
-
else this.#config = config ?? SpringConfig.default;
|
|
480
|
-
this.#target = numericTarget;
|
|
481
|
-
this.#motion = new Motion(this.#config, value - numericTarget, 0);
|
|
482
|
-
if (!this.#motion.isResting) this.#motions.add(this.#motion);
|
|
483
|
-
if (normalized) {
|
|
484
|
-
this.#leader = normalized.spring;
|
|
485
|
-
this.#offset = normalized.offset;
|
|
486
|
-
this.#unsubLeader = normalized.spring.onUpdate(() => {
|
|
487
|
-
this.#setTarget(this.#leader.#target + this.#leader.#motion.position + this.#offset);
|
|
488
|
-
});
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
get target() {
|
|
492
|
-
return this.#target;
|
|
493
|
-
}
|
|
494
|
-
set target(value) {
|
|
495
|
-
if (typeof value === "number") {
|
|
496
|
-
this.#unfollow();
|
|
497
|
-
this.#setTarget(value);
|
|
498
|
-
} else {
|
|
499
|
-
const normalized = normalizeTarget(value);
|
|
500
|
-
this.#follow(normalized.spring, normalized.offset);
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
get value() {
|
|
504
|
-
return this.#target + this.#motion.position;
|
|
505
|
-
}
|
|
506
|
-
set value(value) {
|
|
507
|
-
const position = value - this.#target;
|
|
508
|
-
if (position !== this.#motion.position) {
|
|
509
|
-
this.#motions.add(this.#motion);
|
|
510
|
-
this.#motion.position = position;
|
|
511
|
-
this.#motion.tick(0);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
get velocity() {
|
|
515
|
-
return this.#motion.velocity;
|
|
516
|
-
}
|
|
517
|
-
set velocity(value) {
|
|
518
|
-
this.#motions.add(this.#motion);
|
|
519
|
-
this.#motion.velocity = value;
|
|
520
|
-
}
|
|
521
|
-
get config() {
|
|
522
|
-
return this.#config;
|
|
523
|
-
}
|
|
524
|
-
get mass() {
|
|
525
|
-
return this.#config.mass;
|
|
526
|
-
}
|
|
527
|
-
get tension() {
|
|
528
|
-
return this.#config.tension;
|
|
529
|
-
}
|
|
530
|
-
get damping() {
|
|
531
|
-
return this.#config.damping;
|
|
532
|
-
}
|
|
533
|
-
get dampingRatio() {
|
|
534
|
-
return this.#config.dampingRatio;
|
|
535
|
-
}
|
|
536
|
-
get precision() {
|
|
537
|
-
return this.#config.precision;
|
|
538
|
-
}
|
|
539
|
-
set config(value) {
|
|
540
|
-
if (value) {
|
|
541
|
-
if (this.#leader && !this.#ownsConfig) {
|
|
542
|
-
this.#ownsConfig = true;
|
|
543
|
-
this.#config = new SpringConfig({
|
|
544
|
-
tension: value.tension,
|
|
545
|
-
damping: value.damping,
|
|
546
|
-
mass: value.mass,
|
|
547
|
-
precision: value.precision
|
|
548
|
-
});
|
|
549
|
-
this.#motion.configure(this.#config);
|
|
550
|
-
} else this.#config.assign(value);
|
|
551
|
-
this.#motions.add(this.#motion);
|
|
552
|
-
} else if (this.#ownsConfig) {
|
|
553
|
-
this.#ownsConfig = false;
|
|
554
|
-
this.#config = this.#leader ? this.#leader.#config : SpringConfig.default;
|
|
555
|
-
this.#motion.configure(this.#config);
|
|
556
|
-
this.#motions.add(this.#motion);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
get timeRemaining() {
|
|
560
|
-
return this.#motion.timeRemaining;
|
|
561
|
-
}
|
|
562
|
-
get isResting() {
|
|
563
|
-
return this.#motion.isResting;
|
|
564
|
-
}
|
|
565
|
-
jumpTo(value) {
|
|
566
|
-
this.#target = value;
|
|
567
|
-
this.#motion.position = 0;
|
|
568
|
-
this.#motion.velocity = 0;
|
|
569
|
-
this.#motion.tick(0);
|
|
570
|
-
}
|
|
571
|
-
dispose() {
|
|
572
|
-
if (this.#unsubLeader) {
|
|
573
|
-
this.#unsubLeader();
|
|
574
|
-
this.#unsubLeader = null;
|
|
575
|
-
}
|
|
576
|
-
this.#motions.remove(this.#motion);
|
|
577
|
-
this.#motion.dispose();
|
|
578
|
-
}
|
|
579
|
-
onUpdate(callback) {
|
|
580
|
-
return this.#motion.onUpdate(callback);
|
|
581
|
-
}
|
|
582
|
-
onStart(callback) {
|
|
583
|
-
return this.#motion.onStart(callback);
|
|
584
|
-
}
|
|
585
|
-
onStop(callback) {
|
|
586
|
-
return this.#motion.onStop(callback);
|
|
587
|
-
}
|
|
588
|
-
#setTarget(value) {
|
|
589
|
-
if (value !== this.#target) {
|
|
590
|
-
this.#motions.add(this.#motion);
|
|
591
|
-
const rawValue = this.#target + this.#motion.position;
|
|
592
|
-
this.#target = value;
|
|
593
|
-
this.#motion.position = rawValue - this.#target;
|
|
594
|
-
this.#motion.tick(0);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
#follow(leader, offset) {
|
|
598
|
-
if (this.#unsubLeader) this.#unsubLeader();
|
|
599
|
-
this.#leader = leader;
|
|
600
|
-
this.#offset = offset;
|
|
601
|
-
if (!this.#ownsConfig) {
|
|
602
|
-
this.#config = leader.#config;
|
|
603
|
-
this.#motion.configure(this.#config);
|
|
604
|
-
}
|
|
605
|
-
this.#unsubLeader = leader.onUpdate(() => {
|
|
606
|
-
this.#setTarget(this.#leader.#target + this.#leader.#motion.position + this.#offset);
|
|
607
|
-
});
|
|
608
|
-
this.#setTarget(leader.#target + leader.#motion.position + offset);
|
|
609
|
-
}
|
|
610
|
-
#unfollow() {
|
|
611
|
-
if (!this.#leader) return;
|
|
612
|
-
this.#unsubLeader();
|
|
613
|
-
this.#unsubLeader = null;
|
|
614
|
-
this.#leader = null;
|
|
615
|
-
this.#offset = 0;
|
|
616
|
-
if (!this.#ownsConfig) {
|
|
617
|
-
this.#ownsConfig = true;
|
|
618
|
-
this.#config = new SpringConfig({
|
|
619
|
-
tension: this.#config.tension,
|
|
620
|
-
damping: this.#config.damping,
|
|
621
|
-
mass: this.#config.mass,
|
|
622
|
-
precision: this.#config.precision
|
|
623
|
-
});
|
|
624
|
-
this.#motion.configure(this.#config);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
};
|
|
628
|
-
//#endregion
|
|
629
|
-
//#region src/vector2.ts
|
|
630
|
-
function isVector2(value) {
|
|
631
|
-
return typeof value === "object" && value !== null && "x" in value && typeof value.x === "number";
|
|
632
|
-
}
|
|
633
|
-
//#endregion
|
|
634
|
-
//#region src/spring2d.ts
|
|
635
|
-
function normalizeTarget2D(target) {
|
|
636
|
-
if (target instanceof Spring2D) return {
|
|
637
|
-
spring: target,
|
|
638
|
-
offset: void 0
|
|
639
|
-
};
|
|
640
|
-
if (typeof target === "object" && target !== null && "spring" in target && target.spring instanceof Spring2D) return {
|
|
641
|
-
spring: target.spring,
|
|
642
|
-
offset: target.offset
|
|
643
|
-
};
|
|
644
|
-
return null;
|
|
645
|
-
}
|
|
646
|
-
function toScalarTarget(spring, offset) {
|
|
647
|
-
return offset ? {
|
|
648
|
-
spring,
|
|
649
|
-
offset
|
|
650
|
-
} : spring;
|
|
651
|
-
}
|
|
652
|
-
function toScalarPos(target, value) {
|
|
653
|
-
if (typeof target === "number") return value !== void 0 ? {
|
|
654
|
-
target,
|
|
655
|
-
value
|
|
656
|
-
} : target;
|
|
657
|
-
return {
|
|
658
|
-
target,
|
|
659
|
-
value
|
|
660
|
-
};
|
|
661
|
-
}
|
|
662
|
-
var Spring2D = class Spring2D {
|
|
663
|
-
#x;
|
|
664
|
-
#y;
|
|
665
|
-
#value = {
|
|
666
|
-
x: 0,
|
|
667
|
-
y: 0
|
|
668
|
-
};
|
|
669
|
-
#velocity = {
|
|
670
|
-
x: 0,
|
|
671
|
-
y: 0
|
|
672
|
-
};
|
|
673
|
-
constructor(motions, position, config) {
|
|
674
|
-
let xPos;
|
|
675
|
-
let yPos;
|
|
676
|
-
if (isVector2(position)) {
|
|
677
|
-
xPos = position.x;
|
|
678
|
-
yPos = position.y;
|
|
679
|
-
} else {
|
|
680
|
-
const normalized = normalizeTarget2D(position.target);
|
|
681
|
-
if (normalized) {
|
|
682
|
-
const lx = normalized.spring.#x;
|
|
683
|
-
const ly = normalized.spring.#y;
|
|
684
|
-
const xTarget = toScalarTarget(lx, normalized.offset?.x);
|
|
685
|
-
const yTarget = toScalarTarget(ly, normalized.offset?.y);
|
|
686
|
-
xPos = toScalarPos(xTarget, position.value?.x);
|
|
687
|
-
yPos = toScalarPos(yTarget, position.value?.y);
|
|
688
|
-
} else if (isVector2(position.target)) {
|
|
689
|
-
const t = position.target;
|
|
690
|
-
xPos = {
|
|
691
|
-
target: t.x,
|
|
692
|
-
value: position.value?.x
|
|
693
|
-
};
|
|
694
|
-
yPos = {
|
|
695
|
-
target: t.y,
|
|
696
|
-
value: position.value?.y
|
|
697
|
-
};
|
|
698
|
-
} else {
|
|
699
|
-
xPos = {
|
|
700
|
-
target: position.target,
|
|
701
|
-
value: position.value?.x
|
|
702
|
-
};
|
|
703
|
-
yPos = {
|
|
704
|
-
target: void 0,
|
|
705
|
-
value: position.value?.y
|
|
706
|
-
};
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
this.#x = new Spring(motions, xPos, config);
|
|
710
|
-
this.#y = new Spring(motions, yPos, config);
|
|
711
|
-
}
|
|
712
|
-
get target() {
|
|
713
|
-
return {
|
|
714
|
-
x: this.#x.target,
|
|
715
|
-
y: this.#y.target
|
|
716
|
-
};
|
|
717
|
-
}
|
|
718
|
-
set target(value) {
|
|
719
|
-
if (value instanceof Spring2D) {
|
|
720
|
-
this.#x.target = value.#x;
|
|
721
|
-
this.#y.target = value.#y;
|
|
722
|
-
} else if ("spring" in value && value.spring instanceof Spring2D) {
|
|
723
|
-
const { spring, offset } = value;
|
|
724
|
-
this.#x.target = toScalarTarget(spring.#x, offset?.x);
|
|
725
|
-
this.#y.target = toScalarTarget(spring.#y, offset?.y);
|
|
726
|
-
} else {
|
|
727
|
-
const v = value;
|
|
728
|
-
this.#x.target = v.x;
|
|
729
|
-
this.#y.target = v.y;
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
get value() {
|
|
733
|
-
this.#value.x = this.#x.value;
|
|
734
|
-
this.#value.y = this.#y.value;
|
|
735
|
-
return this.#value;
|
|
736
|
-
}
|
|
737
|
-
set value(value) {
|
|
738
|
-
this.#x.value = value.x;
|
|
739
|
-
this.#y.value = value.y;
|
|
740
|
-
}
|
|
741
|
-
get velocity() {
|
|
742
|
-
this.#velocity.x = this.#x.velocity;
|
|
743
|
-
this.#velocity.y = this.#y.velocity;
|
|
744
|
-
return this.#velocity;
|
|
745
|
-
}
|
|
746
|
-
set velocity(value) {
|
|
747
|
-
this.#x.velocity = value.x;
|
|
748
|
-
this.#y.velocity = value.y;
|
|
749
|
-
}
|
|
750
|
-
get config() {
|
|
751
|
-
return this.#x.config;
|
|
752
|
-
}
|
|
753
|
-
get mass() {
|
|
754
|
-
return this.#x.mass;
|
|
755
|
-
}
|
|
756
|
-
get tension() {
|
|
757
|
-
return this.#x.tension;
|
|
758
|
-
}
|
|
759
|
-
get damping() {
|
|
760
|
-
return this.#x.damping;
|
|
761
|
-
}
|
|
762
|
-
get dampingRatio() {
|
|
763
|
-
return this.#x.dampingRatio;
|
|
764
|
-
}
|
|
765
|
-
get precision() {
|
|
766
|
-
return this.#x.precision;
|
|
767
|
-
}
|
|
768
|
-
set config(value) {
|
|
769
|
-
this.#x.config = value;
|
|
770
|
-
this.#y.config = value;
|
|
771
|
-
}
|
|
772
|
-
get timeRemaining() {
|
|
773
|
-
return Math.max(this.#x.timeRemaining, this.#y.timeRemaining);
|
|
774
|
-
}
|
|
775
|
-
get isResting() {
|
|
776
|
-
return this.#x.isResting && this.#y.isResting;
|
|
777
|
-
}
|
|
778
|
-
jumpTo(value) {
|
|
779
|
-
this.#x.jumpTo(value.x);
|
|
780
|
-
this.#y.jumpTo(value.y);
|
|
781
|
-
}
|
|
782
|
-
dispose() {
|
|
783
|
-
this.#x.dispose();
|
|
784
|
-
this.#y.dispose();
|
|
785
|
-
}
|
|
786
|
-
onUpdate(callback) {
|
|
787
|
-
const a = this.#x.onUpdate(callback);
|
|
788
|
-
const b = this.#y.onUpdate(callback);
|
|
789
|
-
return () => {
|
|
790
|
-
a();
|
|
791
|
-
b();
|
|
792
|
-
};
|
|
793
|
-
}
|
|
794
|
-
onStart(callback) {
|
|
795
|
-
const a = this.#x.onStart(callback);
|
|
796
|
-
const b = this.#y.onStart(callback);
|
|
797
|
-
return () => {
|
|
798
|
-
a();
|
|
799
|
-
b();
|
|
800
|
-
};
|
|
801
|
-
}
|
|
802
|
-
onStop(callback) {
|
|
803
|
-
const check = () => {
|
|
804
|
-
if (this.isResting) callback();
|
|
805
|
-
};
|
|
806
|
-
const a = this.#x.onStop(check);
|
|
807
|
-
const b = this.#y.onStop(check);
|
|
808
|
-
return () => {
|
|
809
|
-
a();
|
|
810
|
-
b();
|
|
811
|
-
};
|
|
812
|
-
}
|
|
813
|
-
};
|
|
814
|
-
//#endregion
|
|
815
|
-
//#region src/ticker.ts
|
|
816
|
-
const hasWindow = typeof window !== "undefined";
|
|
817
|
-
const request = hasWindow ? (cb) => window.requestAnimationFrame(cb) : (cb) => setTimeout(cb, 1);
|
|
818
|
-
const cancel = hasWindow ? (id) => window.cancelAnimationFrame(id) : (id) => clearTimeout(id);
|
|
819
|
-
var Ticker = class {
|
|
820
|
-
#fps;
|
|
821
|
-
#gap;
|
|
822
|
-
#lagThreshold;
|
|
823
|
-
#adjustedLag;
|
|
824
|
-
#motion;
|
|
825
|
-
#frame = 0;
|
|
826
|
-
#time = 0;
|
|
827
|
-
#previousTime = 0;
|
|
828
|
-
#delta = 0;
|
|
829
|
-
#nextTime;
|
|
830
|
-
#lastWallTime = 0;
|
|
831
|
-
#id = 0;
|
|
832
|
-
#stopped = true;
|
|
833
|
-
constructor(motions, options) {
|
|
834
|
-
this.#motion = motions;
|
|
835
|
-
const fps = options?.fps ?? 60;
|
|
836
|
-
const lagThreshold = options?.lagThreshold ?? 500;
|
|
837
|
-
const adjustedLag = options?.adjustedLag ?? 33;
|
|
838
|
-
invariant(fps > 0, "FPS must be greater than 0");
|
|
839
|
-
invariant(lagThreshold >= 0, "Lag threshold must be greater than or equal to 0");
|
|
840
|
-
invariant(adjustedLag >= 0, "Adjusted lag must be greater than or equal to 0");
|
|
841
|
-
this.#fps = fps;
|
|
842
|
-
this.#gap = 1e3 / fps;
|
|
843
|
-
this.#lagThreshold = lagThreshold === 0 ? 1e8 : lagThreshold;
|
|
844
|
-
this.#adjustedLag = Math.min(adjustedLag, this.#lagThreshold);
|
|
845
|
-
this.#nextTime = this.#gap;
|
|
846
|
-
}
|
|
847
|
-
get fps() {
|
|
848
|
-
return this.#fps;
|
|
849
|
-
}
|
|
850
|
-
set fps(value) {
|
|
851
|
-
invariant(value > 0, "FPS must be greater than 0");
|
|
852
|
-
this.#fps = value;
|
|
853
|
-
this.#gap = 1e3 / value;
|
|
854
|
-
this.#nextTime = this.#previousTime + this.#gap;
|
|
855
|
-
}
|
|
856
|
-
get lagThreshold() {
|
|
857
|
-
return this.#lagThreshold;
|
|
858
|
-
}
|
|
859
|
-
set lagThreshold(value) {
|
|
860
|
-
invariant(value >= 0, "Lag threshold must be greater than or equal to 0");
|
|
861
|
-
this.#lagThreshold = value === 0 ? 1e8 : value;
|
|
862
|
-
this.#adjustedLag = Math.min(this.#adjustedLag, this.#lagThreshold);
|
|
863
|
-
}
|
|
864
|
-
get adjustedLag() {
|
|
865
|
-
return this.#adjustedLag;
|
|
866
|
-
}
|
|
867
|
-
set adjustedLag(value) {
|
|
868
|
-
invariant(value >= 0, "Adjusted lag must be greater than or equal to 0");
|
|
869
|
-
this.#adjustedLag = Math.min(value, this.#lagThreshold);
|
|
870
|
-
}
|
|
871
|
-
get time() {
|
|
872
|
-
return this.#time;
|
|
873
|
-
}
|
|
874
|
-
get frame() {
|
|
875
|
-
return this.#frame;
|
|
876
|
-
}
|
|
877
|
-
get delta() {
|
|
878
|
-
return this.#delta;
|
|
879
|
-
}
|
|
880
|
-
get deltaRatio() {
|
|
881
|
-
return this.#delta / this.#gap;
|
|
882
|
-
}
|
|
883
|
-
get stopped() {
|
|
884
|
-
return this.#stopped;
|
|
885
|
-
}
|
|
886
|
-
start() {
|
|
887
|
-
if (this.#stopped) {
|
|
888
|
-
this.#stopped = false;
|
|
889
|
-
this.#lastWallTime = performance.now();
|
|
890
|
-
this.#id = request((t) => this.#onFrame(t));
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
stop() {
|
|
894
|
-
if (!this.#stopped) {
|
|
895
|
-
cancel(this.#id);
|
|
896
|
-
this.#stopped = true;
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
/** Manually advance one frame. */
|
|
900
|
-
tick() {
|
|
901
|
-
this.#step(this.#gap);
|
|
902
|
-
}
|
|
903
|
-
#onFrame(timestamp) {
|
|
904
|
-
if (this.#stopped) return;
|
|
905
|
-
const wallElapsed = timestamp - this.#lastWallTime;
|
|
906
|
-
this.#lastWallTime = timestamp;
|
|
907
|
-
const elapsed = wallElapsed > this.#lagThreshold ? this.#adjustedLag : wallElapsed;
|
|
908
|
-
this.#time += elapsed;
|
|
909
|
-
if (this.#time - this.#nextTime >= 0) {
|
|
910
|
-
this.#frame++;
|
|
911
|
-
this.#delta = this.#time - this.#previousTime;
|
|
912
|
-
this.#previousTime = this.#time;
|
|
913
|
-
this.#nextTime += this.#gap;
|
|
914
|
-
this.#motion.tick(this.#delta / 1e3);
|
|
915
|
-
}
|
|
916
|
-
this.#id = request((t) => this.#onFrame(t));
|
|
917
|
-
}
|
|
918
|
-
#step(dt) {
|
|
919
|
-
this.#time += dt;
|
|
920
|
-
this.#frame++;
|
|
921
|
-
this.#delta = dt;
|
|
922
|
-
this.#previousTime = this.#time;
|
|
923
|
-
this.#motion.tick(dt / 1e3);
|
|
924
|
-
}
|
|
925
|
-
};
|
|
926
|
-
//#endregion
|
|
927
|
-
//#region src/system.ts
|
|
928
|
-
var SpringSystemImpl = class {
|
|
929
|
-
#motion;
|
|
930
|
-
#ticker;
|
|
931
|
-
constructor(options) {
|
|
932
|
-
this.#motion = new MotionSet(options?.debug);
|
|
933
|
-
this.#ticker = new Ticker(this.#motion, options);
|
|
934
|
-
}
|
|
935
|
-
createSpring(position, config) {
|
|
936
|
-
return new Spring(this.#motion, position, config);
|
|
937
|
-
}
|
|
938
|
-
createSpring2D(position, config) {
|
|
939
|
-
return new Spring2D(this.#motion, position, config);
|
|
940
|
-
}
|
|
941
|
-
advance(dt) {
|
|
942
|
-
this.#motion.tick(dt / 1e3);
|
|
943
|
-
}
|
|
944
|
-
start() {
|
|
945
|
-
this.#ticker.start();
|
|
946
|
-
}
|
|
947
|
-
stop() {
|
|
948
|
-
this.#ticker.stop();
|
|
949
|
-
}
|
|
950
|
-
get running() {
|
|
951
|
-
return !this.#ticker.stopped;
|
|
952
|
-
}
|
|
953
|
-
get fps() {
|
|
954
|
-
return this.#ticker.fps;
|
|
955
|
-
}
|
|
956
|
-
set fps(value) {
|
|
957
|
-
this.#ticker.fps = value;
|
|
958
|
-
}
|
|
959
|
-
get lagThreshold() {
|
|
960
|
-
return this.#ticker.lagThreshold;
|
|
961
|
-
}
|
|
962
|
-
set lagThreshold(value) {
|
|
963
|
-
this.#ticker.lagThreshold = value;
|
|
964
|
-
}
|
|
965
|
-
get adjustedLag() {
|
|
966
|
-
return this.#ticker.adjustedLag;
|
|
967
|
-
}
|
|
968
|
-
set adjustedLag(value) {
|
|
969
|
-
this.#ticker.adjustedLag = value;
|
|
970
|
-
}
|
|
971
|
-
};
|
|
972
|
-
function createSpringSystem(options) {
|
|
973
|
-
return new SpringSystemImpl(options);
|
|
974
|
-
}
|
|
975
|
-
//#endregion
|
|
976
|
-
export { SpringConfig as n, defineSpring as r, createSpringSystem as t };
|