How to detect when an animated element has reached a certain position. The element should not stop in this position. It should continue the off-screen animation.
When an element exceeds the given position (line), I have to trigger some action (e.g. change the color of the line to red).
const Component = () => {
const moveAnimX = useRef(new Animated.Value(0)).current;
const runAnimation = () => {
Animated.timing(moveAnimX, {
toValue: 2000, // out of screen
duration: 1500,
useNativeDriver: true,
}).start();
};
useEffect(() => {
runAnimation();
}, []);
return (
<Animated.View
style={[
{
height: 50,
width: 50,
backgroundColor: 'red',
transform: [
{
translateX: moveAnimX,
},
],
},
]}
/>
);
};
CodePudding user response:
Since you tagged the question with react-native-reanimated, here's how I would do it using Reanimated 2. You could probably translate this to use the RN Animated API.
- Get the line's x coordinate. If you don't set it imperatively, you could measure it with onLayout (shown below), or native methods if you need to know its position on the screen.
- Make a shared value that represents the x offset of the square.
- Create two animated styles - one for the position of the square, one for the color of the line.
- In the animated style for the color of the line, interpolate the x offset so that when the value is below that, it returns one color, and above that, returns another.
- Animate.
Pseudocode below
import Animated, {
interpolateColor,
useAnimatedStyle,
useSharedValue,
withTiming,
} from 'react-native-reanimated';
...
const [lineX, setLineX] = useState(0);
const squareOffsetX = useSharedValue(0);
const animatedSquareStyle = useAnimatedStyle(() => ({
left: squareOffsetX,
});
// the destination offset of the square - substitute whatever makes sense
const { width: screenWidth } = Dimensions.get('screen');
const animatedLineStyle = useAnimatedStyle(() => ({
backgroundColor: interpolateColor(
squareOffsetX.value,
[0, lineX - 1, lineX, screenWidth],
['black', 'black', 'red', 'red']
),
});
useEffect(() => {
squareOffsetX.value = withTiming(screenWidth, { duration: 5000 });
}, []);
...
return (
<>
<Animated.View
style={[styles.line, animatedLineStyle]}
onLayout={({ nativeEvent }) => setLineX(nativeEvent.layout.x)}
/>
<Animated.View style={[styles.square, animatedSquareStyle]} />
</>
);
CodePudding user response:
It's possible to get current value of Animated.Value
by adding addListener to it. The way how to achieve it is explained in this article
Then you can compare it with position of line and trigger action.