How to place marker when click anywhere on the map view in react-native
Asked Answered
F

2

12

My requirement is, I need to show the marker on the MaoView, when user clicks anywhere on the map and also need to get coordinates (latitude & longitude) of location where the marker is placed.

Here's what I tried:

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>
        );
    }
}
Frobisher answered 3/4, 2017 at 14:34 Comment(1)
any update on this?Coerce
H
25

First of all, take an empty array for map markers.

constructor(props) {
  super(props)

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

Then push coordinates of clicked locations as a new marker in array. Finally, in your <MapView>, render all markers:

<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>

Whenever you click anywhere on map, the location's coordinates will be added in markers array and as state is updated, render() function will be called again and all markers will be placed on map including the new marker.


EDIT
@FortuneCookie's comment:

To show only one marker on the map and when user taps on elsewhere the other marker gets removed, just like dropping a pin.

It is much more simpler. First of all, change markers array to single marker in state.

constructor(props) {
  super(props)

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

And for <MapView>, just change its children & onPress event.

<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>

You don't have to to put multiple markers in array and then loop through it. Rather, you just put your selected location's coordinates to state as a single marker and (if marker exists) then just render it on map. It will automatically set selected location to the state and remove any previously selected ones.

Horne answered 1/1, 2019 at 12:45 Comment(5)
But this creates multiple markers on the map. Is it possible to show only one marker on the map and when user taps on elsewhere the other marker gets removed, just like drop a pin??Dorsal
Edited my answer. Hope that'll help!Horne
@TalhaSiddiqi thank the lord for your help, i've been trying to find a working solution for a similar problem and nothing helped but yours. Have a good day!Botulinus
I know this is an old post, but what would this look like if you use function based and useEffect/Hooks?Saffron
onPress is not invoking if we press on any icon on map.Gaslight
B
4

For functional component

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>
Billat answered 3/4, 2023 at 6:53 Comment(1)
Thank You!! I'm using Expo and its MapView component. This was the perfect fix I needed. I couldn't find a way to register a press on the map otherwise.Thyestes

© 2022 - 2024 — McMap. All rights reserved.