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
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.
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.
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.
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)
});
}
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]})
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With