Created
January 26, 2024 01:25
-
-
Save lrsbt/84ab1be381d58d0c05f3d751bf2a1cb8 to your computer and use it in GitHub Desktop.
ReactNative Reanimated Ball Bouncing of Walls
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 { StyleSheet, View } from "react-native"; | |
import Animated, { | |
useAnimatedStyle, | |
useSharedValue | |
} from "react-native-reanimated"; | |
import { viewPort } from "@project/utils"; | |
const BALL_SIZE = 20; | |
const Bounce = () => { | |
const locationX = useSharedValue(15); | |
const locationY = useSharedValue(255); | |
const speed = useSharedValue(10); | |
const angle = useSharedValue(60); | |
const min_X = useSharedValue(0); | |
const max_X = useSharedValue(viewPort.width - BALL_SIZE); | |
const min_Y = useSharedValue(0); | |
const max_Y = useSharedValue(viewPort.height - BALL_SIZE); | |
const degToRad = (degrees: number) => { | |
var pi = Math.PI; | |
return degrees * (pi / 180); | |
}; | |
const angleReflect = (incidenceAngle: number, surfaceAngle: number) => { | |
var a = surfaceAngle * 2 - incidenceAngle; | |
return a >= 360 ? a - 360 : a < 0 ? a + 360 : a; | |
}; | |
const progress = () => { | |
locationX.value += speed.value * Math.sin(degToRad(angle.value)); | |
locationY.value += speed.value * Math.cos(degToRad(angle.value)); | |
if (locationX.value > max_X.value) { | |
angle.value = angleReflect(angle.value, 0); | |
locationX.value = max_X.value; | |
} else if (locationX.value < min_X.value) { | |
angle.value = angleReflect(angle.value, 0); | |
locationX.value = min_X.value; | |
} | |
if (locationY.value > max_Y.value) { | |
angle.value = angleReflect(angle.value, 90); | |
locationY.value = max_Y.value; | |
} else if (locationY.value < min_Y.value) { | |
angle.value = angleReflect(angle.value, 90); | |
locationY.value = min_Y.value; | |
} | |
setTimeout(progress, 10); | |
}; | |
const start = () => { | |
setTimeout(progress, 100); | |
}; | |
const animatedStyle = useAnimatedStyle(() => { | |
return { | |
transform: [ | |
{ translateX: locationX.value }, | |
{ translateY: locationY.value } | |
] | |
}; | |
}); | |
useEffect(() => { | |
start(); | |
}, []); | |
return ( | |
<View style={{ flex: 1 }}> | |
<Animated.View style={animatedStyle}> | |
<View style={styles.ball} /> | |
</Animated.View> | |
</View> | |
); | |
}; | |
const styles = StyleSheet.create({ | |
ball: { | |
backgroundColor: "red", | |
position: "absolute", | |
borderRadius: 100, | |
width: BALL_SIZE, | |
height: BALL_SIZE | |
} | |
}); | |
export { Bounce }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment