在 Capacitor 中使用 Google 地图
npm install @capacitor/google-maps npx cap sync
要在任何平台上使用 Google Maps SDK,都需要使用关联到已启用计费的账户的 API 密钥。这些密钥可以从 Google Cloud Console 获取。Android、iOS 和 JavaScript 三个平台均需要此密钥。关于获取这些 API 密钥的更多信息,可在各平台的 Google Maps 文档 中找到。
Google Maps SDK 支持通过 enableCurrentLocation(bool) 显示用户的当前位置。为此,Apple 要求在 Info.plist 中指定隐私描述:
NSLocationWhenInUseUsageDescription (隐私 - 使用时位置访问说明)
请阅读 iOS 指南 中的 配置 Info.plist 部分,了解更多关于在 Xcode 中设置 iOS 权限的信息。
您的项目还需要在 tsconfig.json 中将 skipLibCheck 设置为 true。
主要的 Google Maps SDK 现在支持在 Apple Silicon Mac 的模拟器上运行,但请确保您安装了最新版本的 Google-Maps-iOS-Utils 。
如果您之前添加了获取未发布版本的特殊处理,现在可以通过从 ios/App/Podfile 中删除以下行来移除它:
pod 'Google-Maps-iOS-Utils', :git => 'https://github.com/googlemaps/google-maps-ios-utils.git', :commit => '637954e5bcb2a879c11a6f2cead153a6bad5339f'
然后从 ios/App/ 文件夹运行 pod update Google-Maps-iOS-Utils:
cd ios/App pod update Google-Maps-iOS-Utils
适用于 Android 的 Google Maps SDK 要求您将 API 密钥添加到项目中的 AndroidManifest.xml 文件。
< meta-data android: name = " com.google.android.geo.API_KEY " android: value = " YOUR_API_KEY_HERE " />
要使用某些定位功能,SDK 还要求将以下权限添加到您的 AndroidManifest.xml:
< uses-permission android: name = " android.permission.ACCESS_COARSE_LOCATION " /> < uses-permission android: name = " android.permission.ACCESS_FINE_LOCATION " />
此插件将使用以下项目变量(在您应用的 variables.gradle 文件中定义):
googleMapsPlayServicesVersion: com.google.android.gms:play-services-maps 的版本(默认:19.2.0)
googleMapsUtilsVersion: com.google.maps.android:android-maps-utils 的版本(默认:3.19.1)
googleMapsKtxVersion: com.google.maps.android:maps-ktx 的版本(默认:5.2.1)
googleMapsUtilsKtxVersion: com.google.maps.android:maps-utils-ktx 的版本(默认:5.2.1)
kotlinxCoroutinesVersion: org.jetbrains.kotlinx:kotlinx-coroutines-android 和 org.jetbrains.kotlinx:kotlinx-coroutines-core 的版本(默认:1.10.2)
androidxCoreKTXVersion: androidx.core:core-ktx 的版本(默认:1.17.0)
kotlin_version: org.jetbrains.kotlin:kotlin-stdlib 的版本(默认:2.2.20)
Google Maps Capacitor 插件附带了一个 Web 组件,必须在您的应用程序中使用它来渲染地图,因为它使我们能够在 iOS 上更有效地嵌入原生视图。插件将自动注册此 Web 组件以供您在应用中使用。
对于 Angular 用户,您会收到一个错误警告,提示 Angular 编译器不认识此 Web 组件。这可以通过修改声明组件的模块以允许自定义 Web 组件来解决。
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core' ; @ NgModule ( { schemas : [ CUSTOM_ELEMENTS_SCHEMA ] } )
在您的 HTML 中包含此组件并为其分配一个 ID,以便稍后可以轻松查询该元素引用。
< capacitor-google-map id = " map " > </ capacitor-google-map >
在 Android 上,地图是在整个 WebView 下方渲染的,并使用此组件在滚动事件期间管理其定位。这意味着作为开发者,您必须 确保 WebView 从各层一直到最底部都是透明的。在典型的 Ionic 应用中,这意味着需要在诸如 IonContent 和根 HTML 标签等元素上设置透明度,以确保可以看到地图。如果在 Android 上看不到地图,这应该是您首先检查的事项。
在 iOS 上,我们直接将地图渲染到 WebView 中,因此不需要相同的透明度效果。我们仍在研究 Android 的替代方法,并希望在未来的更新中更好地解决此问题。
Google Map 元素本身是无样式的,因此您应该对其进行样式设置以使其适应页面结构的布局。因为我们正在将视 图渲染到此插槽中,所以元素本身没有宽度或高度,请务必显式设置它们。
capacitor-google-map { display : inline-block ; width : 275 px ; height : 400 px ; }
接下来,我们应该创建地图引用。这是通过从 Capacitor 插件导入 GoogleMap 类并调用 create 方法,并传入所需的参数来完成的。
import { GoogleMap } from '@capacitor/google-maps' ; const apiKey = 'YOUR_API_KEY_HERE' ; const mapRef = document . getElementById ( 'map' ) ; const newMap = await GoogleMap . create ( { id : 'my-map' , element : mapRef , apiKey : apiKey , config : { center : { lat : 33.6 , lng : - 117.9 , } , zoom : 8 , } , } ) ;
此时,您的地图应该在应用程序中创建完成。使用返回的地图引用,您可以通过多种方式轻松地与地图交互,这里展示了其中一些方式。
const newMap = await GoogleMap . create ( { ... } ) ; const markerId = await newMap . addMarker ( { coordinate : { lat : 33.6 , lng : - 117.9 } } ) ; await newMap . setCamera ( { coordinate : { lat : 33.6 , lng : - 117.9 } } ) ; await newMap . enableClustering ( ) ; await newMap . setOnMarkerClickListener ( ( event ) => { ... } ) ; await newMap . destroy ( ) ;
import { GoogleMap } from '@capacitor/google-maps' ; @ Component ( { template : ` <capacitor-google-map #map></capacitor-google-map> <button (click)="createMap()">创建地图</button> ` , styles : [ ` capacitor-google-map { display: inline-block; width: 275px; height: 400px; } ` , ] , } ) export class MyMap { @ ViewChild ( 'map' ) mapRef : ElementRef < HTMLElement > ; newMap : GoogleMap ; async createMap ( ) { this . newMap = await GoogleMap . create ( { id : 'my-cool-map' , element : this . mapRef . nativeElement , apiKey : environment . apiKey , config : { center : { lat : 33.6 , lng : - 117.9 , } , zoom : 8 , } , } ) ; } }
import { GoogleMap } from '@capacitor/google-maps' ; import { useRef } from 'react' ; const MyMap : React . FC = ( ) => { const mapRef = useRef < HTMLElement > (); let newMap: GoogleMap; async function createMap() { if ( ! mapRef . current ) return ; newMap = await GoogleMap . create ( { id : 'my-cool-map' , element : mapRef . current , apiKey : process . env . REACT_APP_YOUR_API_KEY_HERE , config : { center : { lat : 33.6 , lng : - 117.9 } , zoom : 8 } } ) } return ( < div className = " component-wrapper " > < capacitor-google-map ref = { mapRef } style = { { display : 'inline-block' , width : 275 , height : 400 } } > </ capacitor-google-map > < button onClick = { createMap } > 创建地图 </ button > </ div > ) } export default MyMap;
你可能需要为React中的自定义元素创建一个*.d.ts文件:
declare module "react" { namespace JSX { interface IntrinsicElements { "capacitor-google-map" : React . DetailedHTMLProps < React . HTMLAttributes < HTMLElement > , HTMLElement > ; } } } export { } ;
<script lang="ts" setup> import { ref, shallowRef, useTemplateRef } from 'vue'; import { GoogleMap } from '@capacitor/google-maps'; const mapRef = useTemplateRef<HTMLElement>('mapRef'); const newMap = shallowRef<GoogleMap>(); async function createMap() { if (!mapRef.value) return; newMap.value = await GoogleMap.create({ id: 'my-cool-map', element: mapRef.value, apiKey: import.meta.env.VITE_YOUR_API_KEY_HERE, config: { center: { lat: 33.6, lng: -117.9, }, zoom: 8, }, }); } </script> <template> <capacitor-google-map ref="mapRef" style="display: inline-block; width: 275px; height: 400px"></capacitor-google-map> <button @click="createMap()">创建地图</button> </template>
请确保您需要启用识别原生自定义元素 功能,例如:
Vue ( { template : { compilerOptions : { isCustomElement : ( tag ) => tag . startsWith ( 'capacitor-' ) } , } , } ) ,
< capacitor-google-map id = " map " > </ capacitor-google-map > < button onclick = " createMap ( ) " > 创建地图 </ button > < style > capacitor-google-map { display : inline-block ; width : 275 px ; height : 400 px ; } </ style > < script > import { GoogleMap } from '@capacitor/google-maps' ; const createMap = async ( ) => { const mapRef = document . getElementById ( 'map' ) ; const newMap = await GoogleMap . create ( { id : 'my-map' , element : mapRef , apiKey : 'YOUR_API_KEY_HERE' , config : { center : { lat : 33.6 , lng : - 117.9 , } , zoom : 8 , } , } ) ; } ; </ script >
create ( options : CreateMapArgs , callback ? : MapListenerCallback < MapReadyCallbackData > | undefined ) => Promise < GoogleMap >
返回值: Promise<GoogleMap>
enableTouch ( ) => Promise < void >
disableTouch ( ) => Promise < void >
enableClustering ( minClusterSize ? : number | undefined ) => Promise < void >
参数 类型 描述 minClusterSizenumber可聚集在一起的最小标记数量。默认为 4 个标记。
disableClustering ( ) => Promise < void >
addTileOverlay ( tileOverlay : TileOverlay ) => Promise < { id : string ; } >
返回值: Promise<{ id: string; }>
removeTileOverlay ( id : string ) => Promise < void >
addMarker ( marker : Marker ) => Promise < string >
返回值: Promise<string>
addMarkers ( markers : Marker [ ] ) => Promise < string [ ] >
返回值: Promise<string[]>
removeMarker ( id : string ) => Promise < void >
removeMarkers ( ids : string [ ] ) => Promise < void >
addPolygons ( polygons : Polygon [ ] ) => Promise < string [ ] >
返回值: Promise<string[]>
removePolygons ( ids : string [ ] ) => Promise < void >
addCircles ( circles : Circle [ ] ) => Promise < string [ ] >
返回值: Promise<string[]>
removeCircles ( ids : string [ ] ) => Promise < void >
addPolylines ( polylines : Polyline [ ] ) => Promise < string [ ] >
返回值: Promise<string[]>
removePolylines ( ids : string [ ] ) => Promise < void >
destroy ( ) => Promise < void >
setCamera ( config : CameraConfig ) => Promise < void >
getMapType ( ) => Promise < MapType >
获取当前地图类型
返回值:
Promise<MapType >
setMapType ( mapType : MapType ) => Promise < void >
enableIndoorMaps ( enabled : boolean ) => Promise < void >
enableTrafficLayer ( enabled : boolean ) => Promise < void >
enableAccessibilityElements ( enabled : boolean ) => Promise < void >
enableCurrentLocation ( enabled : boolean ) => Promise < void >
setPadding ( padding : MapPadding ) => Promise < void >
getMapBounds ( ) => Promise < LatLngBounds >
获取地图当前视口的经纬度边界。
返回值: Promise<LatLngBounds>
fitBounds ( bounds : LatLngBounds , padding ? : number | undefined ) => Promise < void >
设置地图视口以包含给定的边界。
参数 类型 描述 boundsLatLngBounds要适应视口的边界。 paddingnumber可选的内边距(以像素为单位)。边界将适应在移除内边距后剩余的地图部分。
setOnBoundsChangedListener ( callback ? : MapListenerCallback < CameraIdleCallbackData > | undefined ) => Promise < void >
setOnCameraIdleListener ( callback ? : MapListenerCallback < CameraIdleCallbackData > | undefined ) => Promise < void >
setOnCameraMoveStartedListener ( callback ? : MapListenerCallback < CameraMoveStartedCallbackData > | undefined ) => Promise < void >
setOnClusterClickListener ( callback ? : MapListenerCallback < ClusterClickCallbackData > | undefined ) => Promise < void >
setOnClusterInfoWindowClickListener ( callback ? : MapListenerCallback < ClusterClickCallbackData > | undefined ) => Promise < void >
setOnInfoWindowClickListener ( callback ? : MapListenerCallback < MarkerClickCallbackData > | undefined ) => Promise < void >
setOnMapClickListener ( callback ? : MapListenerCallback < MapClickCallbackData > | undefined ) => Promise < void >
setOnMarkerClickListener ( callback ? : MapListenerCallback < MarkerClickCallbackData > | undefined ) => Promise < void >
setOnPolygonClickListener ( callback ? : MapListenerCallback < PolygonClickCallbackData > | undefined ) => Promise < void >
setOnCircleClickListener ( callback ? : MapListenerCallback < CircleClickCallbackData > | undefined ) => Promise < void >
setOnPolylineClickListener ( callback ? : MapListenerCallback < PolylineCallbackData > | undefined ) => Promise < void >
setOnMarkerDragStartListener ( callback ? : MapListenerCallback < MarkerClickCallbackData > | undefined ) => Promise < void >
setOnMarkerDragListener ( callback ? : MapListenerCallback < MarkerClickCallbackData > | undefined ) => Promise < void >
setOnMarkerDragEndListener ( callback ? : MapListenerCallback < MarkerClickCallbackData > | undefined ) => Promise < void >
setOnMyLocationButtonClickListener ( callback ? : MapListenerCallback < MyLocationButtonClickCallbackData > | undefined ) => Promise < void >
setOnMyLocationClickListener ( callback ? : MapListenerCallback < MapClickCallbackData > | undefined ) => Promise < void >