[英]React Native: Fade through a series of images using Animated & opacity
我目前正在尝试淡出一系列图像。 基本上,我总是想一次显示一个图像,然后将其不透明度设置为从 1 到 0 以及系列中下一张图像的不透明度从 0 到 1,等等。 基本上是这样的,我已经在 ReactJS 和 CSS 动画中为 web 实现了:
但是,我似乎一直坚持使用 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>
);
}
但是,这似乎根本不起作用。 安装后,它只显示第一张图片,然后淡出那张图片,然后淡出所有其他图片并卡在那里:
有人知道我在哪里搞砸了吗? 我觉得我没有像我应该的那样将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.