Composants React Native Map pour iOS + Android
Ce projet est maintenu par un petit groupe de personnes, et toute aide concernant les problèmes et les demandes d'extraction est toujours appréciée. Si vous êtes capable et désireux de contribuer, veuillez lire les lignes directrices.
Voir les instructions d'installation.
Voir les instructions de configuration pour l'exemple de projet inclus.
react-native >= 0.74
.react-native >= 0.64.3
. API du composant <MapView />
API du composant <Marker />
<Callout />
API du composant
API du composant <Polygon />
API du composant <Polyline />
API du composant <Circle />
API du composant <Overlay />
<Heatmap />
API du composant
<Geojson />
API du composant
import MapView from 'react-native-maps' ;
ou
var MapView = require ( 'react-native-maps' ) ;
Ce composant MapView est construit de manière à ce que les entités de la carte (telles que les marqueurs, les polygones, etc.) soient spécifiées comme enfants du MapView lui-même. Cela fournit une API intuitive et de type réaction pour contrôler de manière déclarative les fonctionnalités de la carte.
< MapView
initialRegion = { {
latitude : 37.78825 ,
longitude : - 122.4324 ,
latitudeDelta : 0.0922 ,
longitudeDelta : 0.0421 ,
} }
/ >
getInitialState ( ) {
return {
region : {
latitude : 37.78825 ,
longitude : - 122.4324 ,
latitudeDelta : 0.0922 ,
longitudeDelta : 0.0421 ,
} ,
} ;
}
onRegionChange ( region ) {
this . setState ( { region } ) ;
}
render ( ) {
return (
< MapView
region = { this . state . region }
onRegionChange = { this . onRegionChange }
/ >
) ;
}
import { Marker } from 'react-native-maps' ;
< MapView region = { this . state . region } onRegionChange = { this . onRegionChange } >
{ this . state . markers . map ( ( marker , index ) => (
< Marker
key = { index }
coordinate = { marker . latlng }
title = { marker . title }
description = { marker . description }
/ >
) ) }
< / MapView > ;
png
avec différentes résolutions (appelons-les custom_pin
) - pour plus d'informations, accédez à Android, iOS < Marker
coordinate = { { latitude : latitude , longitude : longitude } }
image = { { uri : 'custom_pin' } }
/ >
Remarque : Vous pouvez également transmettre les données binaires de l'image telles que image={require('custom_pin.png')}
, mais cela ne s'adaptera pas correctement aux différentes tailles d'écran.
Remarque : Cela a des implications en termes de performances. Si vous souhaitez une solution plus simple, optez pour une image personnalisée (évitez-vous les maux de tête)
< Marker coordinate = { { latitude : latitude , longitude : longitude } } >
< MyCustomMarkerView { ... marker } / >
< / Marker >
import { Callout } from 'react-native-maps' ;
< Marker coordinate = { marker . latlng } >
< MyCustomMarkerView { ... marker } / >
< Callout >
< MyCustomCalloutView { ... marker } / >
< / Callout >
< / Marker > ;
< MapView initialRegion = { ... } >
< Marker draggable
coordinate = { this . state . x }
onDragEnd = { ( e ) => this . setState ( { x : e . nativeEvent . coordinate } ) }
/ >
< / MapView >
import { UrlTile } from 'react-native-maps' ;
< MapView region = { this . state . region } onRegionChange = { this . onRegionChange } >
< UrlTile
/**
* The url template of the tile server. The patterns {x} {y} {z} will be replaced at runtime
* For example, http://c.tile.openstreetmap.org/{z}/{x}/{y}.png
*/
urlTemplate = { this . state . urlTemplate }
/**
* The maximum zoom level for this tile overlay. Corresponds to the maximumZ setting in
* MKTileOverlay. iOS only.
*/
maximumZ = { 19 }
/**
* flipY allows tiles with inverted y coordinates (origin at bottom left of map)
* to be used. Its default value is false.
*/
flipY = { false }
/ >
< / MapView > ;
Pour Android : ajoutez la ligne suivante dans votre AndroidManifest.xml
< uses-permission android : name = " android.permission.INTERNET " />
Pour IOS : configurez App Transport Security dans votre application
Cette bibliothèque fonctionne avec Fabric en utilisant la nouvelle couche d'interopérabilité du moteur de rendu
Un message d'avertissement s'affiche indiquant que ces étapes ne sont pas nécessaires ; mais nous n'avons pas pu faire fonctionner l'exemple sans eux jusqu'à présent.
Ouvrez votre fichier de configuration : Localisez le fichier react-native-config
dans le répertoire de votre projet.
Ajoutez la configuration suivante : incluez le tableau unstable_reactLegacyComponentNames
pour les plates-formes Android et iOS, comme indiqué ci-dessous :
module . exports = {
project : {
android : {
unstable_reactLegacyComponentNames : [
'AIRMap' ,
'AIRMapCallout' ,
'AIRMapCalloutSubview' ,
'AIRMapCircle' ,
'AIRMapHeatmap' ,
'AIRMapLocalTile' ,
'AIRMapMarker' ,
'AIRMapOverlay' ,
'AIRMapPolygon' ,
'AIRMapPolyline' ,
'AIRMapUrlTile' ,
'AIRMapWMSTile' ,
] ,
} ,
ios : {
unstable_reactLegacyComponentNames : [
'AIRMap' ,
'AIRMapCallout' ,
'AIRMapCalloutSubview' ,
'AIRMapCircle' ,
'AIRMapHeatmap' ,
'AIRMapLocalTile' ,
'AIRMapMarker' ,
'AIRMapOverlay' ,
'AIRMapPolygon' ,
'AIRMapPolyline' ,
'AIRMapUrlTile' ,
'AIRMapWMSTile' ,
] ,
} ,
} ,
} ;
consultez l'exemple de projet pour le voir en action.
Les vignettes peuvent être stockées localement dans l'appareil à l'aide du schéma de mosaïque xyz et également affichées sous forme de superposition de vignettes. Ceci est particulièrement utile pour l'utilisation de la carte hors ligne lorsque des tuiles sont disponibles pour la région cartographique sélectionnée dans le stockage de l'appareil.
import { LocalTile } from 'react-native-maps' ;
< MapView region = { this . state . region } onRegionChange = { this . onRegionChange } >
< LocalTile
/**
* The path template of the locally stored tiles. The patterns {x} {y} {z} will be replaced at runtime
* For example, /storage/emulated/0/mytiles/{z}/{x}/{y}.png
*/
pathTemplate = { this . state . pathTemplate }
/**
* The size of provided local tiles (usually 256 or 512).
*/
tileSize = { 256 }
/ >
< / MapView > ;
Pour Android : LocalTile est toujours simplement une superposition sur les tuiles de la carte originale. Cela signifie que si l'appareil est en ligne, les vignettes sous-jacentes seront toujours téléchargées. Si le téléchargement/affichage des tuiles originales n'est pas souhaitable, définissez mapType sur « aucun ». Par exemple:
<MapView
mapType={Platform.OS == "android" ? "none" : "standard"}
>
Consultez le wiki OSM pour savoir comment télécharger des tuiles pour une utilisation hors ligne.
Placez les composants que vous souhaitez superposer MapView
sous la balise de fermeture MapView
. Positionnez absolument ces éléments.
render ( ) {
return (
< MapView
region = { this . state . region }
/ >
< OverlayComponent
style = { { position : "absolute" , bottom : 50 } }
/ >
) ;
}
Le <MapView provider="google" googleMapId="yourStyledMapId" />
Google Maps sur iOS et Android prend en charge le style via la plate-forme Google Cloud, les cartes stylisées sont publiées sous un googleMapId, en définissant simplement la propriété googleMapId sur MapView, vous pouvez l'utiliser carte stylisée plus d'informations ici : identifiant google map
Le composant <MapView />
et ses composants enfants comportent plusieurs événements auxquels vous pouvez vous abonner. Cet exemple en affiche certains dans un journal à titre de démonstration.
On peut modifier la position de la vue cartographique à l'aide de méthodes de référence et de composants, ou en transmettant un accessoire region
mis à jour. Les méthodes des composants permettront d'animer vers une position donnée comme le ferait l'API native.
Le composant <MapView />
peut être configuré pour fonctionner avec l'API Animated, en déclarant l'ensemble region
comme valeur animée. Cela permet d'animer le zoom et la position du MapView avec d'autres gestes, donnant une sensation agréable.
De plus, les vues Marker peuvent utiliser l’API animée pour améliorer l’effet.
Problème : étant donné qu'Android doit afficher ses vues de marqueur sous forme de bitmap, les API d'animation peuvent ne pas être compatibles avec les vues de marqueur. Je ne sais pas si cela peut encore être contourné ou non.
Les coordonnées des marqueurs peuvent également être animées, comme le montre cet exemple :
Jusqu'à présent, <Circle />
, <Polygon />
et <Polyline />
sont disponibles pour être transmis en tant qu'enfants au composant <MapView />
.
Les polylignes de dégradé peuvent être créées à l'aide de la propriété strokeColors
du composant <Polyline>
.
Les marqueurs par défaut seront rendus sauf si un marqueur personnalisé est spécifié. On peut éventuellement ajuster la couleur du marqueur par défaut en utilisant le prop pinColor
.
Les légendes vers les marqueurs peuvent être des vues de réaction complètement arbitraires, similaires aux marqueurs. En conséquence, vous pouvez interagir avec elles comme n’importe quelle autre vue.
De plus, vous pouvez revenir au comportement standard consistant à simplement avoir un titre/description via les accessoires title
et description
de <Marker />
.
Les vues de légende personnalisées peuvent représenter l’intégralité de la bulle d’aide ou simplement le contenu de la bulle par défaut du système.
Pour gérer la pression sur une sous-vue spécifique de la légende, utilisez <CalloutSubview />
avec onPress
. Voir l'exemple Callouts.js
.
Les marqueurs peuvent être personnalisés en utilisant simplement des images et spécifiés à l'aide de l'accessoire image
.
Les marqueurs peuvent être déplacés et émettent des événements de glissement continus pour mettre à jour d'autres interfaces utilisateur pendant les glissements.
Activez le mode simplifié sur Android avec la prop liteMode
. Idéal lorsque vous avez plusieurs cartes dans une vue ou un ScrollView.
Les Poi sont cliquables, vous pouvez capturer l'événement pour obtenir ses informations (généralement pour obtenir tous les détails de Google Place en utilisant le placeId).
MapView peut accepter une valeur AnimatedRegion
comme accessoire region
. Cela vous permet d'utiliser l'API animée pour contrôler le centre et le zoom de la carte.
import MapView , { AnimatedRegion , Animated } from 'react-native-maps' ;
getInitialState ( ) {
return {
region : new AnimatedRegion ( {
latitude : LATITUDE ,
longitude : LONGITUDE ,
latitudeDelta : LATITUDE_DELTA ,
longitudeDelta : LONGITUDE_DELTA ,
} ) ,
} ;
}
onRegionChange ( region ) {
this . state . region . setValue ( region ) ;
}
render ( ) {
return (
< Animated
region = { this . state . region }
onRegionChange = { this . onRegionChange }
/ >
) ;
}
Les marqueurs peuvent également accepter une valeur AnimatedRegion
comme coordonnée.
import MapView , { AnimatedRegion , MarkerAnimated } from 'react-native-maps' ;
getInitialState ( ) {
return {
coordinate : new AnimatedRegion ( {
latitude : LATITUDE ,
longitude : LONGITUDE ,
} ) ,
} ;
}
componentWillReceiveProps ( nextProps ) {
const duration = 500
if ( this . props . coordinate !== nextProps . coordinate ) {
if ( Platform . OS === 'android' ) {
if ( this . marker ) {
this . marker . animateMarkerToCoordinate (
nextProps . coordinate ,
duration
) ;
}
} else {
this . state . coordinate . timing ( {
... nextProps . coordinate ,
useNativeDriver : true , // defaults to false if not passed explicitly
duration
} ) . start ( ) ;
}
}
}
render ( ) {
return (
< MapView initialRegion = { ... } >
< MarkerAnimated
ref = { marker => { this . marker = marker } }
coordinate = { this . state . coordinate }
/ >
< / MapView >
) ;
}
import MapView , { Marker } from 'react-native-maps' ;
getInitialState ( ) {
return {
coordinate : {
latitude : LATITUDE ,
longitude : LONGITUDE ,
} ,
} ;
}
takeSnapshot ( ) {
// 'takeSnapshot' takes a config object with the
// following options
const snapshot = this . map . takeSnapshot ( {
width : 300 , // optional, when omitted the view-width is used
height : 300 , // optional, when omitted the view-height is used
region : { . . } , // iOS only, optional region to render
format : 'png' , // image formats: 'png', 'jpg' (default: 'png')
quality : 0.8 , // image quality: 0..1 (only relevant for jpg, default: 1)
result : 'file' // result types: 'file', 'base64' (default: 'file')
} ) ;
snapshot . then ( ( uri ) => {
this . setState ( { mapSnapshot : uri } ) ;
} ) ;
}
render ( ) {
return (
< View >
< MapView initialRegion = { ... } ref = { map => { this . map = map } } >
< Marker coordinate = { this . state . coordinate } / >
< / MapView >
< Image source = { { uri : this . state . mapSnapshot . uri } } / >
< TouchableOpacity onPress = { this . takeSnapshot } >
Take Snapshot
< / TouchableOpacity >
< / View >
) ;
}
Transmettez un tableau d’identifiants de marqueurs pour recentrer la carte.
Transmettez un tableau de coordonnées pour concentrer une région de la carte sur lesdites coordonnées.
const styles = StyleSheet . create ( {
map : {
... StyleSheet . absoluteFillObject ,
} ,
} ) ;
< MapView
style = { styles . map }
// other props
/ >
Mauvais:
< View >
< TextInput / >
< MapView / >
< / View >
Bien:
< View >
< MapView / >
< TextInput / >
< / View >
Les composants qui ne sont pas déclarés par cette bibliothèque (Ex : Marqueurs, Polyligne) ne doivent pas être des enfants du composant MapView en raison de la méthodologie de rendu unique de MapView. Placez vos composants/vues personnalisés en dehors du composant MapView et positionnez-les de manière absolue pour garantir qu'ils ne seront restitués qu'en cas de besoin. Exemple : Mauvais :
< View style = { StyleSheet . absoluteFillObject } >
< MapView style = { StyleSheet . absoluteFillObject } >
< View style = { { position : 'absolute' , top : 100 , left : 50 } } / >
< / MapView >
< / View >
Bien:
< View style = { StyleSheet . absoluteFillObject } >
< MapView style = { StyleSheet . absoluteFillObject } / >
< View style = { { position : 'absolute' , top : 100 , left : 50 } } / >
< / View >
Source : #1901
<MapView>
utilisant Apple Maps dans mapType: "standard"
plantera parfois lorsque vous mettrez l'application en arrière-plan ou passerez à une autre application. Il s'agit uniquement d'un problème dans XCode utilisant la validation de l'API Metal, et cela ne se produira pas en production. Pour éliminer ce problème même lors du débogage dans XCode, accédez à Edit Scheme... -> Run (Debug) -> Diagnostics
et décochez Metal -> API Validation
. (h/t @Simon-TechForm).
Source : #3957 (commentaire)
Si le changement d'état dans onRegionChangeComplete
est appelé à l'infini, ajoutez une condition pour limiter ces appels à se produire uniquement lorsque le changement de région a été effectué à la suite de l'action d'un utilisateur.
onRegionChangeComplete = { ( region , gesture ) => {
// This fix only works on Google Maps because isGesture is NOT available on Apple Maps
if ( ! gesture . isGesture ) {
return ;
}
// You can use
dispatch ( { type : "map_region" , payload : { mapRegion : region }