我最初使用setInterval()
来制作循环图像背景,方法是让两个图像从x:0
开始,另一个从x: imageWidth
开始,然后按以下方式更新它们:
_updateBackgroundImage = () => {
this.setState({
background1Left: this.state.background1Left > (-this.backgroundImageWidth) ? this.state.background1Left-3 : this.backgroundImageWidth,
background2Left: this.state.background2Left > (-this.backgroundImageWidth) ? this.state.background2Left-3 : this.backgroundImageWidth,
})
}
它工作得很好但是setInterval()
导致与在线库中的另一个组件发生冲突,因此我转而使用Animated
API并拥有以下代码:
this.translateValue = new Animated.Value(0)
translate() {
this.translateValue.setValue(0)
Animated.timing(
this.translateValue,
{
toValue: 1,
duration: 14000,
easing: Easing.linear
}
).start(()=>this.translate())
}
const translateBackgroundImage1 = this.translateValue.interpolate({ inputRange: [0, 1], outputRange: [0, -this.backgroundImageWidth] }) const translateBackgroundImage2 = this.translateValue.interpolate({ inputRange: [0, 1], outputRange: [this.backgroundImageWidth, -this.backgroundImageWidth] }) return ( <View style={{flex:1}}> <Animated.Image style={{ flex: 1, position: 'absolute', left: translateBackgroundImage1, }} resizeMode={Image.resizeMode.cover} source={this.backgroundImage} /> <Animated.Image style={{ flex: 1, position: 'absolute', left: translateBackgroundImage2, }} resizeMode={Image.resizeMode.cover} source={this.backgroundImage} />
要应用我用于setInterval()
的相同逻辑,我会translateBackgroundImage1
从第一个循环中的x:0
开始,然后从x: ImageWidth
开始
我不确定如何使用Animated
答案 0 :(得分:1)
我最终找到了解决方案。它不是很干净但有效。
我基本上从同一张图片中加载了两个Animated.image
。然后我有translateValue1
,它控制第一张图像的左侧位置。然后根据translateValue1
,我们translateValue2
的{{1}} offset
。 imagewidth
控制第二张图片的左侧位置。
当第一张图像即将从屏幕退出时,它将转到屏幕的最右侧,同时第二张图像将移动到第一张图像的正面,因此我们需要更改translateValue2
到offset
。因此,在两个动画函数中都有一个-imagewidth
方法。
在构造函数中我有以下变量:
setState
然后我有这两个函数,每个函数控制循环的一半:
constructor(props) {
super(props);
this.backgroundImage = require('../assets/images/graidenttPastel.jpg');
this.backgroundImageWidth = resolveAssetSource(this.backgroundImage).width;
this.translateXValue1 = new Animated.Value(-1);
this.translateXValue2 = new Animated.Value(0);
this.animationLength = 20000;
this.state = {
translateXValue2Offset: this.backgroundImageWidth,
stopAnimation: false,
}
最后在 translateXFirstHalfLoop() {
this.translateXValue1.setValue(-1);
this.setState({translateXValue2Offset: this.backgroundImageWidth});
this.firstHalfLoop = Animated.timing(
this.translateXValue1,
{
toValue: -this.backgroundImageWidth,
duration: this.animationLength/2,
easing: Easing.linear
}
).start(() => {
if(this.state.stopAnimation === false) {
this.translateXSecondHalfLoop()
}
})
}
translateXSecondHalfLoop() {
this.translateXValue1.setValue(this.backgroundImageWidth);
this.setState({translateXValue2Offset: -this.backgroundImageWidth});
this.secondHalfLoop = Animated.timing(
this.translateXValue1,
{
toValue: 0,
duration: this.animationLength/2,
easing: Easing.linear
}
).start(() => {
if(this.state.stopAnimation === false) {
this.translateXFirstHalfLoop()
}
})
}
方法中,我有两个render()
,如下所示:
Animated.Image
由于每个半循环函数都调用另一个,我们需要在卸载此组件之前停止它们,因此我们在下面添加了以下额外步骤:
render() {
this.translateXValue2 = Animated.add(this.translateXValue1, this.state.translateXValue2Offset);
return (
<SafeAreaView
style={[{backgroundColor: THEME_COLOR, flex: 1}]}
forceInset={{ bottom: 'never' }}>
<Animated.Image
style={{
position: 'absolute',
left: this.translateXValue1,
}}
resizestate={Image.resizeMode.cover}
source={this.backgroundImage}
/>
<Animated.Image
style={{
position: 'absolute',
left: this.translateXValue2,
}}
resizestate={Image.resizeMode.cover}
source={this.backgroundImage}
/>
<View style={{flex:1}}>
{this._renderScreenContent()}
</View>
</SafeAreaView>
);
}
答案 1 :(得分:0)
如果您想为ImageBackground
制作动画,请尝试
var AnimatedImage = Animated.createAnimatedComponent(ImageBackground)