Skip to content

Instantly share code, notes, and snippets.

@uwemneku
Last active December 29, 2021 08:57
Show Gist options
  • Save uwemneku/0849d78c68ec73733001ff1b680acf24 to your computer and use it in GitHub Desktop.
Save uwemneku/0849d78c68ec73733001ff1b680acf24 to your computer and use it in GitHub Desktop.
How to add loading animation to an Image component in react native using reanimated2

How to add loading animation to a react native component using reanimated2

We'll wrap the the Image component in an animated view having the same dimension as the image. 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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment