Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

397
Visualizações
React Native: Fade through a series of images using Animated & opacity

I'm currently trying to fade through a series of images. Basically, I always want to display one image at a time, then animate its opacity from 1 to 0 and that of the next image in the series from 0 to 1, and so on. Basically something like this, which I've already implemented for the web in ReactJS and CSS animations:

Fade animation in ReactJS

However, I seem to keep getting stuck on using React Native's Animated library and refs. I've tried storing the opacity of all the images in an array which itself is contained in an useRef hook. Then, using Animated, I'm trying to perform two parallel animations which change the opacity of the current image index and that of the next index. This is what I've come up with:

export default function StartImageSwitcher() {
  const images = Object.values(Images).map((img) => img.imageNoShadow);

  const [currentImage, setCurrentImage] = useState(0);
  const opacity = useRef<Animated.Value[]>([
    new Animated.Value(1),
    ...Array(images.length - 1).fill(new Animated.Value(0)),
  ]).current;

  useEffect(() => {
    let nextImage = currentImage + 1;
    if (nextImage >= images.length) nextImage = 0;

    Animated.parallel([
      Animated.timing(
        opacity[currentImage],
        {
          toValue: 0,
          duration: 2000,
          useNativeDriver: true,
        },
      ),
      Animated.timing(
        opacity[nextImage],
        {
          toValue: 1,
          duration: 2000,
          useNativeDriver: true,
        },
      ),
    ]).start(() => {
      setCurrentImage(nextImage);
    });
  }, [currentImage]);

  images.map((image, index) => console.log(index, opacity[index]));

  return (
    <View style={styles.imageWrapper}>
      {
      images.map((image, index) => (
        <Animated.Image style={{ ...styles.image, opacity: opacity[index] }} source={image} key={index} />
      ))
    }
    </View>
  );
}

However, this doesn't seem to work at all. When mounted, it only shows the first image, then fades that one out and all the other images in and gets stuck there:

Image clutter using the above code in React Native

Anyone got an idea where I messed up? I feel like I'm not using the useRef() hook in combination with the Animated library like I'm supposed to.

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

Your solution is pretty clever, and it generally looks like it should work to me. Performance might take a hit though as the number of images increases. I thought of an alternate method: partition the images array and then use setInterval to alternate between two Animated.Images, which get their source from each array.

// from https://stackoverflow.com/questions/41932345/get-current-value-of-animated-value-react-native
const getAnimatedValue = (value: Animated.Value) => Number.parseInt(JSON.stringify(value));

export default function StartImageSwitcher() {
  // partition images into two arrays
  const images1 = [];
  const images2 = [];
  Object.values(Images).forEach((img, i) => {
    (i % 1 === 0 ? images1 : images2).push(img.imageNoShadow)
  });

  // use refs for the indexes so values don't become stale in the setInterval closure
  const images1Index = useRef(0);
  const images2Index = useRef(0);
  const image1Opacity = useRef(new Animated.Value(1)).current;
  const image2Opacity = useRef(new Animated.Value(0)).current;

  useEffect(() => {
    const swapImageInterval = setInterval(() => {
      const newImage1Opacity = getAnimatedValue(image1Opacity) === 1 ? 0 : 1;
      const newImage2Opacity = getAnimatedValue(image2Opacity) === 1 ? 0 : 1;

      Animated.parallel([
        Animated.timing(image1Opacity, {
          toValue: newImage1Opacity,
          duration: 2000,
          useNativeDriver: true,
        }),
        Animated.timing(image2Opacity, {
          toValue: newImage2Opacity,
          duration: 2000,
          useNativeDriver: true,
        }),
      ]).start(() => {
        if (newImage1Opacity === 1) {
          // image 2 is now faded out, so we can swap out its source
          const nextIndex = images2Index.current === images2.length - 1 ? 0 : images2Index.current + 1;
          images2Index.current = nextIndex;
        } else {
          // image 1 is faded out, so we can swap out its source 
          const nextIndex = images1Index.current === images1.length - 1 ? 0 : images1Index.current + 1;
          images1Index.current = nextIndex;
        }
      })
    }, 5000)

    return () => clearInterval(swapImageInterval);
  }, [images1Index, images2Index]);

  return (
    <View style={styles.imageWrapper}>
      <Animated.Image style={{ ...styles.image, opacity: image1Opacity }} source={images1[images1Index.current]} />
      <Animated.Image style={{ ...styles.image, opacity: image2Opacity }} source={images2[images2Index.current]} />
    </View>
  );
}
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda