Created
October 21, 2025 18:42
-
-
Save Nodonisko/e43178790a9ea3b00cca4bfca1babb1d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React, { useEffect } from 'react'; | |
| import { Dimensions, StyleSheet, TextInput, View, Text } from 'react-native'; | |
| import { Gesture, GestureDetector } from 'react-native-gesture-handler'; | |
| import Animated, { | |
| interpolateColor, | |
| setNativeProps, | |
| useAnimatedRef, | |
| useAnimatedStyle, | |
| useFrameCallback, | |
| useSharedValue, | |
| withSpring, | |
| } from 'react-native-reanimated'; | |
| const AnimatedTextInput = Animated.createAnimatedComponent(TextInput); | |
| export const ReanimatedFpsCounter = React.memo(() => { | |
| const heartbeats = useSharedValue<number[]>( | |
| // Predefine array with 5s of heartbeats | |
| new Array(300).fill(Date.now() - 1000), | |
| ); | |
| const fps = useSharedValue<number>(0); | |
| const ref = useAnimatedRef<TextInput>(); | |
| const lastUpdateTime = useSharedValue<number>(Date.now()); | |
| useEffect(() => { | |
| let rafId: number; | |
| const tick = () => { | |
| heartbeats.set(value => { | |
| value.shift(); | |
| value.push(Date.now()); | |
| return value; | |
| }); | |
| rafId = requestAnimationFrame(tick); | |
| }; | |
| rafId = requestAnimationFrame(tick); | |
| return () => cancelAnimationFrame(rafId); | |
| }, []); | |
| useFrameCallback(() => { | |
| const now = Date.now(); | |
| if (now - lastUpdateTime.value < 300) { | |
| return; | |
| } | |
| const heartbeatsArray = heartbeats.get(); | |
| // Count heartbeats in the last 1 second | |
| const oneSecondAgo = now - 1000; | |
| let recentHeartbeats = 0; | |
| // Count the number of heartbeats in the last second, but start from end so we save resources | |
| for (let i = heartbeatsArray.length - 1; i >= 0; i--) { | |
| if (heartbeatsArray[i] >= oneSecondAgo) { | |
| recentHeartbeats++; | |
| } else { | |
| break; | |
| } | |
| } | |
| lastUpdateTime.value = now; | |
| fps.value = recentHeartbeats; | |
| setNativeProps(ref, { text: recentHeartbeats.toString() }); | |
| }); | |
| const style = useAnimatedStyle(() => { | |
| return { | |
| backgroundColor: interpolateColor(fps.value, [0, 60], ['red', 'green']), | |
| }; | |
| }); | |
| return ( | |
| <AnimatedTextInput | |
| style={[ | |
| style, | |
| { | |
| color: 'white', | |
| fontSize: 16, | |
| }, | |
| ]} | |
| textAlign="center" | |
| textAlignVertical="center" | |
| ref={ref} | |
| editable={false} | |
| underlineColorAndroid="transparent" | |
| /> | |
| ); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment