โต้ตอบส่วนประกอบ Native Map สำหรับ iOS + Android
โปรเจ็กต์นี้ได้รับการดูแลโดยคนกลุ่มเล็กๆ และความช่วยเหลือใดๆ เกี่ยวกับปัญหาและการดึงคำขอจะได้รับการชื่นชมเสมอ หากคุณสามารถและเต็มใจที่จะมีส่วนร่วม โปรดอ่านหลักเกณฑ์
ดูคำแนะนำในการติดตั้ง
ดูคำแนะนำในการตั้งค่าสำหรับโครงการตัวอย่างที่รวมไว้
react-native >= 0.74
react-native >= 0.64.3
<MapView />
คอมโพเนนต์ API
<Marker />
ส่วนประกอบ API
<Callout />
API คอมโพเนนต์
<Polygon />
คอมโพเนนต์ API
<Polyline />
คอมโพเนนต์ API
<Circle />
ส่วนประกอบ API
<Overlay />
คอมโพเนนต์ API
<Heatmap />
API ส่วนประกอบ
<Geojson />
ส่วนประกอบ API
import MapView from 'react-native-maps' ;
หรือ
var MapView = require ( 'react-native-maps' ) ;
ส่วนประกอบ MapView นี้ถูกสร้างขึ้นเพื่อให้สถานที่บนแผนที่ (เช่น เครื่องหมาย รูปหลายเหลี่ยม ฯลฯ) ได้รับการระบุเป็นลูกของ MapView เอง นี่เป็น API ที่ใช้งานง่ายและเหมือนตอบสนองสำหรับการควบคุมคุณสมบัติต่างๆ บนแผนที่อย่างเปิดเผย
< 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
ที่มีความละเอียดต่างๆ (ให้เรียกมันว่า custom_pin
) - สำหรับข้อมูลเพิ่มเติมไปที่ Android, iOS < Marker
coordinate = { { latitude : latitude , longitude : longitude } }
image = { { uri : 'custom_pin' } }
/ >
หมายเหตุ: คุณยังสามารถส่งข้อมูลไบนารี่ของรูปภาพเช่น image={require('custom_pin.png')}
ได้ แต่จะปรับขนาดได้ไม่ดีตามขนาดหน้าจอที่แตกต่างกัน
หมายเหตุ: สิ่งนี้มีผลกระทบต่อประสิทธิภาพ หากคุณต้องการวิธีแก้ปัญหาที่ง่ายกว่า ให้ใช้รูปภาพที่กำหนดเอง (ช่วยตัวเองให้ปวดหัว)
< 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 > ;
สำหรับ Android: เพิ่มบรรทัดต่อไปนี้ใน AndroidManifest.xml ของคุณ
< uses-permission android : name = " android.permission.INTERNET " />
สำหรับ IOS: กำหนดค่า App Transport Security ในแอปของคุณ
ไลบรารีนี้ทำงานร่วมกับ Fabric โดยใช้ New Renderer Interop Layer
มีข้อความเตือนว่าขั้นตอนเหล่านั้นไม่จำเป็น แต่เราไม่สามารถทำให้ตัวอย่างทำงานได้หากไม่มีพวกเขาจนถึงตอนนี้
เปิดไฟล์การกำหนดค่าของคุณ : ค้นหาไฟล์ react-native-config
ในไดเร็กทอรีโปรเจ็กต์ของคุณ
เพิ่มการกำหนดค่าต่อไปนี้ : รวมอาร์เรย์ unstable_reactLegacyComponentNames
สำหรับทั้งแพลตฟอร์ม Android และ iOS ดังที่แสดงด้านล่าง:
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' ,
] ,
} ,
} ,
} ;
ชำระเงินโครงการตัวอย่างเพื่อดูการดำเนินการ
สามารถจัดเก็บไทล์ไว้ในอุปกรณ์โดยใช้รูปแบบการเรียงไทล์ xyz และแสดงเป็นการซ้อนทับไทล์เช่นกัน สิ่งนี้มีประโยชน์โดยเฉพาะอย่างยิ่งสำหรับการใช้แผนที่ออฟไลน์เมื่อมีไทล์สำหรับภูมิภาคแผนที่ที่เลือกภายในที่เก็บข้อมูลของอุปกรณ์
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 > ;
สำหรับ Android: LocalTile ยังคงเป็นเพียงแค่การซ้อนทับบนชิ้นส่วนแผนที่ดั้งเดิม หมายความว่าหากอุปกรณ์ออนไลน์อยู่ ไทล์พื้นฐานจะยังคงดาวน์โหลดอยู่ หากไม่ต้องการการดาวน์โหลด/แสดงไทล์ดั้งเดิม ให้ตั้งค่า mapType เป็น 'none' ตัวอย่างเช่น:
<MapView
mapType={Platform.OS == "android" ? "none" : "standard"}
>
ดู OSM Wiki สำหรับวิธีดาวน์โหลดไทล์สำหรับการใช้งานออฟไลน์
วางส่วนประกอบที่คุณต้องการซ้อนทับ MapView
ใต้แท็กปิด MapView
วางตำแหน่งองค์ประกอบเหล่านี้อย่างแน่นอน
render ( ) {
return (
< MapView
region = { this . state . region }
/ >
< OverlayComponent
style = { { position : "absolute" , bottom : 50 } }
/ >
) ;
}
<MapView provider="google" googleMapId="yourStyledMapId" />
Google Maps บน iOS และ Android รองรับการจัดรูปแบบผ่านแพลตฟอร์ม Google Cloud แผนที่ที่มีการจัดรูปแบบจะได้รับการเผยแพร่ภายใต้ googleMapId โดยเพียงแค่ตั้งค่าคุณสมบัติ googleMapId เป็น MapView ที่คุณสามารถใช้ แผนที่ที่มีสไตล์ ข้อมูลเพิ่มเติมที่นี่: google map id
ส่วนประกอบ <MapView />
และส่วนประกอบย่อยมีหลายกิจกรรมที่คุณสามารถสมัครรับข้อมูลได้ ตัวอย่างนี้แสดงบางส่วนในบันทึกเป็นการสาธิต
คุณสามารถเปลี่ยนตำแหน่งของ mapview โดยใช้วิธีอ้างอิงและส่วนประกอบ หรือโดยการส่งผ่านเสาใน region
ที่อัปเดต วิธีการประกอบจะช่วยให้สามารถเคลื่อนไหวไปยังตำแหน่งที่กำหนดได้เช่นเดียวกับที่ API ดั้งเดิมสามารถทำได้
ส่วนประกอบ <MapView />
สามารถทำงานร่วมกับ Animated API ได้ โดยมีการประกาศพร็อพ region
ทั้งหมดเป็นค่าภาพเคลื่อนไหว ซึ่งช่วยให้สามารถเคลื่อนไหวการซูมและตำแหน่งของ MapView พร้อมกับท่าทางอื่นๆ ได้ ให้ความรู้สึกที่ดี
นอกจากนี้ มุมมอง Marker ยังสามารถใช้ API แบบเคลื่อนไหวเพื่อปรับปรุงเอฟเฟกต์ได้
ปัญหา: เนื่องจาก Android จำเป็นต้องแสดงมุมมองมาร์กเกอร์เป็นบิตแมป API ภาพเคลื่อนไหวจึงอาจเข้ากันไม่ได้กับมุมมองมาร์กเกอร์ ไม่แน่ใจว่าจะสามารถแก้ไขได้หรือยัง
พิกัดของเครื่องหมายยังสามารถเคลื่อนไหวได้ ดังที่แสดงในตัวอย่างนี้:
จนถึงตอนนี้ <Circle />
, <Polygon />
และ <Polyline />
พร้อมให้ส่งผ่านในฐานะลูกไปยังคอมโพเนนต์ <MapView />
เส้นหลายเส้นแบบไล่ระดับสีสามารถสร้างขึ้นได้โดยใช้เสา strokeColors
ของส่วนประกอบ <Polyline>
เครื่องหมายเริ่มต้นจะแสดงผลเว้นแต่จะระบุเครื่องหมายที่กำหนดเอง คุณสามารถเลือกปรับสีของเครื่องหมายเริ่มต้นได้โดยใช้ pinColor
prop
การเรียกไปยังเครื่องหมายอาจเป็นมุมมองตอบสนองตามอำเภอใจได้อย่างสมบูรณ์ คล้ายกับเครื่องหมาย เป็นผลให้พวกเขาสามารถโต้ตอบกับมุมมองอื่น ๆ ได้
นอกจากนี้ คุณสามารถกลับไปใช้พฤติกรรมมาตรฐานเพียงแค่มีชื่อ/คำอธิบายผ่านอุปกรณ์ประกอบ title
และ description
ของ <Marker />
มุมมองคำบรรยายที่กำหนดเองอาจเป็นฟองคำแนะนำเครื่องมือทั้งหมด หรือเพียงเนื้อหาภายในลูกโป่งเริ่มต้นของระบบ
หากต้องการจัดการการกดในมุมมองย่อยเฉพาะของคำบรรยายให้ใช้ <CalloutSubview />
กับ onPress
ดูตัวอย่าง Callouts.js
สามารถปรับแต่งมาร์กเกอร์ได้โดยใช้รูปภาพ และระบุโดยใช้อุปกรณ์ประกอบ image
เครื่องหมายสามารถลากได้ และปล่อยเหตุการณ์การลากอย่างต่อเนื่องเพื่ออัปเดต UI อื่นๆ ระหว่างการลาก
เปิดใช้งานโหมด Lite บน Android ด้วย liteMode
prop เหมาะอย่างยิ่งเมื่อมีหลายแผนที่ใน View หรือ ScrollView
ปอยสามารถคลิกได้ คุณสามารถติดตามกิจกรรมเพื่อรับข้อมูลได้ (โดยปกติจะรับรายละเอียดทั้งหมดจาก Google Place โดยใช้ placeId)
MapView สามารถรับค่า AnimatedRegion
เป็นค่าสนับสนุน region
ได้ ซึ่งจะทำให้คุณสามารถใช้ Animated API เพื่อควบคุมศูนย์กลางและการซูมของแผนที่ได้
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 }
/ >
) ;
}
เครื่องหมายยังสามารถยอมรับค่า AnimatedRegion
เป็นพิกัดได้
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 >
) ;
}
ส่งอาร์เรย์ของตัวระบุเครื่องหมายเพื่อให้แผนที่ปรับโฟกัสใหม่
ส่งผ่านอาร์เรย์ของพิกัดเพื่อเน้นพื้นที่แผนที่ไปที่พิกัดดังกล่าว
const styles = StyleSheet . create ( {
map : {
... StyleSheet . absoluteFillObject ,
} ,
} ) ;
< MapView
style = { styles . map }
// other props
/ >
แย่:
< View >
< TextInput / >
< MapView / >
< / View >
ดี:
< View >
< MapView / >
< TextInput / >
< / View >
ส่วนประกอบที่ไม่ได้ประกาศโดยไลบรารีนี้ (เช่น: Markers, Polyline) จะต้องไม่ใช่ลูกของส่วนประกอบ MapView เนื่องจากวิธีการเรนเดอร์ที่เป็นเอกลักษณ์ของ MapView มีส่วนประกอบ / มุมมองที่คุณกำหนดเองนอกส่วนประกอบ MapView และตำแหน่งที่แน่นอนเพื่อให้แน่ใจว่าจะแสดงผลซ้ำตามความจำเป็นเท่านั้น ตัวอย่าง: ไม่ดี:
< View style = { StyleSheet . absoluteFillObject } >
< MapView style = { StyleSheet . absoluteFillObject } >
< View style = { { position : 'absolute' , top : 100 , left : 50 } } / >
< / MapView >
< / View >
ดี:
< View style = { StyleSheet . absoluteFillObject } >
< MapView style = { StyleSheet . absoluteFillObject } / >
< View style = { { position : 'absolute' , top : 100 , left : 50 } } / >
< / View >
ที่มา: #1901
<MapView>
การใช้ Apple Maps ใน mapType: "standard"
บางครั้งอาจขัดข้องเมื่อคุณทำให้แอปอยู่เบื้องหลังหรือเปลี่ยนไปใช้แอปอื่น นี่เป็นเพียงปัญหาใน XCode ที่ใช้ Metal API Validation และจะไม่เกิดขึ้นในการใช้งานจริง เพื่อขจัดปัญหานี้แม้ในขณะที่ทำการดีบั๊กใน XCode ให้ไปที่ Edit Scheme... -> Run (Debug) -> Diagnostics
และยกเลิกการเลือก Metal -> API Validation
(h/t @Simon-TechForm)
ที่มา: #3957 (ความคิดเห็น)
หากการเปลี่ยนแปลงสถานะใน onRegionChangeComplete
ถูกเรียกอย่างไม่มีที่สิ้นสุด ให้เพิ่มเงื่อนไขเพื่อจำกัดการเรียกเหล่านี้ให้เกิดขึ้นเฉพาะเมื่อการเปลี่ยนแปลงขอบเขตเสร็จสิ้นอันเป็นผลมาจากการกระทำของผู้ใช้
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 }