Hello, how about we make our react native app a little bit fancy by adding preloading animations to our image component using the awesome reanimated2 library
We'll wrap the the Image component in an animated view having the same dimension as the image and create a state to manage the image status.
import React, { useEffect, useState } from "react";
import Animated, {
interpolateColor,
useAnimatedStyle,
useSharedValue,
withTiming,
} from "react-native-reanimated";
interface Props {
/**base64 string or url for the image */
uri: string;
width: number;
height: number;
}
const AppImage = ({ height, uri, width }: Props) => {
const [isImageLoading, setIsImageLoading] = useState(true);
return (
<Animated.View style={[{ width, height }]}>
<Animated.Image
{...{ height, width, source: { uri } }}
style={[{ width, height }]
resizeMethod="auto"
resizeMode="cover"
/>
</Animated.View>
);
};
export default AppImage;
The image opacity will be set to 0 on mounting while we animated the background of the animated view with a loop animation
When the image is loaded, we'll stop the loop animation and set the image opacity to 1
import React, { useEffect, useState } from "react";
import Animated, {
interpolateColor,
useAnimatedStyle,
useSharedValue,
withTiming,
} from "react-native-reanimated";
interface Props {
/**base64 string or url for the image */
uri: string;
width: number;
height: number;
}
const AppImage = ({ height, uri, width }: Props) => {
const [isImageLoading, setIsImageLoading] = useState(true);
const loop = useSharedValue(0); // this will be used to control the animation of the image container
const animatedContainerStyle = useAnimatedStyle(() => ({
backgroundColor: interpolateColor(loop.value, [0, 1], ["black", "white"]), // animate the background color of the image container
}));
const animatedImageStyle = useAnimatedStyle(() => ({
opacity: withTiming(isImageLoading ? 0 : 1, { duration: 500 }), // fade in image when loaded
}));
useEffect(() => {
let animationInterval: NodeJS.Timeout;
//start animation when the component mounts
animationInterval = setInterval(() => {
loop.value = withTiming(loop.value === 1 ? 0 : 1, { duration: 500 });
}, 250);
//stop animation when the image is loaded
!isImageLoading && clearInterval(animationInterval);
return () => clearInterval(animationInterval); //cleanup
}, [isImageLoading]);
return (
<Animated.View style={[{ width, height }, animatedContainerStyle]}>
<Animated.Image
{...{ height, width, source: { uri } }}
style={[{ width, height }, animatedImageStyle]}
onLoad={(e) => {
setIsImageLoading(false);
}}
resizeMethod="auto"
resizeMode="cover"
/>
</Animated.View>
);
};
export default AppImage;
Here is a preview
Top comments (0)