Componentes React Native Map para iOS + Android
Este projeto está sendo mantido por um pequeno grupo de pessoas, e qualquer ajuda com problemas e solicitações pull será sempre apreciada. Se você puder e quiser contribuir, leia as diretrizes.
Consulte as instruções de instalação.
Consulte as instruções de configuração para o projeto de exemplo incluído.
react-native >= 0.74
.react-native >= 0.64.3
. API do componente <MapView />
<Marker />
API do componente
<Callout />
API do componente
<Polygon />
API do componente
<Polyline />
API do componente
<Circle />
API de componente
<Overlay />
API de componente
<Heatmap />
API do componente
<Geojson />
API do componente
import MapView from 'react-native-maps' ;
ou
var MapView = require ( 'react-native-maps' ) ;
Este componente MapView é construído para que os recursos do mapa (como marcadores, polígonos, etc.) sejam especificados como filhos do próprio MapView. Isso fornece uma API intuitiva e semelhante a uma reação para controlar declarativamente recursos no mapa.
< 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
com várias resoluções (vamos chamá-las de custom_pin
) - para obter mais informações, acesse Android, iOS < Marker
coordinate = { { latitude : latitude , longitude : longitude } }
image = { { uri : 'custom_pin' } }
/ >
Nota: Você também pode passar os dados binários da imagem como image={require('custom_pin.png')}
, mas isso não será bem dimensionado com os diferentes tamanhos de tela.
Nota: Isso tem implicações de desempenho, se você deseja uma solução mais simples, escolha uma imagem personalizada (evite dor de cabeça)
< 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 > ;
Para Android: adicione a seguinte linha em seu AndroidManifest.xml
< uses-permission android : name = " android.permission.INTERNET " />
Para IOS: configure o App Transport Security em seu aplicativo
Esta biblioteca funciona com Fabric usando a nova camada de interoperabilidade do renderizador
Há uma mensagem de aviso informando que essas etapas não são necessárias; mas não conseguimos fazer o exemplo funcionar sem eles até agora.
Abra seu arquivo de configuração : localize o arquivo react-native-config
no diretório do seu projeto.
Adicione a seguinte configuração : inclua o array unstable_reactLegacyComponentNames
para plataformas Android e iOS conforme mostrado abaixo:
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' ,
] ,
} ,
} ,
} ;
confira o projeto de exemplo para vê-lo em ação.
Os blocos podem ser armazenados localmente no dispositivo usando o esquema de blocos xyz e também exibidos como sobreposição de blocos. Isso é útil especialmente para uso de mapas off-line quando blocos estão disponíveis para a região selecionada do mapa no armazenamento do dispositivo.
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 > ;
Para Android: LocalTile ainda é apenas uma sobreposição sobre os blocos do mapa original. Isso significa que se o dispositivo estiver online, os blocos subjacentes ainda serão baixados. Se o download/exibição dos blocos originais não for desejável, defina mapType como 'none'. Por exemplo:
<MapView
mapType={Platform.OS == "android" ? "none" : "standard"}
>
Veja OSM Wiki para saber como baixar blocos para uso offline.
Coloque os componentes que você deseja sobrepor MapView
abaixo da tag de fechamento MapView
. Posicione absolutamente esses elementos.
render ( ) {
return (
< MapView
region = { this . state . region }
/ >
< OverlayComponent
style = { { position : "absolute" , bottom : 50 } }
/ >
) ;
}
O <MapView provider="google" googleMapId="yourStyledMapId" />
Google Maps no iOS e Android suporta estilização via google cloud platform, os mapas estilizados são publicados sob um googleMapId, simplesmente definindo a propriedade googleMapId para o MapView você pode usar isso mapa estilizado, mais informações aqui: google map id
O componente <MapView />
e seus componentes filhos possuem vários eventos nos quais você pode assinar. Este exemplo exibe alguns deles em um log como demonstração.
Pode-se alterar a posição do mapview usando refs e métodos de componentes, ou passando uma propriedade region
atualizada. Os métodos do componente permitirão animar uma determinada posição como a API nativa faria.
O componente <MapView />
pode funcionar com a API Animated, fazendo com que toda a propriedade region
seja declarada como um valor animado. Isso permite animar o zoom e a posição do MapView junto com outros gestos, dando uma sensação agradável.
Além disso, as visualizações do marcador podem usar a API animada para aprimorar o efeito.
Problema: como o Android precisa renderizar suas visualizações de marcadores como um bitmap, as APIs de animações podem não ser compatíveis com as visualizações de marcadores. Não tenho certeza se isso ainda pode ser contornado ou não.
As coordenadas dos marcadores também podem ser animadas, conforme mostrado neste exemplo:
Até agora, <Circle />
, <Polygon />
e <Polyline />
estão disponíveis para serem transmitidos como filhos do componente <MapView />
.
Polilinhas gradientes podem ser criadas usando a propriedade strokeColors
do componente <Polyline>
.
Os marcadores padrão serão renderizados, a menos que um marcador personalizado seja especificado. Opcionalmente, é possível ajustar a cor do marcador padrão usando a propriedade pinColor
.
As chamadas para marcadores podem ser visualizações de reação completamente arbitrárias, semelhantes aos marcadores. Como resultado, eles podem interagir como qualquer outra visualização.
Além disso, você pode voltar ao comportamento padrão de apenas ter um título/descrição por meio dos adereços <Marker />
de title
e description
.
As visualizações de texto explicativo personalizadas podem ser todo o balão de dica de ferramenta ou apenas o conteúdo dentro do balão padrão do sistema.
Para lidar com a pressão em uma subvisão específica do texto explicativo, use <CalloutSubview />
com onPress
. Consulte o exemplo Callouts.js
.
Os marcadores podem ser personalizados apenas usando imagens e especificados usando o suporte image
.
Os marcadores são arrastáveis e emitem eventos de arrastar contínuos para atualizar outra UI durante o arrastamento.
Ative o modo Lite no Android com a propriedade liteMode
. Ideal ao ter vários mapas em uma View ou ScrollView.
Poi são clicáveis, você pode capturar o evento para obter suas informações (geralmente para obter todos os detalhes do Google Place usando o placeId).
O MapView pode aceitar um valor AnimatedRegion
como sua propriedade region
. Isso permite que você utilize a API animada para controlar o centro e o zoom do mapa.
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 }
/ >
) ;
}
Os marcadores também podem aceitar um valor AnimatedRegion
como coordenada.
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 >
) ;
}
Passe uma série de identificadores de marcadores para que o mapa volte a focar.
Passe uma série de coordenadas para focar uma região do mapa nessas coordenadas.
const styles = StyleSheet . create ( {
map : {
... StyleSheet . absoluteFillObject ,
} ,
} ) ;
< MapView
style = { styles . map }
// other props
/ >
Ruim:
< View >
< TextInput / >
< MapView / >
< / View >
Bom:
< View >
< MapView / >
< TextInput / >
< / View >
Os componentes que não são declarados por esta biblioteca (Ex: Marcadores, Polilinha) não devem ser filhos do componente MapView devido à metodologia de renderização exclusiva do MapView. Coloque seus componentes/visualizações personalizados fora do componente MapView e posicione-os de forma absoluta para garantir que eles sejam renderizados novamente conforme necessário. Exemplo: Ruim:
< View style = { StyleSheet . absoluteFillObject } >
< MapView style = { StyleSheet . absoluteFillObject } >
< View style = { { position : 'absolute' , top : 100 , left : 50 } } / >
< / MapView >
< / View >
Bom:
< View style = { StyleSheet . absoluteFillObject } >
< MapView style = { StyleSheet . absoluteFillObject } / >
< View style = { { position : 'absolute' , top : 100 , left : 50 } } / >
< / View >
Fonte: #1901
<MapView>
usando Apple Maps em mapType: "standard"
às vezes falha quando você coloca o aplicativo em segundo plano ou muda para outro aplicativo. Este é um problema apenas no XCode usando Metal API Validation e não acontecerá na produção. Para eliminar este problema mesmo durante a depuração no XCode, vá em Edit Scheme... -> Run (Debug) -> Diagnostics
e desmarque Metal -> API Validation
. (h/t @Simon-TechForm).
Fonte: #3957 (comentário)
Se a alteração do estado em onRegionChangeComplete
for chamada infinitamente, adicione uma condição para limitar que essas chamadas ocorram somente quando a alteração da região for feita como resultado de uma ação do usuário.
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 }