当调用animateToRegion()时,MapView消失,并且直到调用animateToRegion()之后,位置标记才会渲染

时间:2019-02-07 04:33:18

标签: react-native react-native-ios react-native-maps react-animated react-android

在将地图添加到我的应用程序以使其在第一个渲染器上加载标记时遇到问题。这些标记应该与滚动视图中的建筑卡相对应。调用CustomMapView的App.js文件以5个建筑对象{title,description,lat,long}的数组的形式对虚拟数据进行了硬编码,将其提供给CustomMapView,然后CustomMapView将数据提供给其其余子对象(在下面的代码)

应用首次加载时如下所示:

Here

然后,当您滚动到下一个索引时,标记会出现(并带有动画),但地图会消失:

Here

这是我的第一个React Native项目,我已经尝试了好几天以找出标记未渲染和地图消失的问题。我基本上是在尝试使用包含建筑物的滚动视图制作地图,并且当您滚动到该“建筑卡”时,地图会以动画形式显示在建筑物上。任何帮助将不胜感激。谢谢!

class CustomMapView extends Component {

/*
    this.lastLoadedIndex
    this.animation
    this.state
    this.mapView
    this.interpolations
    this.regionTimeout
 */

constructor(props) {
    super(props);
    this.lastLoadedIndex = 0;
    this.animation = new Animated.Value(0);
    this.state = {
        buildings: this.props.buildings,
        region: this.props.initialRegion,
    };
}

componentDidMount() {
    this.beginAnimatingMapToMatchSelectedBuildingCard();
}

render() {

    this.interpolations = this.state.buildings.map((building, index) => {
        const inputRange = [(index - 1) * CARD_WIDTH, index * CARD_WIDTH, ((index + 1) * CARD_WIDTH)];

        const scale = this.animation.interpolate({
            inputRange,
            outputRange: [INACTIVE_MARKER_RADIUS_SCALE, ACTIVE__MARKER_RADIUS_SCALE, INACTIVE_MARKER_RADIUS_SCALE],
            extrapolate: "clamp",
        });

        const opacity = this.animation.interpolate({
            inputRange,
            outputRange: [INACTIVE_MARKER_OPACITY, ACTIVE_MARKER_OPACITY, INACTIVE_MARKER_OPACITY],
            extrapolate: "clamp",
        });
        return { scale, opacity };
    });


    return (
        <View style={StJamesMapViewStyle.container}>
            <MapWithBuildingMarkers root={this} interpolations={this.interpolations} region={this.state.region} buildings={this.state.buildings} />
            <BuildingCardSelectorView root={this} buildings={this.state.buildings}/>
        </View>
    );
}

beginAnimatingMapToMatchSelectedBuildingCard() {
    this.animation.addListener(({value}) => {
        let index = Math.floor(value / CARD_WIDTH + SCROLL_OFFSET);

        if (index < 0)
            index = 0;

        else if (index >= this.state.buildings.length)
            index = this.state.buildings.length - 1;


        clearTimeout(this.regionTimeout);

        this.regionTimeout = setTimeout(() => {

            if (this.lastLoadedIndex === index)
                return;

            this.lastLoadedIndex = index;
            const coordinateToBeLoaded = this.state.buildings[index].coordinate;
            const region = {
                latitude: coordinateToBeLoaded.latitude,
                longitude: coordinateToBeLoaded.longitude,
                latitudeDelta: this.state.region.latitudeDelta,
                longitudeDelta: this.state.region.longitudeDelta
            };
            this.mapView.animateToRegion(region, DURATION_AFTER_BUILDING_CARD_IS_SELECTED_TO_START_ANIMATING);
            console.log(region);
        }, DURATION_TO_ANIMATE_TO_REGION);
    });

}


}

class MapWithBuildingMarkers extends Component {

render() {
    const root = this.props.root;
    const buildings = this.props.buildings;
    const interpolations = this.props.interpolations;

    return (
        <MapView ref={mapView => root.mapView = mapView} //When we animateToRegion we render MapView which has Building Markers as its children
                 initialRegion={this.props.region}
                 style={StJamesMapViewStyle.container}>

            {buildings.map((building, index) => <BuildingMarker key={index} index={index} building={building} interpolations={interpolations}/>)}

        </MapView>);
}
}


class BuildingMarker extends Component {

render() {

    const scaleStyle = {transform: [{scale: this.props.interpolations[this.props.index].scale}]};
    const opacityStyle = {opacity: this.props.interpolations[this.props.index].opacity};

    return (
    <MapView.Marker coordinate={this.props.building.coordinate}>
            <AnimatedView style={[StJamesMapViewStyle.markerWrap, opacityStyle]}>
                <AnimatedView style={[StJamesMapViewStyle.ring, scaleStyle]}/>
                    <View style={StJamesMapViewStyle.marker} />
            </AnimatedView>
    </MapView.Marker>);
}
}


class BuildingCardSelectorView extends Component {

render() {

    const root = this.props.root;

    const scrollHandler = Animated.event([{
        nativeEvent: {
            contentOffset: {
                x: root.animation,
            }
        }}],
        { useNativeDriver: true }
    );

    return (
        <Animated.ScrollView horizontal
                             scrollEventThrottle={1}
                             showsHorizontalScrollIndicator={false}
                             snapToInterval={CARD_WIDTH}
                             onScroll={scrollHandler}
                             style={StJamesMapViewStyle.scrollView}
                             contentContainerStyle={StJamesMapViewStyle.endPadding}>

            {this.props.buildings.map((building, index) => <BuildingCard key={index}
                                                                         index={index}
                                                                         building={building}/>)}
        </Animated.ScrollView>
    );
}
}


class BuildingCard extends Component {

render() {
    return (
        <View style={StJamesMapViewStyle.card}>
            <Image source={this.props.building.imageURL} style={StJamesMapViewStyle.cardImage} resizeMode="cover"/>
            <View style={StJamesMapViewStyle.textContent}>
                <Text numberOfLines={1}> {this.props.building.title} </Text>
                <Text numberOfLines={1}> {this.props.building.description} </Text>
            </View>
        </View>
    );
}
}

0 个答案:

没有答案