我的目标是在滑动到每个Card(Animated.ScrollView)时,为每个MapView.Marker设置屏幕动画。已经尝试过了,并且可以正常工作,但是现在我对代码做了一些更改,因为我添加了React Redux。
我认为可能是有关指出React Redux状态或密钥的问题,因为我收到有关密钥的警告。它说:
警告:列表中的每个孩子都应该有唯一的“关键”道具。
我想为每个MapView.Marker动画屏幕,就像这样:
这是我的代码:
componentWillMount() {
this.index = 0;
this.animation = new Animated.Value(0);
}
componentDidMount() {
// We should detect when scrolling has stopped then animate
// We should just debounce the event listener here
this.animation.addListener(({ value }) => {
let index = Math.floor(value / CARD_WIDTH + 0.3); // animate 30% away from landing on the next item
if (index >= this.props.events.length) {
index = this.props.events.length - 1;
} else {
return null;
}
if (index <= 0) {
index = 0;
} else {
return null;
}
clearTimeout(this.regionTimeout);
this.regionTimeout = setTimeout(() => {
if (this.index !== index) {
this.index = index;
const { focusedLocation } = this.props.events.location.value.latitude && this.props.events.location.value.longitude[index];
this.map.animateToRegion(
{
...focusedLocation,
latitudeDelta: this.state.focusedLocation.latitudeDelta,
longitudeDelta: this.state.focusedLocation.longitudeDelta,
},
350
);
}
}, 10);
});
}
render() {
//For the Scroll View Card
const interpolations = this.props.events.map((marker, index) => {
const inputRange = [
(index - 1) * CARD_WIDTH,
index * CARD_WIDTH,
((index + 1) * CARD_WIDTH),
];
const scale = this.animation.interpolate({
inputRange,
outputRange: [1, 2.5, 1],
extrapolate: "clamp",
});
const opacity = this.animation.interpolate({
inputRange,
outputRange: [0.35, 1, 0.35],
extrapolate: "clamp",
});
return { scale, opacity };
});
return(
<View style={styles.container}>
{/* <StatusBar backgroundColor={'transparent'} translucent={true}/> */}
<MapView
style={styles.container}
initialRegion={this.state.focusedLocation}
onPress={this.pickLocationHandler}
showsUserLocation={true}
ref={ref => this.map = ref} //For animating map movement
>
{userMarker}
{this.props.events.map((marker, index) => {
if(marker.location) {
const scaleStyle = {
transform: [
{
scale: interpolations[index].scale,
},
],
};
const opacityStyle = {
opacity: interpolations[index].opacity,
};
return (
<MapView.Marker key={index} coordinate={marker.location}>
<Animated.View style={[styles.markerWrap, opacityStyle]}>
<Animated.View style={[styles.ring, scaleStyle]} />
<View style={styles.marker} />
</Animated.View>
</MapView.Marker>
);
} else {
return null;
}
})}
</MapView>
<Animated.ScrollView
horizontal
scrollEventThrottle={1}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
snapToInterval={snapInterval}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
x: this.animation,
},
},
},
],
{ useNativeDriver: true }
)}
style={styles.scrollView}
contentContainerStyle={styles.endPadding}
>
<FlatList
keyExtractor={this._keyExtractor}
horizontal
data={this.props.events}
renderItem={(info) => (
<TouchableOpacity onPress={() => this.itemSelectedHandler(info.item.key)}>
<View style={styles.card} key={info.item.key}>
<Image
source={info.item.image}
style={styles.cardImage}
resizeMode="cover"
/>
<View style={styles.textContent}>
<Text numberOfLines={1} style={styles.cardtitle}>{info.item.name}</Text>
<Text numberOfLines={1} style={styles.cardDescription}>
{info.item.description}
</Text>
</View>
</View>
</TouchableOpacity>
)}
/>
</Animated.ScrollView>
<TouchableOpacity onPress={this.getLocationHandler} style={styles.iconContainer}>
<Icon name="md-locate" size={30} color="blue"/>
</TouchableOpacity>
</View>
);
}
}
const mapStateToProps = state => {
return {
events: state.events.events
};
};
export default connect(mapStateToProps)(EventMap);
我的React Redux代码:
../../ reducers / events.js:
const reducer = (state = initialState, action) => {
switch (action.type) {
case ADD_EVENT:
return {
...state,
events: state.events.concat({
key: `${Math.random()}`,
name: action.eventName,
description: action.eventDescription,
location: action.location,
image: {
uri: "https://c1.staticflickr.com/5/4096/4744241983_34023bf303_b.jpg"
}
})
};