0
# Imperative Control
1
2
Classes and utilities for imperative animation control and advanced use cases. These provide direct control over spring animations outside of the declarative hook patterns.
3
4
## Capabilities
5
6
### Controller Class
7
8
Controls spring animations imperatively with full lifecycle management.
9
10
```typescript { .api }
11
/**
12
* Core controller class for managing spring animations
13
* Provides imperative API for advanced animation control
14
*/
15
class Controller<State extends Lookup = Lookup> {
16
constructor(props?: ControllerUpdate<State>);
17
18
/**
19
* Start animations with optional configuration
20
* @param props - Animation configuration and target values
21
* @returns Promise resolving when animations complete
22
*/
23
start(props?: ControllerUpdate<State>): Promise<AnimationResult<State>>;
24
25
/**
26
* Stop animations for specified keys or all animations
27
* @param keys - Animation keys to stop, or undefined for all
28
* @returns Controller instance for chaining
29
*/
30
stop(keys?: OneOrMore<string>): this;
31
32
/**
33
* Update animation configuration without starting
34
* @param props - New animation configuration
35
* @returns Controller instance for chaining
36
*/
37
update(props: ControllerUpdate<State>): this;
38
39
/**
40
* Set immediate values without animation
41
* @param props - Values to set immediately
42
* @returns Controller instance for chaining
43
*/
44
set(props: Partial<State>): this;
45
46
/**
47
* Get current animated values
48
* @returns Current spring values
49
*/
50
get(): State;
51
52
/**
53
* Check if any animations are currently running
54
* @returns True if animations are active
55
*/
56
isAnimating(): boolean;
57
58
/**
59
* Access individual SpringValue instances
60
*/
61
springs: { [P in keyof State]: SpringValue<State[P]> };
62
}
63
64
interface ControllerUpdate<State extends Lookup = Lookup> {
65
/** Target values for animations */
66
to?: Partial<State> | ((state: State) => Partial<State>);
67
/** Initial values for animations */
68
from?: Partial<State>;
69
/** Animation configuration */
70
config?: SpringConfig | ((key: string) => SpringConfig);
71
/** Delay before animation starts */
72
delay?: number | ((key: string) => number);
73
/** Immediate properties (no animation) */
74
immediate?: boolean | OneOrMore<string> | ((key: string) => boolean);
75
/** Reset animation state */
76
reset?: boolean | OneOrMore<string>;
77
/** Reverse animation direction */
78
reverse?: boolean;
79
/** Loop configuration */
80
loop?: LoopProps;
81
/** Callback when animation starts */
82
onStart?: (result: AnimationResult<State>) => void;
83
/** Callback during animation */
84
onChange?: (result: AnimationResult<State>) => void;
85
/** Callback when animation completes */
86
onRest?: (result: AnimationResult<State>) => void;
87
}
88
89
interface AnimationResult<State extends Lookup = Lookup> {
90
value: State;
91
finished: boolean;
92
cancelled: boolean;
93
}
94
```
95
96
**Usage Examples:**
97
98
```typescript
99
import { Controller } from "@react-spring/web";
100
101
// Basic controller usage
102
const controller = new Controller({
103
opacity: 0,
104
transform: 'translateX(0px)',
105
});
106
107
// Start animation
108
controller.start({
109
to: { opacity: 1, transform: 'translateX(100px)' },
110
config: { duration: 1000 },
111
});
112
113
// Stop animation
114
controller.stop();
115
116
// Chained operations
117
controller
118
.set({ opacity: 0 })
119
.start({ to: { opacity: 1 } })
120
.then(() => console.log('Animation complete'));
121
```
122
123
### SpringValue Class
124
125
Represents a single animated value with its own lifecycle.
126
127
```typescript { .api }
128
/**
129
* Single animated value with spring physics
130
* Extends FrameValue with spring-specific functionality
131
*/
132
class SpringValue<T = any> extends FrameValue<T> {
133
constructor(value?: T, props?: SpringUpdate<T>);
134
135
/**
136
* Start animation to new value
137
* @param props - Animation configuration or target value
138
* @returns Promise resolving when animation completes
139
*/
140
start(props?: SpringUpdate<T>): Promise<AnimationResult<SpringValue<T>>>;
141
142
/**
143
* Stop the current animation
144
* @returns SpringValue instance for chaining
145
*/
146
stop(): this;
147
148
/**
149
* Set value immediately without animation
150
* @param value - New value to set
151
* @returns SpringValue instance for chaining
152
*/
153
set(value: T | FluidValue<T>): this;
154
155
/**
156
* Get current value
157
* @returns Current animated value
158
*/
159
get(): T;
160
161
/**
162
* Get current velocity
163
* @returns Current animation velocity
164
*/
165
getVelocity(): number;
166
167
/**
168
* Check if animation is currently running
169
* @returns True if animating
170
*/
171
isAnimating(): boolean;
172
173
/**
174
* Advance animation by one frame
175
* @param dt - Delta time in milliseconds
176
* @returns True if animation should continue
177
*/
178
advance(dt: number): boolean;
179
}
180
181
interface SpringUpdate<T = any> {
182
/** Target value */
183
to?: T | FluidValue<T>;
184
/** Initial value */
185
from?: T;
186
/** Animation configuration */
187
config?: SpringConfig;
188
/** Delay before animation starts */
189
delay?: number;
190
/** Set value immediately */
191
immediate?: boolean;
192
/** Reset animation state */
193
reset?: boolean;
194
/** Loop configuration */
195
loop?: LoopProps;
196
/** Animation callbacks */
197
onStart?: (value: SpringValue<T>) => void;
198
onChange?: (value: SpringValue<T>) => void;
199
onRest?: (value: SpringValue<T>) => void;
200
}
201
```
202
203
**Usage Examples:**
204
205
```typescript
206
import { SpringValue } from "@react-spring/web";
207
208
// Create spring value
209
const opacity = new SpringValue(0);
210
211
// Animate to new value
212
opacity.start({
213
to: 1,
214
config: { tension: 300, friction: 30 },
215
onRest: () => console.log('Fade complete'),
216
});
217
218
// Use in component
219
function Component() {
220
return (
221
<animated.div style={{ opacity }}>
222
Content
223
</animated.div>
224
);
225
}
226
```
227
228
### SpringRef Class
229
230
Reference object for imperative control of hook-based springs.
231
232
```typescript { .api }
233
/**
234
* Reference for imperative control of spring hooks
235
* Provides imperative API for hook-based springs
236
*/
237
class SpringRef<State extends Lookup = Lookup> {
238
constructor();
239
240
/**
241
* Start animations on all controlled springs
242
* @param props - Animation configuration
243
* @returns Promise resolving when animations complete
244
*/
245
start(props?: ControllerUpdate<State>): Promise<AnimationResult<State>[]>;
246
247
/**
248
* Stop animations on all controlled springs
249
* @param keys - Animation keys to stop
250
* @returns SpringRef instance for chaining
251
*/
252
stop(keys?: OneOrMore<string>): this;
253
254
/**
255
* Update configuration on all controlled springs
256
* @param props - New animation configuration
257
* @returns SpringRef instance for chaining
258
*/
259
update(props: ControllerUpdate<State>): this;
260
261
/**
262
* Set immediate values on all controlled springs
263
* @param props - Values to set immediately
264
* @returns SpringRef instance for chaining
265
*/
266
set(props: Partial<State>): this;
267
268
/**
269
* Get current values from all controlled springs
270
* @returns Array of current spring states
271
*/
272
get(): State[];
273
274
/**
275
* Access the underlying controllers
276
*/
277
controllers: Controller<State>[];
278
279
/**
280
* Current number of controlled springs
281
*/
282
length: number;
283
}
284
```
285
286
**Usage Examples:**
287
288
```typescript
289
import { useSpring, useSpringRef } from "@react-spring/web";
290
291
function RefControlled() {
292
const springRef = useSpringRef();
293
const styles = useSpring({
294
ref: springRef,
295
from: { opacity: 0 },
296
to: { opacity: 1 },
297
});
298
299
const handleClick = () => {
300
// Imperative control
301
springRef.start({
302
to: { opacity: Math.random() },
303
config: { duration: 500 },
304
});
305
};
306
307
return (
308
<animated.div style={styles} onClick={handleClick}>
309
Click to animate
310
</animated.div>
311
);
312
}
313
```
314
315
### SpringContext
316
317
React context for sharing spring configuration across components.
318
319
```typescript { .api }
320
/**
321
* React context for sharing spring configuration
322
* Provides default props for nested spring animations
323
*/
324
class SpringContext {
325
static Provider: React.Provider<Partial<ControllerUpdate>>;
326
static Consumer: React.Consumer<Partial<ControllerUpdate>>;
327
}
328
```
329
330
**Usage Examples:**
331
332
```typescript
333
import { SpringContext } from "@react-spring/web";
334
335
function App() {
336
return (
337
<SpringContext.Provider value={{
338
config: { tension: 300, friction: 30 },
339
immediate: false,
340
}}>
341
<AnimatedComponents />
342
</SpringContext.Provider>
343
);
344
}
345
```
346
347
### FrameValue Class
348
349
Base class for frame-based animated values.
350
351
```typescript { .api }
352
/**
353
* Base class for frame-based animated values
354
* Provides core animation frame management
355
*/
356
class FrameValue<T = any> extends FluidValue<T> {
357
constructor(value?: T);
358
359
/**
360
* Advance animation by one frame
361
* @param dt - Delta time in milliseconds
362
* @returns True if animation should continue
363
*/
364
advance(dt: number): boolean;
365
366
/**
367
* Reset animation state
368
*/
369
reset(): void;
370
371
/**
372
* Check if animation has finished
373
* @returns True if animation is complete
374
*/
375
isFinished(): boolean;
376
}
377
```
378
379
### Interpolation Class
380
381
Advanced interpolation functionality for complex animations.
382
383
```typescript { .api }
384
/**
385
* Advanced interpolation between animated values
386
* Supports complex value transformations and mappings
387
*/
388
class Interpolation<Input = any, Output = any> extends FrameValue<Output> {
389
constructor(
390
source: OneOrMore<FluidValue<Input>>,
391
args: InterpolatorArgs<Input, Output>
392
);
393
394
/**
395
* Create new interpolation from this one
396
* @param args - Interpolation configuration
397
* @returns New Interpolation instance
398
*/
399
interpolate<NewOutput>(
400
args: InterpolatorArgs<Output, NewOutput>
401
): Interpolation<Output, NewOutput>;
402
}
403
404
interface InterpolatorArgs<Input, Output> {
405
/** Input range for interpolation */
406
range?: number[];
407
/** Output range for interpolation */
408
output?: readonly Output[];
409
/** Interpolation function */
410
map?: (input: Input) => Output;
411
/** Extrapolation mode */
412
extrapolate?: 'extend' | 'clamp' | 'identity';
413
}
414
```
415
416
### BailSignal Class
417
418
Signal for stopping async animations.
419
420
```typescript { .api }
421
/**
422
* Signal for stopping async animations
423
* Used to cancel long-running or complex animations
424
*/
425
class BailSignal extends Error {
426
constructor(reason?: string);
427
}
428
```
429
430
## Advanced Usage Patterns
431
432
### Custom Animation Loops
433
434
```typescript
435
import { Controller } from "@react-spring/web";
436
437
const controller = new Controller({ rotation: 0 });
438
439
async function infiniteRotation() {
440
while (true) {
441
await controller.start({
442
to: { rotation: 360 },
443
config: { duration: 2000 },
444
});
445
controller.set({ rotation: 0 });
446
}
447
}
448
449
infiniteRotation();
450
```
451
452
### Complex State Management
453
454
```typescript
455
import { Controller, SpringValue } from "@react-spring/web";
456
457
class AnimationManager {
458
private opacity = new SpringValue(1);
459
private position = new Controller({ x: 0, y: 0 });
460
461
async fadeOut() {
462
await this.opacity.start({ to: 0 });
463
}
464
465
async moveTo(x: number, y: number) {
466
await this.position.start({ to: { x, y } });
467
}
468
469
getStyles() {
470
return {
471
opacity: this.opacity,
472
transform: this.position.springs.x.to(
473
(x, y) => `translate(${x}px, ${y}px)`
474
),
475
};
476
}
477
}
478
```
479
480
### Additional Core Classes
481
482
#### FrameValue
483
484
Base class for frame-based animated values.
485
486
```typescript { .api }
487
/**
488
* Base class for frame-based animated values
489
* Provides core animation lifecycle and value management
490
*/
491
class FrameValue<T = any> {
492
constructor(value?: T);
493
494
/**
495
* Current animated value
496
*/
497
readonly value: T;
498
499
/**
500
* Check if animation is currently running
501
* @returns True if animating
502
*/
503
isAnimating(): boolean;
504
505
/**
506
* Advance animation by one frame
507
* @param dt - Delta time in milliseconds
508
* @returns True if animation should continue
509
*/
510
advance(dt: number): boolean;
511
512
/**
513
* Set value immediately without animation
514
* @param value - New value to set
515
*/
516
setValue(value: T): void;
517
518
/**
519
* Get current value
520
* @returns Current animated value
521
*/
522
getValue(): T;
523
}
524
```
525
526
#### Interpolation
527
528
Interpolation class for mapping values between different ranges.
529
530
```typescript { .api }
531
/**
532
* Interpolation class for value mapping and transformation
533
* Supports range mapping, easing functions, and complex transformations
534
*/
535
class Interpolation<Output = any> extends FrameValue<Output> {
536
constructor(source: any, args: any);
537
538
/**
539
* Current interpolated output value
540
*/
541
readonly value: Output;
542
543
/**
544
* Source values being interpolated
545
*/
546
readonly source: any;
547
548
/**
549
* Update interpolation configuration
550
* @param config - New interpolation settings
551
*/
552
update(config: any): void;
553
}
554
```
555
556
#### BailSignal
557
558
Signal class for terminating animations early.
559
560
```typescript { .api }
561
/**
562
* Signal class used to terminate animations early
563
* Provides mechanism for graceful animation cancellation
564
*/
565
class BailSignal {
566
constructor(reason?: string);
567
568
/**
569
* Reason for bailing out of animation
570
*/
571
readonly reason?: string;
572
573
/**
574
* Check if this is a bail signal
575
* @param value - Value to check
576
* @returns True if value is BailSignal
577
*/
578
static is(value: any): value is BailSignal;
579
}
580
```