动画后更新动画视图的颜色
Update color of animated view after animation
我正在创建一个 React Native 应用程序,想在用户触摸动画视图后更改它的背景颜色。有关更多上下文,视图是正方形的,我在安装组件时将其旋转 225 度。如果用户触摸正方形,它会动画翻转动作并显示正方形的另一侧,这是不同的颜色。我用来执行此操作的代码如下所示:
const app = (props) => {
let colors = [color1, color2, color3, ...];
let index = 0;
let animatedValue= new Animated.Value(0);
let squareSpin = new Animated.Value(0);
let val = 0;
useEffect(() => {
Animated.timing(squareSpin, {
toValue: 1,
duration: 3000,
easing: Easing.linear,
}).start();
}, []);
const startSpin = squareSpin.interpolate({
inputRange: [0, 1],
outputRange: ["0deg", "225deg"],
});
animatedValue.addListener(({ value }) => {
val = value;
});
let frontInt= animatedValue.interpolate({
inputRange: [0, 180],
outputRange: ["0deg", "180deg"],
});
let backInt = animatedValue.interpolate({
inputRange: [0, 180],
outputRange: ["180deg", "360deg"],
});
let opacityFront = animatedValue.interpolate({
inputRange: [89, 90],
outputRange: [1, 0],
});
let opacityBack = animatedValue.interpolate({
inputRange: [89, 90],
outputRange: [0, 1],
});
const flip= () => {
if (val>= 90) {
Animated.spring(animatedValue, {
toValue: 0,
friction: 6,
tension: 8,
}).start();
} else {
Animated.spring(animatedValue, {
toValue: 180,
friction: 6,
tension: 8,
}).start();
}
};
const frontAnimated = {
transform: [{ rotateY: frontInt }],
};
const backAnimated = {
transform: [{ rotateY: backInt}],
};
return (
<Animated.View
style={{transform: [{ rotate: startSpin }] }}
>
<TouchableWithoutFeedback
onPress={() => {
index++;
flip();
}}>
<Animated.View
style={[
styles.shape,
{
backgroundColor:
colors[index % colors.length],
},
frontAnimated ,
{ opacity: opacityFront },
]}
>
</Animated.View>
<Animated.View
style={[
styles.shape,
{
backgroundColor:
colors[(index + 1) % colors.length],
},
{ position: "absolute" },
backAnimated ,
{ opacity: opacityBack },
]}
></Animated.View>
</TouchableWithoutFeedback>
<Animated.View>
)
}
问题:动画效果都很好,但问题是我翻转的正方形的每一侧只能呈现一种颜色。请注意,在 colors
数组中,方块应根据用户按下方块的次数显示多种颜色。然而,这并没有发生,正方形的每一侧总是开始时的颜色(color1 用于正方形的顶部,color2 用于正方形的底部)。我认为发生这种情况是因为 view
没有意识到索引正在发生变化,因为它永远不会再次呈现。或者,由于 Animated.View
的某些属性,它可能根本无法改变它的颜色,我不太确定。我尝试在使用 useState
按下正方形时强制进行渲染,但这导致正方形撤消了组件安装时发生的旋转,这是我不希望发生的。如何让视图的背景颜色根据用户点击的次数而改变?
谢谢!
内部渲染方法
const BackgroundColorConfig = this.Animation.interpolate(
{
inputRange: [ 0, 0.2, 0.4, 0.6, 0.8, 1 ],
outputRange: [ '#f6f6f6', '#f6f6f6', '#f6f6f6', LIGHT_RED_COLOR, LIGHT_RED_COLOR, LIGHT_RED_COLOR ]
});
usage backgroundColor:BackgroundColorConfig
将以上属性赋予您的组件(它应该在 Animated.View 标签下)
制作一个调用动画的函数,并在 componentDidMount 或按钮点击时使用它
Define this.Animated = new Animated.value(0)
在构造函数中
StartBackgroundColorAnimation = (value) =>
{
Animated.timing(
this.Animation,
{
toValue: value,
duration: 600
}
).start();
}
我能够通过使用两个不同的颜色插值值来解决这个问题。
let colorSideOne = colorValue1.interpolate({
inputRange: [...Array(colors.length)].map((_, index) => index),
outputRange: colors,
});
let colorSideTwo = colorValue2.interpolate({
inputRange: [...Array(colors.length)].map((_, index) => index),
outputRange: colors,
});
并使用这些值将颜色设置为卡片的背景
<Animated.View
style={[
styles.shape,
{
backgroundColor: colorSideOne,
},
frontAnimated,
{ opacity: opacityFront },
]}>
</Animated.View>
<Animated.View
style={[
styles.shape,
{
backgroundColor: colorSideTwo,
},
frontAnimated,
{ opacity: opacityFront },
]}>
</Animated.View>
您现在只需根据索引正确更新 colorValues。
注意前后值需要交替进行
<TouchableWithoutFeedback
style={{
borderWidth: 2,
borderColor: 'red',
}}
onPress={() => {
index++;
//side = side === 'front' ? 'back' : 'front';
//console.log('side',side);
// console.log('index',index, 'color length', colors.length);
if (index & 1) {
colorValue1.setValue((index + 1) % colors.length);
} else {
colorValue2.setValue((index + 1) % colors.length);
}
// console.log('color value', colorValue1, colorValue2);
flip();
}}>
....
....
为了清楚起见,我附上了这个博览会 demo
希望这就是您所期待的!
我正在创建一个 React Native 应用程序,想在用户触摸动画视图后更改它的背景颜色。有关更多上下文,视图是正方形的,我在安装组件时将其旋转 225 度。如果用户触摸正方形,它会动画翻转动作并显示正方形的另一侧,这是不同的颜色。我用来执行此操作的代码如下所示:
const app = (props) => {
let colors = [color1, color2, color3, ...];
let index = 0;
let animatedValue= new Animated.Value(0);
let squareSpin = new Animated.Value(0);
let val = 0;
useEffect(() => {
Animated.timing(squareSpin, {
toValue: 1,
duration: 3000,
easing: Easing.linear,
}).start();
}, []);
const startSpin = squareSpin.interpolate({
inputRange: [0, 1],
outputRange: ["0deg", "225deg"],
});
animatedValue.addListener(({ value }) => {
val = value;
});
let frontInt= animatedValue.interpolate({
inputRange: [0, 180],
outputRange: ["0deg", "180deg"],
});
let backInt = animatedValue.interpolate({
inputRange: [0, 180],
outputRange: ["180deg", "360deg"],
});
let opacityFront = animatedValue.interpolate({
inputRange: [89, 90],
outputRange: [1, 0],
});
let opacityBack = animatedValue.interpolate({
inputRange: [89, 90],
outputRange: [0, 1],
});
const flip= () => {
if (val>= 90) {
Animated.spring(animatedValue, {
toValue: 0,
friction: 6,
tension: 8,
}).start();
} else {
Animated.spring(animatedValue, {
toValue: 180,
friction: 6,
tension: 8,
}).start();
}
};
const frontAnimated = {
transform: [{ rotateY: frontInt }],
};
const backAnimated = {
transform: [{ rotateY: backInt}],
};
return (
<Animated.View
style={{transform: [{ rotate: startSpin }] }}
>
<TouchableWithoutFeedback
onPress={() => {
index++;
flip();
}}>
<Animated.View
style={[
styles.shape,
{
backgroundColor:
colors[index % colors.length],
},
frontAnimated ,
{ opacity: opacityFront },
]}
>
</Animated.View>
<Animated.View
style={[
styles.shape,
{
backgroundColor:
colors[(index + 1) % colors.length],
},
{ position: "absolute" },
backAnimated ,
{ opacity: opacityBack },
]}
></Animated.View>
</TouchableWithoutFeedback>
<Animated.View>
)
}
问题:动画效果都很好,但问题是我翻转的正方形的每一侧只能呈现一种颜色。请注意,在 colors
数组中,方块应根据用户按下方块的次数显示多种颜色。然而,这并没有发生,正方形的每一侧总是开始时的颜色(color1 用于正方形的顶部,color2 用于正方形的底部)。我认为发生这种情况是因为 view
没有意识到索引正在发生变化,因为它永远不会再次呈现。或者,由于 Animated.View
的某些属性,它可能根本无法改变它的颜色,我不太确定。我尝试在使用 useState
按下正方形时强制进行渲染,但这导致正方形撤消了组件安装时发生的旋转,这是我不希望发生的。如何让视图的背景颜色根据用户点击的次数而改变?
谢谢!
内部渲染方法
const BackgroundColorConfig = this.Animation.interpolate(
{
inputRange: [ 0, 0.2, 0.4, 0.6, 0.8, 1 ],
outputRange: [ '#f6f6f6', '#f6f6f6', '#f6f6f6', LIGHT_RED_COLOR, LIGHT_RED_COLOR, LIGHT_RED_COLOR ]
});
usage backgroundColor:BackgroundColorConfig
将以上属性赋予您的组件(它应该在 Animated.View 标签下)
制作一个调用动画的函数,并在 componentDidMount 或按钮点击时使用它
Define this.Animated = new Animated.value(0)
在构造函数中
StartBackgroundColorAnimation = (value) =>
{
Animated.timing(
this.Animation,
{
toValue: value,
duration: 600
}
).start();
}
我能够通过使用两个不同的颜色插值值来解决这个问题。
let colorSideOne = colorValue1.interpolate({
inputRange: [...Array(colors.length)].map((_, index) => index),
outputRange: colors,
});
let colorSideTwo = colorValue2.interpolate({
inputRange: [...Array(colors.length)].map((_, index) => index),
outputRange: colors,
});
并使用这些值将颜色设置为卡片的背景
<Animated.View
style={[
styles.shape,
{
backgroundColor: colorSideOne,
},
frontAnimated,
{ opacity: opacityFront },
]}>
</Animated.View>
<Animated.View
style={[
styles.shape,
{
backgroundColor: colorSideTwo,
},
frontAnimated,
{ opacity: opacityFront },
]}>
</Animated.View>
您现在只需根据索引正确更新 colorValues。
注意前后值需要交替进行
<TouchableWithoutFeedback
style={{
borderWidth: 2,
borderColor: 'red',
}}
onPress={() => {
index++;
//side = side === 'front' ? 'back' : 'front';
//console.log('side',side);
// console.log('index',index, 'color length', colors.length);
if (index & 1) {
colorValue1.setValue((index + 1) % colors.length);
} else {
colorValue2.setValue((index + 1) % colors.length);
}
// console.log('color value', colorValue1, colorValue2);
flip();
}}>
....
....
为了清楚起见,我附上了这个博览会 demo
希望这就是您所期待的!