Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add markers / annotations programatically with mapbox and react native

I'm new to react native and cannot find any documentation on how to add markers / annotations programatically to the map using mapbox.

We are using geofire query, which triggers when a point of interest is withing range.

Inside the trigger I want to insert the marker.

All the documentation I found about it is this: https://www.mapbox.com/help/first-steps-react-native-sdk/ which adds the marker during initialization and render.

Here is my code so far

    render () {
        const {navigate} = this.props.navigation;
        return (
          <View style ={{flex: 1, position: 'relative'}}>
            <Mapbox.MapView
                styleURL={Mapbox.StyleURL.Dark}
                zoomLevel={15}
                centerCoordinate={[11.256, 43.770]}
                ref={map => { this.map = map; }}
                style={{flex: 1}}>
                {this.renderAnnotations([11.256, 43.770])}
            </Mapbox.MapView>


            <View style={styles.menuMainContainer}>

                {this.state.menuStatus ? <Animatable.View style={styles.menuSubcontainer}  animation={"bounceIn"}>
                    <View style={{justifyContent: 'space-between', justifyContent: 'center', flex: 1, marginBottom: 50}}>
                      <View style={{flexDirection: 'row', justifyContent: 'space-around'}}>
                        <MenuOptions imageSource={Images.lightIcon} menuTag="trash" name="Basureros"/>
                        <MenuOptions imageSource={Images.lightIcon} menuTag="holes" name="Huecos"/>
                      </View>
                      <View style={{flexDirection: 'row', justifyContent: 'space-around'}}>
                        <MenuOptions imageSource={Images.lightIcon} menuTag="hydrants" name="Hidrantes"/>
                        <MenuOptions imageSource={Images.lightIcon} menuTag="parking" name="Estacionamiento"/>
                      </View>
                      <View style={{flexDirection: 'row', justifyContent: 'space-around'}}>
                        <MenuOptions imageSource={Images.lightIcon} menuTag="others" name="Otros"/>
                      </View>
                    </View>
                  </Animatable.View> : null
                }
            </View>

            <View style ={styles.bottomContainer}>

              <TouchableOpacity  style={styles.buttons}>
                <Text style={styles.buttonText}>Boton_1</Text>
              </TouchableOpacity>
              <TouchableOpacity onPress ={this._takePhotofromCamera} style={styles.buttons}>
                <Text style={styles.buttonText}>Agregar Reportes</Text>
              </TouchableOpacity>
              <TouchableOpacity style={styles.buttons} onPress = {() => this.toggleMenuStatus()}>
                <Text style={styles.buttonText}>Boton_3</Text>
              </TouchableOpacity>
            </View>

      </View>

        )
      }
    }


    renderAnnotations = (location) =>{
        console.log('entro renderan2')
        return(
          <Mapbox.PointAnnotation
            key='pointAnnotation'
            id='pointAnnotation'
            coordinate={location}>

            <View style={styles.annotationContainer}>
              <View style={styles.annotationFill} />
            </View>
            <Mapbox.Callout title='Look! An annotation!' />
          </Mapbox.PointAnnotation>


      )
      }

    this.state.geoQuery.on("key_entered", function(key, location, distance) {
           console.log(key + " is located at [" + location + "] which is within the query (" + distance.toFixed(2) + " km from center)");
this.renderAnnotations();
})

I'm getting: Error: this.renderAnnotations is not a function

I also tried copying the entire function inside this.state.geoQuery, no error, but markers are not showing either.

this.state.geoQuery.on("key_entered", function(key, location, distance) {
       console.log(key + " is located at [" + location + "] which is within the query (" + distance.toFixed(2) + " km from center)");
       return(
         <Mapbox.PointAnnotation
           key='pointAnnotation'
           id='pointAnnotation'
           coordinate={location}>

           <View style={styles.annotationContainer}>
             <View style={styles.annotationFill} />
           </View>
           <Mapbox.Callout title='Look! An annotation!' />
         </Mapbox.PointAnnotation>
     )});

Thanks

like image 649
Ricardo Chen He Avatar asked Jan 21 '18 19:01

Ricardo Chen He


People also ask

How do I add multiple markers to Mapbox?

To add multiple markers, or to add markers to interactive web or mobile maps, you generally must provide point data in GeoJSON format or in a vector tileset. You can add data to a map style before runtime by using the Mapbox Studio style editor to add a vector tileset as a source for a layer in a map style.

Can you use Mapbox With react native?

The Maps SDK for React Native is a community-maintained React Native library that provides reusable JavaScript components for integrating Mapbox maps into iOS and Android apps.

Can you use Mapbox with Expo?

In order to use native libraries with Expo, you must currently eject your project, creating iOS and Android build folders. This project demonstrates that process using the react-native-mapbox-gl library. In order to use Mapbox GL, you will we need an access token.


2 Answers

After chatting directly with Mapbox support, they told me PointAnnotation is legacy and should use ShapeSource and SymbolLayer instead, it have a LOT better performance. Here is how to do it:

    <Mapbox.MapView
                key='mainmap'
                textureMode={true}
                pitch={60}
                ref={(c) => this._map = c}
                onPress={this.onPress}
                styleURL={Mapbox.StyleURL.Light}
                zoomLevel={17}
                maxZoomLevel={20}
                minZoomLevel={15}
                centerCoordinate={this.initCenterLocation()}
                style={{ flex: 1 }}
                showUserLocation={true}
                userTrackingMode={Mapbox.UserTrackingModes.FollowWithHeading}
            >
                <Mapbox.ShapeSource
                    id='exampleShapeSource'
                    shape={this.state.featureCollection}
                    onPress={(feature) => this.onShapeSourceLayer(feature)}
                    images={{ assets: ['pin', 'm1_marker', 'm2_marker', 'm3_marker', 'm4_marker'] }}>
                    <Mapbox.SymbolLayer id='exampleIconName' minZoomLevel={1} style={stylesIcon.icon} />
                </Mapbox.ShapeSource>
            </Mapbox.MapView>

Insert new annotations / points:

    this.setState({
            featureCollection: Mapbox.geoUtils.addToFeatureCollection(
                this.state.featureCollection,
                Mapbox.geoUtils.makeFeature({ type: 'Point', coordinates: location }, { icon: iconImage, key: key }),
            ),
        });

On annotation Press function:

onShapeSourceLayer(e) {

    const feature = e.nativeEvent.payload;

    this.setState({
        annotationKey: feature.properties.key
    }, function () {

        this.togglePostModal(true)
    });

}
like image 126
Ricardo Chen He Avatar answered Sep 19 '22 21:09

Ricardo Chen He


Simple :

constructor() {
   this.state = {
      myMarker: [0, 0]//intial 0
   };
}

<Mapbox.MapView key='mainmap'> 
    <Mapbox.PointAnnotation
       key="key1"
       id="id1"
       title="Test"
       coordinate={this.state.myMarker}>
    </Mapbox.PointAnnotation>
</Mapbox.MapVie>


update latitude and longitude : 
   updateMyMarker(data){
   this.setState({myMarker: [data.Lng, data.Lat]})
}
like image 34
Khurshid Ansari Avatar answered Sep 19 '22 21:09

Khurshid Ansari