React 原生动画组件相互影响
React native animated components affecting each other
上下文:
我有一个名为 AnimatedSlider
的组件,它在 App.js
中被使用了两次。
AnimatedSlider
使用 React.Animated
来动画其中 View
的宽度。这是代码。
AnimatedSlider.js
import React, { useRef } from 'react';
import {
Text,
View,
StyleSheet,
TouchableWithoutFeedback,
Animated,
Easing,
} from 'react-native';
const { Value } = Animated;
const MENU_ITEM_WIDTH = 50;
const MENU_ITEM_FINAL_WIDTH = 200;
const sliderWidthAnimatedValue = new Value(MENU_ITEM_WIDTH);
export default function AnimatedSlider() {
const sliderState = useRef(-1);
const animateExpantion = () => {
Animated.timing(sliderWidthAnimatedValue, {
toValue: MENU_ITEM_FINAL_WIDTH,
duration: 250,
easing: Easing.linear,
useNativeDriver: false,
}).start();
};
const animateCollapse = () => {
Animated.timing(sliderWidthAnimatedValue, {
toValue: MENU_ITEM_WIDTH,
duration: 250,
easing: Easing.linear,
useNativeDriver: false,
}).start();
};
const animateSlider = () => {
if (sliderState.current === -1) {
animateExpantion();
sliderState.current = 1;
} else {
animateCollapse();
sliderState.current = -1;
}
};
return (
<View style={styles.container}>
<Text>Label</Text>
<TouchableWithoutFeedback onPress={animateSlider}>
<Animated.View
style={[styles.slidingMenu, { width: sliderWidthAnimatedValue }]}
/>
</TouchableWithoutFeedback>
</View>
);
}
const styles = StyleSheet.create({
container: {
width: '100%',
height: 50,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingLeft: 24,
marginBottom: 10,
backgroundColor: 'grey',
},
slidingMenu: {
height: '100%',
width: MENU_ITEM_WIDTH,
backgroundColor: 'pink',
},
});
App.js
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import AnimatedSlider from './components/AnimatedSlider';
export default function App() {
return (
<View style={styles.container}>
<AnimatedSlider menuColor='pink'/>
<AnimatedSlider menuColor='pink'/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});
问题:点击一个组件,似乎也会激活另一个组件。
可以看看小吃here
问题出在下一行的位置。
const sliderWidthAnimatedValue = new Value(MENU_ITEM_WIDTH);
在组件内移动它解决了这个问题。原因是 Value
的实例,因此 slideWidthAnimatedValue
在 AniatedSlider
组件的实例之间共享。
上下文:
我有一个名为 AnimatedSlider
的组件,它在 App.js
中被使用了两次。
AnimatedSlider
使用 React.Animated
来动画其中 View
的宽度。这是代码。
AnimatedSlider.js
import React, { useRef } from 'react';
import {
Text,
View,
StyleSheet,
TouchableWithoutFeedback,
Animated,
Easing,
} from 'react-native';
const { Value } = Animated;
const MENU_ITEM_WIDTH = 50;
const MENU_ITEM_FINAL_WIDTH = 200;
const sliderWidthAnimatedValue = new Value(MENU_ITEM_WIDTH);
export default function AnimatedSlider() {
const sliderState = useRef(-1);
const animateExpantion = () => {
Animated.timing(sliderWidthAnimatedValue, {
toValue: MENU_ITEM_FINAL_WIDTH,
duration: 250,
easing: Easing.linear,
useNativeDriver: false,
}).start();
};
const animateCollapse = () => {
Animated.timing(sliderWidthAnimatedValue, {
toValue: MENU_ITEM_WIDTH,
duration: 250,
easing: Easing.linear,
useNativeDriver: false,
}).start();
};
const animateSlider = () => {
if (sliderState.current === -1) {
animateExpantion();
sliderState.current = 1;
} else {
animateCollapse();
sliderState.current = -1;
}
};
return (
<View style={styles.container}>
<Text>Label</Text>
<TouchableWithoutFeedback onPress={animateSlider}>
<Animated.View
style={[styles.slidingMenu, { width: sliderWidthAnimatedValue }]}
/>
</TouchableWithoutFeedback>
</View>
);
}
const styles = StyleSheet.create({
container: {
width: '100%',
height: 50,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingLeft: 24,
marginBottom: 10,
backgroundColor: 'grey',
},
slidingMenu: {
height: '100%',
width: MENU_ITEM_WIDTH,
backgroundColor: 'pink',
},
});
App.js
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import AnimatedSlider from './components/AnimatedSlider';
export default function App() {
return (
<View style={styles.container}>
<AnimatedSlider menuColor='pink'/>
<AnimatedSlider menuColor='pink'/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});
问题:点击一个组件,似乎也会激活另一个组件。
可以看看小吃here
问题出在下一行的位置。
const sliderWidthAnimatedValue = new Value(MENU_ITEM_WIDTH);
在组件内移动它解决了这个问题。原因是 Value
的实例,因此 slideWidthAnimatedValue
在 AniatedSlider
组件的实例之间共享。