繁体   English   中英

React Native:使用动画和不透明度淡入一系列图像

[英]React Native: Fade through a series of images using Animated & opacity

我目前正在尝试淡出一系列图像。 基本上,我总是想一次显示一个图像,然后将其不透明度设置为从 1 到 0 以及系列中下一张图像的不透明度从 0 到 1,等等。 基本上是这样的,我已经在 ReactJS 和 CSS 动画中为 web 实现了:

ReactJS 中的淡入淡出动画

但是,我似乎一直坚持使用 React Native 的动画库和引用。 我试过将所有图像的不透明度存储在一个数组中,该数组本身包含在 useRef 挂钩中。 然后,使用 Animated,我尝试执行两个并行动画,它们改变当前图像索引和下一个索引的不透明度。 这就是我想出的:

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>
  );
}

但是,这似乎根本不起作用。 安装后,它只显示第一张图片,然后淡出那张图片,然后淡出所有其他图片并卡在那里:

在 React Native 中使用上述代码的图像混乱

有人知道我在哪里搞砸了吗? 我觉得我没有像我应该的那样将useRef()钩子与动画库结合使用。

您的解决方案非常聪明,通常看起来应该对我有用。 随着图像数量的增加,性能可能会受到影响。 我想到了另一种方法:对图像数组进行分区,然后使用 setInterval 在两个 Animated.Images 之间交替,从每个数组获取它们的源。

// 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>
  );
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM