0
# Advanced Animation Features
1
2
Advanced animation capabilities including chaining, imperative control, utility hooks, and performance optimizations for complex Three.js scenes.
3
4
## Capabilities
5
6
### useChain Hook
7
8
Sequences multiple spring animations to create complex, choreographed motion.
9
10
```typescript { .api }
11
/**
12
* Chains multiple spring animations in sequence
13
* @param refs - Array of SpringRef instances to chain
14
* @param timeSteps - Optional array of timing offsets (0-1) for each ref
15
* @param timeFrame - Total duration for the chain in milliseconds
16
*/
17
function useChain(
18
refs: SpringRef[],
19
timeSteps?: number[],
20
timeFrame?: number
21
): void;
22
```
23
24
**Usage Examples:**
25
26
```typescript
27
import { animated, useSpring, useSpringRef, useChain } from "@react-spring/three";
28
29
function ChainedAnimation() {
30
const scaleRef = useSpringRef();
31
const rotationRef = useSpringRef();
32
const positionRef = useSpringRef();
33
34
const scaleSpring = useSpring({
35
ref: scaleRef,
36
from: { scale: [0, 0, 0] },
37
to: { scale: [1, 1, 1] },
38
});
39
40
const rotationSpring = useSpring({
41
ref: rotationRef,
42
from: { rotation: [0, 0, 0] },
43
to: { rotation: [0, Math.PI * 2, 0] },
44
});
45
46
const positionSpring = useSpring({
47
ref: positionRef,
48
from: { position: [0, 0, 0] },
49
to: { position: [2, 0, 0] },
50
});
51
52
// Chain animations: scale → rotation → position
53
useChain([scaleRef, rotationRef, positionRef], [0, 0.3, 0.8], 2000);
54
55
return (
56
<animated.mesh
57
{...scaleSpring}
58
{...rotationSpring}
59
{...positionSpring}
60
>
61
<boxGeometry />
62
<meshStandardMaterial color="purple" />
63
</animated.mesh>
64
);
65
}
66
```
67
68
### useScroll Hook
69
70
Creates animations based on scroll position, useful for scroll-driven 3D animations.
71
72
```typescript { .api }
73
/**
74
* Creates scroll-driven animations
75
* @param config - Scroll animation configuration
76
* @returns Spring values based on scroll position
77
*/
78
function useScroll(config: ScrollConfig): SpringValues;
79
80
interface ScrollConfig {
81
from?: any;
82
to?: any;
83
config?: SpringConfig["config"];
84
container?: RefObject<HTMLElement>;
85
offset?: [number, number];
86
immediate?: boolean;
87
}
88
```
89
90
**Usage Examples:**
91
92
```typescript
93
import { animated, useScroll } from "@react-spring/three";
94
95
function ScrollDrivenAnimation() {
96
const { rotation, scale } = useScroll({
97
from: { rotation: [0, 0, 0], scale: [1, 1, 1] },
98
to: { rotation: [0, Math.PI * 2, 0], scale: [2, 2, 2] },
99
config: { tension: 200, friction: 50 },
100
});
101
102
return (
103
<animated.mesh rotation={rotation} scale={scale}>
104
<torusGeometry args={[1, 0.3, 16, 100]} />
105
<meshStandardMaterial color="gold" />
106
</animated.mesh>
107
);
108
}
109
110
// With custom scroll container
111
function ContainerScrollAnimation() {
112
const containerRef = useRef();
113
114
const { position } = useScroll({
115
container: containerRef,
116
from: { position: [0, -10, 0] },
117
to: { position: [0, 10, 0] },
118
offset: [0, 1], // Start and end of scroll range
119
});
120
121
return (
122
<div ref={containerRef} style={{ height: "200vh", overflow: "auto" }}>
123
<Canvas>
124
<animated.mesh position={position}>
125
<sphereGeometry />
126
<meshStandardMaterial />
127
</animated.mesh>
128
</Canvas>
129
</div>
130
);
131
}
132
```
133
134
### useResize Hook
135
136
Creates animations based on window or element resize events.
137
138
```typescript { .api }
139
/**
140
* Creates resize-driven animations
141
* @param config - Resize animation configuration
142
* @returns Spring values based on resize events
143
*/
144
function useResize(config: ResizeConfig): SpringValues;
145
146
interface ResizeConfig {
147
from?: any;
148
to?: any;
149
config?: SpringConfig["config"];
150
container?: RefObject<HTMLElement>;
151
immediate?: boolean;
152
}
153
```
154
155
**Usage Examples:**
156
157
```typescript
158
import { animated, useResize } from "@react-spring/three";
159
160
function ResizeResponsiveAnimation() {
161
const { scale, position } = useResize({
162
from: { scale: [0.5, 0.5, 0.5], position: [0, 0, 0] },
163
to: ({ width, height }) => ({
164
scale: [width / 800, height / 600, 1],
165
position: [(width - 800) / 400, (height - 600) / 300, 0],
166
}),
167
config: { tension: 300, friction: 30 },
168
});
169
170
return (
171
<animated.mesh scale={scale} position={position}>
172
<boxGeometry />
173
<meshStandardMaterial color="orange" />
174
</animated.mesh>
175
);
176
}
177
```
178
179
### useInView Hook
180
181
Creates animations triggered by intersection observer events.
182
183
```typescript { .api }
184
/**
185
* Creates intersection-driven animations
186
* @param config - InView animation configuration
187
* @returns Tuple of [spring values, ref callback]
188
*/
189
function useInView(config: InViewConfig): [SpringValues, RefCallback];
190
191
interface InViewConfig {
192
from?: any;
193
to?: any;
194
config?: SpringConfig["config"];
195
rootMargin?: string;
196
threshold?: number | number[];
197
triggerOnce?: boolean;
198
immediate?: boolean;
199
}
200
201
type RefCallback = (element: HTMLElement | null) => void;
202
```
203
204
**Usage Examples:**
205
206
```typescript
207
import { animated, useInView } from "@react-spring/three";
208
209
function InViewAnimation() {
210
const [springs, ref] = useInView({
211
from: { opacity: 0, scale: [0, 0, 0] },
212
to: { opacity: 1, scale: [1, 1, 1] },
213
config: { tension: 300, friction: 25 },
214
threshold: 0.5,
215
triggerOnce: true,
216
});
217
218
return (
219
<div ref={ref}>
220
<Canvas>
221
<animated.mesh {...springs}>
222
<icosahedronGeometry />
223
<meshStandardMaterial color="cyan" />
224
</animated.mesh>
225
</Canvas>
226
</div>
227
);
228
}
229
```
230
231
### Custom Easings and Interpolations
232
233
Advanced easing functions and custom interpolations for precise animation control.
234
235
```typescript { .api }
236
/**
237
* Built-in easing functions
238
*/
239
const easings: {
240
linear: (t: number) => number;
241
easeInQuad: (t: number) => number;
242
easeOutQuad: (t: number) => number;
243
easeInOutQuad: (t: number) => number;
244
easeInCubic: (t: number) => number;
245
easeOutCubic: (t: number) => number;
246
easeInOutCubic: (t: number) => number;
247
easeInQuart: (t: number) => number;
248
easeOutQuart: (t: number) => number;
249
easeInOutQuart: (t: number) => number;
250
easeInQuint: (t: number) => number;
251
easeOutQuint: (t: number) => number;
252
easeInOutQuint: (t: number) => number;
253
easeInSine: (t: number) => number;
254
easeOutSine: (t: number) => number;
255
easeInOutSine: (t: number) => number;
256
easeInExpo: (t: number) => number;
257
easeOutExpo: (t: number) => number;
258
easeInOutExpo: (t: number) => number;
259
easeInCirc: (t: number) => number;
260
easeOutCirc: (t: number) => number;
261
easeInOutCirc: (t: number) => number;
262
easeInBack: (t: number) => number;
263
easeOutBack: (t: number) => number;
264
easeInOutBack: (t: number) => number;
265
easeInElastic: (t: number) => number;
266
easeOutElastic: (t: number) => number;
267
easeInOutElastic: (t: number) => number;
268
easeInBounce: (t: number) => number;
269
easeOutBounce: (t: number) => number;
270
easeInOutBounce: (t: number) => number;
271
};
272
273
/**
274
* Creates custom interpolators
275
* @param config - Interpolation configuration
276
* @returns Interpolator function
277
*/
278
function createInterpolator(config: InterpolatorConfig): (input: number) => any;
279
```
280
281
**Usage Examples:**
282
283
```typescript
284
import { animated, useSpring, easings, createInterpolator } from "@react-spring/three";
285
286
// Using built-in easings
287
function EasedAnimation() {
288
const springs = useSpring({
289
position: [0, 2, 0],
290
from: { position: [0, 0, 0] },
291
config: {
292
duration: 2000,
293
easing: easings.easeOutBounce,
294
},
295
});
296
297
return (
298
<animated.mesh {...springs}>
299
<sphereGeometry />
300
<meshStandardMaterial color="red" />
301
</animated.mesh>
302
);
303
}
304
305
// Custom interpolation
306
function CustomInterpolation() {
307
const colorInterpolator = createInterpolator({
308
range: [0, 0.5, 1],
309
output: ["#ff0000", "#00ff00", "#0000ff"],
310
});
311
312
const springs = useSpring({
313
progress: 1,
314
from: { progress: 0 },
315
config: { duration: 3000 },
316
});
317
318
const color = springs.progress.to(colorInterpolator);
319
320
return (
321
<animated.mesh>
322
<boxGeometry />
323
<animated.meshStandardMaterial color={color} />
324
</animated.mesh>
325
);
326
}
327
```
328
329
### Performance Optimization Utilities
330
331
Utilities for optimizing animation performance in complex scenes.
332
333
```typescript { .api }
334
/**
335
* Reduced motion preference hook
336
* @returns Boolean indicating user's motion preference
337
*/
338
function useReducedMotion(): boolean;
339
340
/**
341
* Cross-platform layout effect hook
342
*/
343
function useIsomorphicLayoutEffect(
344
effect: EffectCallback,
345
deps?: DependencyList
346
): void;
347
```
348
349
**Usage Examples:**
350
351
```typescript
352
import { animated, useSpring, useReducedMotion } from "@react-spring/three";
353
354
function AccessibleAnimation() {
355
const prefersReducedMotion = useReducedMotion();
356
357
const springs = useSpring({
358
rotation: [0, Math.PI * 2, 0],
359
from: { rotation: [0, 0, 0] },
360
config: prefersReducedMotion
361
? { duration: 0 } // Instant animation
362
: { tension: 200, friction: 25 }, // Normal spring
363
loop: !prefersReducedMotion,
364
});
365
366
return (
367
<animated.mesh {...springs}>
368
<octahedronGeometry />
369
<meshStandardMaterial color="violet" />
370
</animated.mesh>
371
);
372
}
373
```
374
375
## Types
376
377
```typescript { .api }
378
interface ScrollConfig {
379
from?: any;
380
to?: any;
381
config?: SpringConfig["config"];
382
container?: RefObject<HTMLElement>;
383
offset?: [number, number];
384
immediate?: boolean;
385
}
386
387
interface ResizeConfig {
388
from?: any;
389
to?: any | ((size: { width: number; height: number }) => any);
390
config?: SpringConfig["config"];
391
container?: RefObject<HTMLElement>;
392
immediate?: boolean;
393
}
394
395
interface InViewConfig {
396
from?: any;
397
to?: any;
398
config?: SpringConfig["config"];
399
rootMargin?: string;
400
threshold?: number | number[];
401
triggerOnce?: boolean;
402
immediate?: boolean;
403
}
404
405
interface InterpolatorConfig {
406
range: number[];
407
output: any[];
408
extrapolate?: "identity" | "clamp" | "extend";
409
}
410
411
type RefCallback = (element: HTMLElement | null) => void;
412
type EffectCallback = () => void | (() => void);
413
type DependencyList = ReadonlyArray<any>;
414
415
// Core animation classes
416
class Controller<State = any> {
417
start(props?: any): Promise<any>;
418
stop(keys?: string[]): void;
419
update(props: any): void;
420
set(values: any): void;
421
}
422
423
class SpringValue<T = any> {
424
constructor(initial: T, props?: any);
425
get(): T;
426
set(value: T): void;
427
start(config?: any): Promise<void>;
428
stop(): void;
429
to(value: T): SpringValue<T>;
430
}
431
432
class SpringRef<State = any> {
433
current: Controller<State>[];
434
start(): Promise<any>[];
435
stop(): void;
436
update(props: any): void;
437
set(values: any): void;
438
}
439
440
class SpringContext {
441
static Provider: React.ComponentType<{ value: any; children: React.ReactNode }>;
442
}
443
444
class FrameValue {
445
priority: number;
446
get(): any;
447
set(value: any): void;
448
}
449
450
class Interpolation {
451
constructor(source: any, args: any);
452
get(): any;
453
}
454
455
class BailSignal extends Error {
456
constructor(message?: string);
457
}
458
459
// Utility function
460
function inferTo(props: any): any;
461
```