如何在React Native的地图视图上单击任意位置时放置标记?

9

我的需求是,当用户在地图上点击任何位置时,我需要在MaoView上显示标记,并且需要获取放置标记的位置的坐标(纬度和经度)。

以下是我尝试过的方法:

class Maps extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            region: {
                latitude: LATITUDE,
                longitude: LONGITUDE,
                latitudeDelta: LATITUDE_DELTA,
                longitudeDelta: LONGITUDE_DELTA
            },
            marker: {
                latlng: {
                    latitude: 17.6868,
                    longitude: 83.2185,
                    latitudeDelta: LATITUDE_DELTA,
                    longitudeDelta: LONGITUDE_DELTA
                }
            }
        };
    }
    
    onMapPress(e) {
        alert("coordinates:" + JSON.stringify(e.nativeEvent.coordinate));

        this.setState({
            marker: [
                {
                    coordinate: e.nativeEvent.coordinate
                }
            ]
        });
    }

    handleMarkerPress(event) {
        const markerID = event.nativeEvent.identifier;
        alert(markerID);
    }

    render() {
        return (
            <MapView
                identifier={"1"}
                ref={component => (this.map = component)}
                provider={this.props.provider}
                style={styles.map}
                region={this.state.region}
                onPress={this.onMapPress.bind(this)}
                //onPress={(event) => this.onMapPress(event)}
                provider={PROVIDER_DEFAULT}
                mapType="standard"
                zoomEnabled={true}
                pitchEnabled={true}
                showsUserLocation={true}
                followsUserLocation={true}
                showsCompass={true}
                showsBuildings={true}
                showsTraffic={true}
                showsIndoors={true}
            >
                <MapView.Marker coordinate={this.state.marker.latlng} />
            </MapView>
        );
    }
}

这个有任何更新吗? - Nisarg Thakkar
2个回答

24

首先,创建一个空数组来存储地图标记。

constructor(props) {
  super(props)

  this.state = {
    region: {
      latitude: LATITUDE, 
      longitude: LONGITUDE,
      latitudeDelta: LATITUDE_DELTA,
      longitudeDelta: LONGITUDE_DELTA
    },
    markers: []        // Here it is
  }
}

然后将点击位置的坐标作为一个新的标记点加入到数组中。最后,在您的<MapView>中渲染所有标记点:

<MapView style={styles.map} region={this.state.region}
onPress={(e) => this.setState({ markers: [...this.state.markers, { latlng: e.nativeEvent.coordinate }] })}>
{
    // loop through markers array & render all markers
    this.state.markers.map((marker, i) => (
        <MapView.Marker coordinate={marker.latlng} key={i} />
    ))
}
</MapView>
无论您在地图上点击任何位置,该位置的坐标都将被添加到markers数组中,并且更新staterender()函数将再次被调用,在地图上放置所有标记,包括新标记。

编辑
@FortuneCookie 的评论:

仅在地图上显示一个标记,并在用户单击其他位置时删除另一个标记,就像放置大头针一样。

这更简单。首先,将markers数组更改为状态中的单个marker

constructor(props) {
  super(props)

  this.state = {
    region: {
      latitude: LATITUDE, 
      longitude: LONGITUDE,
      latitudeDelta: LATITUDE_DELTA,
      longitudeDelta: LONGITUDE_DELTA
    },
    // markers: []        Change this
    marker: null          // to this
  }
}

对于 <MapView>,只需更改其子元素和 onPress 事件。

<MapView style={styles.map} region={this.state.region}
onPress={(e) => this.setState({ marker: e.nativeEvent.coordinate })}>
{
      // if state contains marker variable with a valid value, render the marker
      this.state.marker &&
      <MapView.Marker coordinate={this.state.marker} />
}
</MapView>
你不需要在数组中放置多个标记,然后循环它。相反,你只需将所选位置的坐标作为单个标记放入state中,(如果标记存在)则只需在地图上呈现它。它会自动将所选位置设置为状态并删除任何先前选择的位置。

但这会在地图上创建多个标记。是否有可能仅显示一个标记,并在用户点击其他位置时删除另一个标记,就像放置图钉一样? - FortuneCookie
修改了我的回答。希望能有所帮助! - TalESid
@TalhaSiddiqi 感谢上帝您的帮助,我一直在尝试寻找一个可行的解决方案来解决类似的问题,但是没有什么帮助,只有您的解决方案有效。祝您有美好的一天! - leveeee
1
我知道这是一个旧帖子,但如果您使用基于函数的组件和useEffect/Hooks,它会是什么样子? - TinaDitte
如果我们在地图上按任何图标,onPress不会被调用。 - Rehan Shakir

2

针对功能组件

const [marker, setMarker] = useState(null)
 <MapView
        //   ref={data}
        provider={PROVIDER_GOOGLE} // remove if not using Google Maps
        style={styles.map}
        region={region}
        zoomEnabled={true}
        maxZoomLevel={zoom-3}
        minZoomLevel={2}
        scrollEnabled={true}
        showsScale={true}
        zoomControlEnabled={true}
        zoomTapEnabled={true}
        // mapType={'satellite'}
        rotateEnabled={false}
        showsUserLocation={true}
        userLocationUpdateInterval={5000}
        showsMyLocationButton={true}
        loadingEnabled={true}
        showsCompass={true}
        onPress={(e) => setMarker(e.nativeEvent.coordinate)}
      >
{marker!=null?
        <Marker
          draggable
          coordinate={marker}
          onPress={()=>Alert.alert("test")}

        />:null}
</MapView>

谢谢!我正在使用Expo和它的MapView组件。这正是我需要的完美解决方案。否则,我找不到在地图上注册按压的方法。 - Joshua Santiago

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接