0
# Platform Functions
1
2
Utilities for measuring components, scrolling, native platform integration, and accessing platform-specific functionality for optimal performance and native behavior.
3
4
## Capabilities
5
6
### Component Measurement
7
8
Functions for measuring component dimensions and positions.
9
10
```typescript { .api }
11
/**
12
* Measures the dimensions and position of a component
13
* @param ref - Animated ref to the component to measure
14
* @returns MeasuredDimensions object or null if measurement fails
15
*/
16
function measure(ref: AnimatedRef<any>): MeasuredDimensions | null;
17
18
/**
19
* Gets relative coordinates within a component
20
* @param ref - Animated ref to the reference component
21
* @param x - X coordinate to convert
22
* @param y - Y coordinate to convert
23
* @returns ComponentCoords object or null if conversion fails
24
*/
25
function getRelativeCoords(
26
ref: AnimatedRef<any>,
27
x: number,
28
y: number
29
): ComponentCoords | null;
30
31
interface MeasuredDimensions {
32
/** Component x position relative to its parent */
33
x: number;
34
/** Component y position relative to its parent */
35
y: number;
36
/** Component width */
37
width: number;
38
/** Component height */
39
height: number;
40
/** Component x position relative to the screen */
41
pageX: number;
42
/** Component y position relative to the screen */
43
pageY: number;
44
}
45
46
interface ComponentCoords {
47
/** X coordinate relative to the component */
48
x: number;
49
/** Y coordinate relative to the component */
50
y: number;
51
}
52
```
53
54
**Usage Examples:**
55
56
```typescript
57
import React, { useRef } from "react";
58
import Animated, {
59
useAnimatedRef,
60
measure,
61
getRelativeCoords,
62
useSharedValue,
63
useAnimatedStyle,
64
runOnUI,
65
runOnJS
66
} from "react-native-reanimated";
67
import { Button } from "react-native";
68
69
const MeasurementExample = () => {
70
const containerRef = useAnimatedRef();
71
const targetRef = useAnimatedRef();
72
const ballPosition = useSharedValue({ x: 50, y: 50 });
73
74
// Measure component dimensions
75
const measureComponent = () => {
76
runOnUI(() => {
77
'worklet';
78
const dimensions = measure(targetRef);
79
if (dimensions) {
80
runOnJS(console.log)('Component dimensions:', dimensions);
81
// Use measurements for animations
82
ballPosition.value = {
83
x: dimensions.width / 2,
84
y: dimensions.height / 2
85
};
86
}
87
})();
88
};
89
90
// Convert screen coordinates to component-relative coordinates
91
const handlePress = (event: any) => {
92
const { locationX, locationY } = event.nativeEvent;
93
94
runOnUI(() => {
95
'worklet';
96
const coords = getRelativeCoords(containerRef, locationX, locationY);
97
if (coords) {
98
ballPosition.value = coords;
99
runOnJS(console.log)('Relative coordinates:', coords);
100
}
101
})();
102
};
103
104
const ballStyle = useAnimatedStyle(() => ({
105
transform: [
106
{ translateX: ballPosition.value.x - 25 }, // Center the ball
107
{ translateY: ballPosition.value.y - 25 },
108
],
109
}));
110
111
return (
112
<>
113
<Button title="Measure Target" onPress={measureComponent} />
114
115
<Animated.View
116
ref={containerRef}
117
onTouchEnd={handlePress}
118
style={{
119
width: 300,
120
height: 200,
121
backgroundColor: "lightgray",
122
margin: 20,
123
borderRadius: 10,
124
position: "relative",
125
}}
126
>
127
<Animated.Text>Touch anywhere to move the ball</Animated.Text>
128
129
{/* Target component to measure */}
130
<Animated.View
131
ref={targetRef}
132
style={{
133
width: 100,
134
height: 100,
135
backgroundColor: "lightblue",
136
position: "absolute",
137
top: 20,
138
right: 20,
139
borderRadius: 5,
140
}}
141
>
142
<Animated.Text>Target</Animated.Text>
143
</Animated.View>
144
145
{/* Animated ball */}
146
<Animated.View
147
style={[
148
{
149
width: 50,
150
height: 50,
151
backgroundColor: "red",
152
borderRadius: 25,
153
position: "absolute",
154
},
155
ballStyle,
156
]}
157
/>
158
</Animated.View>
159
</>
160
);
161
};
162
```
163
164
### Scrolling Control
165
166
Programmatic scrolling control for ScrollView and other scrollable components.
167
168
```typescript { .api }
169
/**
170
* Programmatically scrolls a scrollable component
171
* @param ref - Animated ref to the scrollable component
172
* @param x - X coordinate to scroll to
173
* @param y - Y coordinate to scroll to
174
* @param animated - Whether to animate the scroll
175
*/
176
function scrollTo(
177
ref: AnimatedRef<any>,
178
x: number,
179
y: number,
180
animated: boolean
181
): void;
182
```
183
184
**Usage Examples:**
185
186
```typescript
187
import React from "react";
188
import Animated, {
189
useAnimatedRef,
190
scrollTo,
191
useSharedValue,
192
useAnimatedScrollHandler,
193
runOnUI
194
} from "react-native-reanimated";
195
import { Button } from "react-native";
196
197
const ScrollControlExample = () => {
198
const scrollRef = useAnimatedRef();
199
const scrollY = useSharedValue(0);
200
201
// Track scroll position
202
const scrollHandler = useAnimatedScrollHandler({
203
onScroll: (event) => {
204
scrollY.value = event.contentOffset.y;
205
},
206
});
207
208
// Scroll to specific positions
209
const scrollToTop = () => {
210
runOnUI(() => {
211
'worklet';
212
scrollTo(scrollRef, 0, 0, true);
213
})();
214
};
215
216
const scrollToMiddle = () => {
217
runOnUI(() => {
218
'worklet';
219
scrollTo(scrollRef, 0, 500, true);
220
})();
221
};
222
223
const scrollToBottom = () => {
224
runOnUI(() => {
225
'worklet';
226
scrollTo(scrollRef, 0, 1500, true);
227
})();
228
};
229
230
// Smooth scrolling animation
231
const smoothScrollTo = (targetY: number) => {
232
runOnUI(() => {
233
'worklet';
234
const startY = scrollY.value;
235
const distance = targetY - startY;
236
const duration = Math.abs(distance) / 2; // Adjust speed based on distance
237
238
// Custom smooth scroll implementation
239
const startTime = Date.now();
240
const animate = () => {
241
'worklet';
242
const elapsed = Date.now() - startTime;
243
const progress = Math.min(elapsed / duration, 1);
244
const easeProgress = 1 - Math.pow(1 - progress, 3); // Ease out cubic
245
246
const currentY = startY + distance * easeProgress;
247
scrollTo(scrollRef, 0, currentY, false);
248
249
if (progress < 1) {
250
// Continue animation
251
setTimeout(() => animate(), 16); // ~60fps
252
}
253
};
254
255
animate();
256
})();
257
};
258
259
return (
260
<>
261
<Button title="Scroll to Top" onPress={scrollToTop} />
262
<Button title="Scroll to Middle" onPress={scrollToMiddle} />
263
<Button title="Scroll to Bottom" onPress={scrollToBottom} />
264
<Button title="Smooth Scroll to 800" onPress={() => smoothScrollTo(800)} />
265
266
<Animated.ScrollView
267
ref={scrollRef}
268
onScroll={scrollHandler}
269
scrollEventThrottle={16}
270
style={{ height: 400 }}
271
>
272
{/* Content to scroll through */}
273
{Array.from({ length: 100 }).map((_, index) => (
274
<Animated.View
275
key={index}
276
style={{
277
height: 60,
278
backgroundColor: index % 2 ? "white" : "lightgray",
279
justifyContent: "center",
280
alignItems: "center",
281
borderBottomWidth: 1,
282
borderBottomColor: "gray",
283
}}
284
>
285
<Animated.Text>Item {index} - Y: {index * 60}</Animated.Text>
286
</Animated.View>
287
))}
288
</Animated.ScrollView>
289
</>
290
);
291
};
292
```
293
294
### Native Props Manipulation
295
296
Direct manipulation of native component properties for performance-critical updates.
297
298
```typescript { .api }
299
/**
300
* Sets native properties on a component directly
301
* @param ref - Animated ref to the component
302
* @param props - Object containing properties to set
303
*/
304
function setNativeProps(ref: AnimatedRef<any>, props: object): void;
305
306
/**
307
* Dispatches a command to a native component
308
* @param ref - Animated ref to the component
309
* @param commandName - Name of the command to dispatch
310
* @param args - Optional arguments for the command
311
*/
312
function dispatchCommand(
313
ref: AnimatedRef<any>,
314
commandName: string,
315
args?: any[]
316
): void;
317
318
/**
319
* Gets a property value from a native component
320
* @param ref - Animated ref to the component
321
* @param prop - Property name to get
322
* @returns Property value
323
*/
324
function getViewProp(ref: AnimatedRef<any>, prop: string): any;
325
```
326
327
**Usage Examples:**
328
329
```typescript
330
import React from "react";
331
import { TextInput } from "react-native";
332
import Animated, {
333
useAnimatedRef,
334
setNativeProps,
335
dispatchCommand,
336
getViewProp,
337
useSharedValue,
338
useAnimatedStyle,
339
runOnUI,
340
runOnJS
341
} from "react-native-reanimated";
342
import { Button } from "react-native";
343
344
const NativePropsExample = () => {
345
const textInputRef = useAnimatedRef();
346
const viewRef = useAnimatedRef();
347
const opacity = useSharedValue(1);
348
349
// Direct native prop manipulation
350
const changeInputProps = () => {
351
runOnUI(() => {
352
'worklet';
353
setNativeProps(textInputRef, {
354
text: "Updated via native props!",
355
placeholder: "Native update",
356
backgroundColor: "#ffeeee",
357
});
358
})();
359
};
360
361
// Focus input using dispatch command
362
const focusInput = () => {
363
runOnUI(() => {
364
'worklet';
365
dispatchCommand(textInputRef, "focus", []);
366
})();
367
};
368
369
// Blur input using dispatch command
370
const blurInput = () => {
371
runOnUI(() => {
372
'worklet';
373
dispatchCommand(textInputRef, "blur", []);
374
})();
375
};
376
377
// Get view properties
378
const getViewProperties = () => {
379
runOnUI(() => {
380
'worklet';
381
const opacity = getViewProp(viewRef, "opacity");
382
const backgroundColor = getViewProp(viewRef, "backgroundColor");
383
384
runOnJS(console.log)("View opacity:", opacity);
385
runOnJS(console.log)("View backgroundColor:", backgroundColor);
386
})();
387
};
388
389
// Batch native updates for performance
390
const batchNativeUpdates = () => {
391
runOnUI(() => {
392
'worklet';
393
// Multiple native updates in single UI frame
394
setNativeProps(viewRef, {
395
backgroundColor: `hsl(${Math.random() * 360}, 70%, 80%)`,
396
borderRadius: Math.random() * 20,
397
borderWidth: Math.random() * 5,
398
});
399
400
setNativeProps(textInputRef, {
401
fontSize: 14 + Math.random() * 10,
402
color: Math.random() > 0.5 ? "black" : "blue",
403
});
404
})();
405
};
406
407
const animatedStyle = useAnimatedStyle(() => ({
408
opacity: opacity.value,
409
}));
410
411
return (
412
<>
413
<Button title="Change Input Props" onPress={changeInputProps} />
414
<Button title="Focus Input" onPress={focusInput} />
415
<Button title="Blur Input" onPress={blurInput} />
416
<Button title="Get View Props" onPress={getViewProperties} />
417
<Button title="Batch Updates" onPress={batchNativeUpdates} />
418
419
<Animated.View
420
ref={viewRef}
421
style={[
422
{
423
width: 200,
424
height: 100,
425
backgroundColor: "lightblue",
426
margin: 20,
427
padding: 10,
428
borderRadius: 10,
429
},
430
animatedStyle,
431
]}
432
>
433
<TextInput
434
ref={textInputRef}
435
style={{
436
height: 40,
437
borderWidth: 1,
438
borderColor: "gray",
439
borderRadius: 5,
440
paddingHorizontal: 10,
441
backgroundColor: "white",
442
}}
443
placeholder="Type something..."
444
/>
445
</Animated.View>
446
</>
447
);
448
};
449
```
450
451
### Gesture Integration
452
453
Integration with gesture handling systems for advanced touch interactions.
454
455
```typescript { .api }
456
/**
457
* Sets the state of a gesture handler
458
* @param handlerTag - Tag identifying the gesture handler
459
* @param newState - New state to set for the handler
460
*/
461
function setGestureState(handlerTag: number, newState: number): void;
462
```
463
464
**Usage Example:**
465
466
```typescript
467
import React from "react";
468
import Animated, {
469
useSharedValue,
470
useAnimatedStyle,
471
useAnimatedGestureHandler,
472
setGestureState,
473
runOnUI
474
} from "react-native-reanimated";
475
import { PanGestureHandler, State } from "react-native-gesture-handler";
476
477
const GestureIntegrationExample = () => {
478
const translateX = useSharedValue(0);
479
const translateY = useSharedValue(0);
480
const gestureHandlerTag = useSharedValue(0);
481
482
// Gesture handler with state control
483
const gestureHandler = useAnimatedGestureHandler({
484
onStart: (_, context) => {
485
context.startX = translateX.value;
486
context.startY = translateY.value;
487
},
488
onActive: (event, context) => {
489
translateX.value = context.startX + event.translationX;
490
translateY.value = context.startY + event.translationY;
491
492
// Control gesture state based on conditions
493
if (Math.abs(event.translationX) > 200) {
494
// Cancel gesture if moved too far
495
setGestureState(gestureHandlerTag.value, State.CANCELLED);
496
}
497
},
498
onEnd: (event) => {
499
// Snap back to center if released
500
if (Math.abs(translateX.value) > 100 || Math.abs(translateY.value) > 100) {
501
translateX.value = withSpring(0);
502
translateY.value = withSpring(0);
503
}
504
},
505
});
506
507
// Programmatic gesture control
508
const resetGesture = () => {
509
runOnUI(() => {
510
'worklet';
511
setGestureState(gestureHandlerTag.value, State.END);
512
translateX.value = withSpring(0);
513
translateY.value = withSpring(0);
514
})();
515
};
516
517
const animatedStyle = useAnimatedStyle(() => ({
518
transform: [
519
{ translateX: translateX.value },
520
{ translateY: translateY.value },
521
],
522
}));
523
524
return (
525
<>
526
<Button title="Reset Gesture" onPress={resetGesture} />
527
528
<PanGestureHandler
529
onGestureEvent={gestureHandler}
530
onHandlerStateChange={(event) => {
531
gestureHandlerTag.value = event.nativeEvent.handlerTag;
532
}}
533
>
534
<Animated.View
535
style={[
536
{
537
width: 100,
538
height: 100,
539
backgroundColor: "lightcoral",
540
borderRadius: 10,
541
margin: 50,
542
},
543
animatedStyle,
544
]}
545
>
546
<Animated.Text style={{ textAlign: "center", marginTop: 35 }}>
547
Drag me!
548
</Animated.Text>
549
</Animated.View>
550
</PanGestureHandler>
551
</>
552
);
553
};
554
```
555
556
### Platform-Specific Utilities
557
558
Utilities for handling platform differences and native integration.
559
560
**Version and Configuration Checks:**
561
562
```typescript
563
import {
564
isConfigured,
565
isReanimated3,
566
reanimatedVersion
567
} from "react-native-reanimated";
568
569
// Check if Reanimated is properly configured
570
if (isConfigured()) {
571
console.log("Reanimated is ready");
572
}
573
574
// Check version
575
if (isReanimated3()) {
576
console.log("Using Reanimated 3+");
577
}
578
579
console.log("Reanimated version:", reanimatedVersion);
580
```
581
582
**Configuration and Debugging:**
583
584
```typescript
585
import {
586
configureReanimatedLogger,
587
ReanimatedLogLevel,
588
enableLayoutAnimations
589
} from "react-native-reanimated";
590
591
// Configure logging
592
configureReanimatedLogger({
593
level: ReanimatedLogLevel.warn,
594
strict: false,
595
});
596
597
// Enable layout animations (required for some platforms)
598
enableLayoutAnimations(true);
599
```
600
601
### Performance Monitoring
602
603
Monitor and optimize animation performance using built-in tools.
604
605
```typescript { .api }
606
/**
607
* Performance monitoring component for tracking animation performance
608
*/
609
const PerformanceMonitor: React.ComponentType<PerformanceMonitorProps>;
610
611
interface PerformanceMonitorProps {
612
/** Whether to show performance overlay */
613
enabled?: boolean;
614
/** Callback for performance data */
615
onPerformanceData?: (data: PerformanceData) => void;
616
}
617
618
interface PerformanceData {
619
/** Frames per second */
620
fps: number;
621
/** JavaScript thread usage */
622
jsThreadUsage: number;
623
/** UI thread usage */
624
uiThreadUsage: number;
625
/** Memory usage */
626
memoryUsage: number;
627
}
628
```
629
630
**Usage Example:**
631
632
```typescript
633
import React, { useState } from "react";
634
import Animated, {
635
PerformanceMonitor,
636
useSharedValue,
637
useAnimatedStyle,
638
withRepeat,
639
withTiming
640
} from "react-native-reanimated";
641
642
const PerformanceExample = () => {
643
const [performanceEnabled, setPerformanceEnabled] = useState(false);
644
const rotation = useSharedValue(0);
645
646
const animatedStyle = useAnimatedStyle(() => ({
647
transform: [{ rotate: `${rotation.value}deg` }],
648
}));
649
650
const startHeavyAnimation = () => {
651
rotation.value = withRepeat(
652
withTiming(360, { duration: 100 }),
653
-1,
654
false
655
);
656
};
657
658
const handlePerformanceData = (data: PerformanceData) => {
659
console.log("Performance:", data);
660
};
661
662
return (
663
<>
664
<PerformanceMonitor
665
enabled={performanceEnabled}
666
onPerformanceData={handlePerformanceData}
667
/>
668
669
<Button
670
title={`Performance Monitor: ${performanceEnabled ? "ON" : "OFF"}`}
671
onPress={() => setPerformanceEnabled(!performanceEnabled)}
672
/>
673
674
<Button title="Start Heavy Animation" onPress={startHeavyAnimation} />
675
676
<Animated.View
677
style={[
678
{
679
width: 100,
680
height: 100,
681
backgroundColor: "lightgreen",
682
margin: 20,
683
},
684
animatedStyle,
685
]}
686
/>
687
</>
688
);
689
};
690
```
691
692
## Type Definitions
693
694
```typescript { .api }
695
interface AnimatedRef<T> {
696
current: T | null;
697
(component?: T | null): void;
698
}
699
700
interface SerializableRef {
701
__reanimatedSerializableRef: true;
702
__value: number;
703
}
704
705
type NativeMethods = {
706
measure(callback: (x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void): void;
707
measureInWindow(callback: (x: number, y: number, width: number, height: number) => void): void;
708
measureLayout(
709
relativeToNativeNode: number,
710
onSuccess: (left: number, top: number, width: number, height: number) => void,
711
onFail: () => void
712
): void;
713
setNativeProps(nativeProps: object): void;
714
focus(): void;
715
blur(): void;
716
};
717
718
enum ReanimatedLogLevel {
719
debug = 0,
720
info = 1,
721
warn = 2,
722
error = 3,
723
}
724
725
interface LoggerConfig {
726
level?: ReanimatedLogLevel;
727
strict?: boolean;
728
}
729
```
730
731
## Best Practices
732
733
### Performance Optimization
734
735
1. **Batch native updates**: Group multiple `setNativeProps` calls together
736
2. **Use appropriate measurement timing**: Measure after layout is complete
737
3. **Cache measurement results**: Store dimensions in shared values when possible
738
4. **Minimize cross-thread communication**: Keep measurements on UI thread when possible
739
5. **Profile with PerformanceMonitor**: Monitor FPS and thread usage
740
741
### Platform Considerations
742
743
1. **Test on all target platforms**: iOS, Android, and Web have different behaviors
744
2. **Handle platform-specific features**: Some functions may not be available on all platforms
745
3. **Use native props judiciously**: Direct native manipulation bypasses React's reconciliation
746
4. **Consider accessibility**: Ensure platform functions don't break accessibility features
747
748
### Common Patterns
749
750
1. **Responsive layouts**: Use measurements to create adaptive UIs
751
2. **Custom gesture handling**: Combine with gesture libraries for complex interactions
752
3. **Performance monitoring**: Track animation performance in development builds
753
4. **Smooth scrolling**: Implement custom scroll behaviors with `scrollTo`