diff --git a/google-maps/README.md b/google-maps/README.md index 58997960d..902c7c0e0 100644 --- a/google-maps/README.md +++ b/google-maps/README.md @@ -292,13 +292,13 @@ export default MyMap; ### create(...) ```typescript -create(options: CreateMapArgs, callback?: MapListenerCallback | undefined) => Promise +create(options: CreateMapArgs, callback?: MapListenerCallback | undefined) => Promise ``` -| Param | Type | -| -------------- | ------------------------------------------------------------------- | -| **`options`** | CreateMapArgs | -| **`callback`** | MapListenerCallback | +| Param | Type | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| **`options`** | CreateMapArgs | +| **`callback`** | MapListenerCallback<MapReadyCallbackData> | **Returns:** Promise<GoogleMap> @@ -482,12 +482,12 @@ setPadding(padding: MapPadding) => Promise ### setOnCameraIdleListener(...) ```typescript -setOnCameraIdleListener(callback?: MapListenerCallback | undefined) => Promise +setOnCameraIdleListener(callback?: MapListenerCallback | undefined) => Promise ``` -| Param | Type | -| -------------- | ------------------------------------------------------------------- | -| **`callback`** | MapListenerCallback | +| Param | Type | +| -------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| **`callback`** | MapListenerCallback<CameraIdleCallbackData> | -------------------- @@ -495,12 +495,12 @@ setOnCameraIdleListener(callback?: MapListenerCallback | undefined) => Promise Promise +setOnCameraMoveStartedListener(callback?: MapListenerCallback | undefined) => Promise ``` -| Param | Type | -| -------------- | ------------------------------------------------------------------- | -| **`callback`** | MapListenerCallback | +| Param | Type | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`callback`** | MapListenerCallback<CameraMoveStartedCallbackData> | -------------------- @@ -508,12 +508,12 @@ setOnCameraMoveStartedListener(callback?: MapListenerCallback | undefined) => Pr ### setOnClusterClickListener(...) ```typescript -setOnClusterClickListener(callback?: MapListenerCallback | undefined) => Promise +setOnClusterClickListener(callback?: MapListenerCallback | undefined) => Promise ``` -| Param | Type | -| -------------- | ------------------------------------------------------------------- | -| **`callback`** | MapListenerCallback | +| Param | Type | +| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| **`callback`** | MapListenerCallback<ClusterClickCallbackData> | -------------------- @@ -521,12 +521,12 @@ setOnClusterClickListener(callback?: MapListenerCallback | undefined) => Promise ### setOnClusterInfoWindowClickListener(...) ```typescript -setOnClusterInfoWindowClickListener(callback?: MapListenerCallback | undefined) => Promise +setOnClusterInfoWindowClickListener(callback?: MapListenerCallback | undefined) => Promise ``` -| Param | Type | -| -------------- | ------------------------------------------------------------------- | -| **`callback`** | MapListenerCallback | +| Param | Type | +| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| **`callback`** | MapListenerCallback<ClusterClickCallbackData> | -------------------- @@ -534,12 +534,12 @@ setOnClusterInfoWindowClickListener(callback?: MapListenerCallback | undefined) ### setOnInfoWindowClickListener(...) ```typescript -setOnInfoWindowClickListener(callback?: MapListenerCallback | undefined) => Promise +setOnInfoWindowClickListener(callback?: MapListenerCallback | undefined) => Promise ``` -| Param | Type | -| -------------- | ------------------------------------------------------------------- | -| **`callback`** | MapListenerCallback | +| Param | Type | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| **`callback`** | MapListenerCallback<MarkerClickCallbackData> | -------------------- @@ -547,12 +547,12 @@ setOnInfoWindowClickListener(callback?: MapListenerCallback | undefined) => Prom ### setOnMapClickListener(...) ```typescript -setOnMapClickListener(callback?: MapListenerCallback | undefined) => Promise +setOnMapClickListener(callback?: MapListenerCallback | undefined) => Promise ``` -| Param | Type | -| -------------- | ------------------------------------------------------------------- | -| **`callback`** | MapListenerCallback | +| Param | Type | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| **`callback`** | MapListenerCallback<MapClickCallbackData> | -------------------- @@ -560,12 +560,12 @@ setOnMapClickListener(callback?: MapListenerCallback | undefined) => Promise Promise +setOnMarkerClickListener(callback?: MapListenerCallback | undefined) => Promise ``` -| Param | Type | -| -------------- | ------------------------------------------------------------------- | -| **`callback`** | MapListenerCallback | +| Param | Type | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| **`callback`** | MapListenerCallback<MarkerClickCallbackData> | -------------------- @@ -573,12 +573,12 @@ setOnMarkerClickListener(callback?: MapListenerCallback | undefined) => Promise< ### setOnMyLocationButtonClickListener(...) ```typescript -setOnMyLocationButtonClickListener(callback?: MapListenerCallback | undefined) => Promise +setOnMyLocationButtonClickListener(callback?: MapListenerCallback | undefined) => Promise ``` -| Param | Type | -| -------------- | ------------------------------------------------------------------- | -| **`callback`** | MapListenerCallback | +| Param | Type | +| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`callback`** | MapListenerCallback<MyLocationButtonClickCallbackData> | -------------------- @@ -586,12 +586,12 @@ setOnMyLocationButtonClickListener(callback?: MapListenerCallback | undefined) = ### setOnMyLocationClickListener(...) ```typescript -setOnMyLocationClickListener(callback?: MapListenerCallback | undefined) => Promise +setOnMyLocationClickListener(callback?: MapListenerCallback | undefined) => Promise ``` -| Param | Type | -| -------------- | ------------------------------------------------------------------- | -| **`callback`** | MapListenerCallback | +| Param | Type | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| **`callback`** | MapListenerCallback<MapClickCallbackData> | -------------------- @@ -601,27 +601,29 @@ setOnMyLocationClickListener(callback?: MapListenerCallback | undefined) => Prom #### CreateMapArgs -| Prop | Type | -| ---------------------- | ----------------------------------------------------------- | -| **`id`** | string | -| **`apiKey`** | string | -| **`config`** | GoogleMapConfig | -| **`element`** | HTMLElement | -| **`forceCreate`** | boolean | -| **`devicePixelRatio`** | number | +An interface containing the options used when creating a map. + +| Prop | Type | Description | Default | +| ----------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------ | +| **`id`** | string | A unique identifier for the map instance. | | +| **`apiKey`** | string | The Google Maps SDK API Key. | | +| **`config`** | GoogleMapConfig | The initial configuration settings for the map. | | +| **`element`** | HTMLElement | The DOM element that the Google Map View will be mounted on which determines size and positioning. | | +| **`forceCreate`** | boolean | Destroy and re-create the map instance if a map with the supplied id already exists | false | #### GoogleMapConfig -| Prop | Type | Description | Default | -| --------------------- | ----------------------------------------- | -------------------------------------------------------------- | ------------------ | -| **`width`** | number | Override width for native map | | -| **`height`** | number | Override height for native map | | -| **`x`** | number | Override absolute x coordinate position for native map | | -| **`y`** | number | Override absolute y coordinate position for native map | | -| **`center`** | LatLng | Default location on the Earth towards which the camera points. | | -| **`zoom`** | number | Sets the zoom of the map. | | -| **`androidLiteMode`** | boolean | Enables image-based lite mode on Android. | false | +| Prop | Type | Description | Default | +| ---------------------- | ----------------------------------------- | -------------------------------------------------------------- | ------------------ | +| **`width`** | number | Override width for native map. | | +| **`height`** | number | Override height for native map. | | +| **`x`** | number | Override absolute x coordinate position for native map. | | +| **`y`** | number | Override absolute y coordinate position for native map. | | +| **`center`** | LatLng | Default location on the Earth towards which the camera points. | | +| **`zoom`** | number | Sets the zoom of the map. | | +| **`androidLiteMode`** | boolean | Enables image-based lite mode on Android. | false | +| **`devicePixelRatio`** | number | Override pixel ratio for native map. | | #### LatLng @@ -634,6 +636,13 @@ An interface representing a pair of latitude and longitude coordinates. | **`lng`** | number | Coordinate longitude, in degrees. This value is in the range [-180, 180]. | +#### MapReadyCallbackData + +| Prop | Type | +| ----------- | ------------------- | +| **`mapId`** | string | + + #### Marker A marker is an icon placed at a particular point on the map's surface. @@ -675,12 +684,79 @@ Controls for setting padding on the 'visible' region of the view. | **`bottom`** | number | +#### CameraIdleCallbackData + +| Prop | Type | +| --------------- | ------------------- | +| **`mapId`** | string | +| **`bearing`** | number | +| **`latitude`** | number | +| **`longitude`** | number | +| **`tilt`** | number | +| **`zoom`** | number | + + +#### CameraMoveStartedCallbackData + +| Prop | Type | +| --------------- | -------------------- | +| **`mapId`** | string | +| **`isGesture`** | boolean | + + +#### ClusterClickCallbackData + +| Prop | Type | +| --------------- | --------------------------------- | +| **`mapId`** | string | +| **`latitude`** | number | +| **`longitude`** | number | +| **`size`** | number | +| **`items`** | MarkerCallbackData[] | + + +#### MarkerCallbackData + +| Prop | Type | +| --------------- | ------------------- | +| **`markerId`** | string | +| **`latitude`** | number | +| **`longitude`** | number | +| **`title`** | string | +| **`snippet`** | string | + + +#### MarkerClickCallbackData + +| Prop | Type | +| ----------- | ------------------- | +| **`mapId`** | string | + + +#### MapClickCallbackData + +| Prop | Type | +| --------------- | ------------------- | +| **`mapId`** | string | +| **`latitude`** | number | +| **`longitude`** | number | + + +#### MyLocationButtonClickCallbackData + +| Prop | Type | +| ----------- | ------------------- | +| **`mapId`** | string | + + ### Type Aliases #### MapListenerCallback -(data: any): void +The callback function to be called when map events are emitted. + +(data: T): void ### Enums diff --git a/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/CapacitorGoogleMap.kt b/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/CapacitorGoogleMap.kt index 58ad86252..9debbb812 100644 --- a/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/CapacitorGoogleMap.kt +++ b/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/CapacitorGoogleMap.kt @@ -15,8 +15,8 @@ import com.getcapacitor.JSArray import com.getcapacitor.JSObject import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap -import com.google.android.gms.maps.MapView import com.google.android.gms.maps.GoogleMap.* +import com.google.android.gms.maps.MapView import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng @@ -67,8 +67,6 @@ class CapacitorGoogleMap( isReadyChannel.receive() - this@CapacitorGoogleMap.mapView = mapView - render() } @@ -100,7 +98,7 @@ class CapacitorGoogleMap( ((bridge.webView.parent) as ViewGroup).addView(mapViewParent) bridge.webView.bringToFront() - bridge.webView.setBackgroundColor(Color.TRANSPARENT); + bridge.webView.setBackgroundColor(Color.TRANSPARENT) } } } @@ -134,7 +132,10 @@ class CapacitorGoogleMap( fun bringToFront() { CoroutineScope(Dispatchers.Main).launch { - val mapViewParent = ((delegate.bridge.webView.parent) as ViewGroup).findViewWithTag(this@CapacitorGoogleMap.id) + val mapViewParent = + ((delegate.bridge.webView.parent) as ViewGroup).findViewWithTag( + this@CapacitorGoogleMap.id + ) mapViewParent.bringToFront() } } @@ -394,17 +395,17 @@ class CapacitorGoogleMap( CoroutineScope(Dispatchers.Main).launch { val mapTypeInt: Int = when (mapType) { - "Normal" -> GoogleMap.MAP_TYPE_NORMAL - "Hybrid" -> GoogleMap.MAP_TYPE_HYBRID - "Satellite" -> GoogleMap.MAP_TYPE_SATELLITE - "Terrain" -> GoogleMap.MAP_TYPE_TERRAIN - "None" -> GoogleMap.MAP_TYPE_NONE + "Normal" -> MAP_TYPE_NORMAL + "Hybrid" -> MAP_TYPE_HYBRID + "Satellite" -> MAP_TYPE_SATELLITE + "Terrain" -> MAP_TYPE_TERRAIN + "None" -> MAP_TYPE_NONE else -> { Log.w( "CapacitorGoogleMaps", "unknown mapView type '$mapType' Defaulting to normal." ) - GoogleMap.MAP_TYPE_NORMAL + MAP_TYPE_NORMAL } } @@ -467,10 +468,10 @@ class CapacitorGoogleMap( fun getMapBounds(): Rect { return Rect( - getScaledPixels(delegate.bridge, config.x).toInt(), - getScaledPixels(delegate.bridge, config.y).toInt(), - getScaledPixels(delegate.bridge, config.x + config.width).toInt(), - getScaledPixels(delegate.bridge, config.y + config.height).toInt() + getScaledPixels(delegate.bridge, config.x), + getScaledPixels(delegate.bridge, config.y), + getScaledPixels(delegate.bridge, config.x + config.width), + getScaledPixels(delegate.bridge, config.y + config.height) ) } @@ -490,10 +491,10 @@ class CapacitorGoogleMap( private fun getScaledRect(bridge: Bridge, rectF: RectF): RectF { return RectF( - getScaledPixelsF(bridge, rectF.left), - getScaledPixelsF(bridge, rectF.top), - getScaledPixelsF(bridge, rectF.right), - getScaledPixelsF(bridge, rectF.bottom) + getScaledPixelsF(bridge, rectF.left), + getScaledPixelsF(bridge, rectF.top), + getScaledPixelsF(bridge, rectF.right), + getScaledPixelsF(bridge, rectF.bottom) ) } diff --git a/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/CapacitorGoogleMapsPlugin.kt b/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/CapacitorGoogleMapsPlugin.kt index 194593553..379a8a598 100644 --- a/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/CapacitorGoogleMapsPlugin.kt +++ b/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/CapacitorGoogleMapsPlugin.kt @@ -2,7 +2,6 @@ package com.capacitorjs.plugins.googlemaps import android.Manifest import android.annotation.SuppressLint -import android.graphics.Rect import android.graphics.RectF import android.util.Log import android.view.MotionEvent @@ -15,20 +14,19 @@ import org.json.JSONArray import org.json.JSONObject @CapacitorPlugin( - name = "CapacitorGoogleMaps", - permissions = [ - Permission( - strings = [Manifest.permission.ACCESS_FINE_LOCATION], - alias = CapacitorGoogleMapsPlugin.LOCATION - ), - ], + name = "CapacitorGoogleMaps", + permissions = + [ + Permission( + strings = [Manifest.permission.ACCESS_FINE_LOCATION], + alias = CapacitorGoogleMapsPlugin.LOCATION + ), + ], ) class CapacitorGoogleMapsPlugin : Plugin() { private var maps: HashMap = HashMap() private var cachedTouchEvents: HashMap> = HashMap() private val tag: String = "CAP-GOOGLE-MAPS" - private var devicePixelRatio = 1.00f - companion object { const val LOCATION = "location" @@ -38,46 +36,48 @@ class CapacitorGoogleMapsPlugin : Plugin() { override fun load() { super.load() - this.bridge.webView.setOnTouchListener(object : View.OnTouchListener { - override fun onTouch(v: View?, event: MotionEvent?): Boolean { - if (event != null) { - if (event.source == -1) { - return v?.onTouchEvent(event) ?: true - } + this.bridge.webView.setOnTouchListener( + object : View.OnTouchListener { + override fun onTouch(v: View?, event: MotionEvent?): Boolean { + if (event != null) { + if (event.source == -1) { + return v?.onTouchEvent(event) ?: true + } - val touchX = event.x - val touchY = event.y + val touchX = event.x + val touchY = event.y - for ((id, map) in maps) { - val mapRect = map.getMapBounds() - if (mapRect.contains(touchX.toInt(), touchY.toInt())) { - if (event.action == MotionEvent.ACTION_DOWN) { - if (cachedTouchEvents[id] == null) { - cachedTouchEvents[id] = mutableListOf() - } + for ((id, map) in maps) { + val mapRect = map.getMapBounds() + if (mapRect.contains(touchX.toInt(), touchY.toInt())) { + if (event.action == MotionEvent.ACTION_DOWN) { + if (cachedTouchEvents[id] == null) { + cachedTouchEvents[id] = mutableListOf() + } - cachedTouchEvents[id]?.clear() - } + cachedTouchEvents[id]?.clear() + } - val motionEvent = MotionEvent.obtain(event) - cachedTouchEvents[id]?.add(motionEvent) + val motionEvent = MotionEvent.obtain(event) + cachedTouchEvents[id]?.add(motionEvent) - val payload = JSObject() - payload.put("x", touchX / devicePixelRatio) - payload.put("y", touchY / devicePixelRatio) - payload.put("mapId", map.id) + val payload = JSObject() + payload.put("x", touchX / map.config.devicePixelRatio) + payload.put("y", touchY / map.config.devicePixelRatio) + payload.put("mapId", map.id) - notifyListeners("isMapInFocus", payload) - return true + notifyListeners("isMapInFocus", payload) + return true + } + } } + + return v?.onTouchEvent(event) ?: true } } - - return v?.onTouchEvent(event) ?: true - } - }) + ) } - + override fun handleOnStart() { super.handleOnStart() maps.forEach { it.value.onStart() } @@ -108,14 +108,13 @@ class CapacitorGoogleMapsPlugin : Plugin() { try { val id = call.getString("id") - this.devicePixelRatio = call.getFloat("devicePixelRatio", 1.00f)!! - if (null == id || id.isEmpty()) { throw InvalidMapIdError() } - val configObject = call.getObject("config") - ?: throw InvalidArgumentsError("config object is missing") + val configObject = + call.getObject("config") + ?: throw InvalidArgumentsError("config object is missing") val forceCreate = call.getBoolean("forceCreate", false)!! @@ -240,7 +239,7 @@ class CapacitorGoogleMapsPlugin : Plugin() { val map = maps[id] map ?: throw MapNotFoundError() - map.enableClustering() { err -> + map.enableClustering { err -> if (err != null) { throw err } @@ -263,7 +262,7 @@ class CapacitorGoogleMapsPlugin : Plugin() { val map = maps[id] map ?: throw MapNotFoundError() - map.disableClustering() { err -> + map.disableClustering { err -> if (err != null) { throw err } @@ -349,8 +348,9 @@ class CapacitorGoogleMapsPlugin : Plugin() { val map = maps[id] map ?: throw MapNotFoundError() - val cameraConfigObject = call.getObject("config") - ?: throw InvalidArgumentsError("config object is missing") + val cameraConfigObject = + call.getObject("config") + ?: throw InvalidArgumentsError("config object is missing") val config = GoogleMapCameraConfig(cameraConfigObject) @@ -377,8 +377,8 @@ class CapacitorGoogleMapsPlugin : Plugin() { val map = maps[id] map ?: throw MapNotFoundError() - val mapType = call.getString("mapType") - ?: throw InvalidArgumentsError("mapType is missing") + val mapType = + call.getString("mapType") ?: throw InvalidArgumentsError("mapType is missing") map.setMapType(mapType) { err -> if (err != null) { @@ -403,8 +403,8 @@ class CapacitorGoogleMapsPlugin : Plugin() { val map = maps[id] map ?: throw MapNotFoundError() - val enabled = call.getBoolean("enabled") - ?: throw InvalidArgumentsError("enabled is missing") + val enabled = + call.getBoolean("enabled") ?: throw InvalidArgumentsError("enabled is missing") map.enableIndoorMaps(enabled) { err -> if (err != null) { @@ -429,8 +429,8 @@ class CapacitorGoogleMapsPlugin : Plugin() { val map = maps[id] map ?: throw MapNotFoundError() - val enabled = call.getBoolean("enabled") - ?: throw InvalidArgumentsError("enabled is missing") + val enabled = + call.getBoolean("enabled") ?: throw InvalidArgumentsError("enabled is missing") map.enableTrafficLayer(enabled) { err -> if (err != null) { @@ -448,7 +448,7 @@ class CapacitorGoogleMapsPlugin : Plugin() { @PluginMethod fun enableCurrentLocation(call: PluginCall) { - if (getPermissionState(CapacitorGoogleMapsPlugin.LOCATION) != PermissionState.GRANTED) { + if (getPermissionState(LOCATION) != PermissionState.GRANTED) { requestAllPermissions(call, "enableCurrentLocationCallback") } else { internalEnableCurrentLocation(call) @@ -457,7 +457,7 @@ class CapacitorGoogleMapsPlugin : Plugin() { @PermissionCallback fun enableCurrentLocationCallback(call: PluginCall) { - if (getPermissionState(CapacitorGoogleMapsPlugin.LOCATION) == PermissionState.GRANTED) { + if (getPermissionState(LOCATION) == PermissionState.GRANTED) { internalEnableCurrentLocation(call) } else { call.reject("location permission was denied") @@ -473,8 +473,8 @@ class CapacitorGoogleMapsPlugin : Plugin() { val map = maps[id] map ?: throw MapNotFoundError() - val paddingObj = call.getObject("padding") - ?: throw InvalidArgumentsError("padding is missing") + val paddingObj = + call.getObject("padding") ?: throw InvalidArgumentsError("padding is missing") val padding = GoogleMapPadding(paddingObj) @@ -506,7 +506,9 @@ class CapacitorGoogleMapsPlugin : Plugin() { val map = maps[id] map ?: throw MapNotFoundError() - val boundsObj = call.getObject("mapBounds") ?: throw InvalidArgumentsError("mapBounds object is missing") + val boundsObj = + call.getObject("mapBounds") + ?: throw InvalidArgumentsError("mapBounds object is missing") val bounds = boundsObjectToRect(boundsObj) @@ -533,7 +535,7 @@ class CapacitorGoogleMapsPlugin : Plugin() { val events = cachedTouchEvents[id] if (events != null) { - for(event in events) { + for (event in events) { if (focus) { map.dispatchTouchEvent(event) } else { @@ -561,8 +563,8 @@ class CapacitorGoogleMapsPlugin : Plugin() { val map = maps[id] map ?: throw MapNotFoundError() - val enabled = call.getBoolean("enabled") - ?: throw InvalidArgumentsError("enabled is missing") + val enabled = + call.getBoolean("enabled") ?: throw InvalidArgumentsError("enabled is missing") map.enableCurrentLocation(enabled) { err -> if (err != null) { diff --git a/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/GoogleMapConfig.kt b/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/GoogleMapConfig.kt index a471403ba..da0e9063b 100644 --- a/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/GoogleMapConfig.kt +++ b/google-maps/android/src/main/java/com/capacitorjs/plugins/googlemaps/GoogleMapConfig.kt @@ -14,40 +14,60 @@ class GoogleMapConfig(fromJSONObject: JSONObject) { var googleMapOptions: GoogleMapOptions? = null var zoom: Int = 0 var liteMode: Boolean = false + var devicePixelRatio: Float = 1.00f init { - if(!fromJSONObject.has("width")) { - throw InvalidArgumentsError("GoogleMapConfig object is missing the required 'width' property") + if (!fromJSONObject.has("width")) { + throw InvalidArgumentsError( + "GoogleMapConfig object is missing the required 'width' property" + ) } - if(!fromJSONObject.has("height")) { - throw InvalidArgumentsError("GoogleMapConfig object is missing the required 'height' property") + if (!fromJSONObject.has("height")) { + throw InvalidArgumentsError( + "GoogleMapConfig object is missing the required 'height' property" + ) } - if(!fromJSONObject.has("x")) { - throw InvalidArgumentsError("GoogleMapConfig object is missing the required 'x' property") + if (!fromJSONObject.has("x")) { + throw InvalidArgumentsError( + "GoogleMapConfig object is missing the required 'x' property" + ) } - if(!fromJSONObject.has("y")) { - throw InvalidArgumentsError("GoogleMapConfig object is missing the required 'y' property") + if (!fromJSONObject.has("y")) { + throw InvalidArgumentsError( + "GoogleMapConfig object is missing the required 'y' property" + ) } - if(!fromJSONObject.has("zoom")) { - throw InvalidArgumentsError("GoogleMapConfig object is missing the required 'zoom' property") + if (!fromJSONObject.has("zoom")) { + throw InvalidArgumentsError( + "GoogleMapConfig object is missing the required 'zoom' property" + ) } - if(!fromJSONObject.has("center")) { - throw InvalidArgumentsError("GoogleMapConfig object is missing the required 'center' property") + if (fromJSONObject.has("devicePixelRatio")) { + devicePixelRatio = fromJSONObject.getDouble("devicePixelRatio").toFloat() + } + + if (!fromJSONObject.has("center")) { + throw InvalidArgumentsError( + "GoogleMapConfig object is missing the required 'center' property" + ) } val centerJSONObject = fromJSONObject.getJSONObject("center") - if(!centerJSONObject.has("lat") || !centerJSONObject.has("lng")) { - throw InvalidArgumentsError("LatLng object is missing the required 'lat' and/or 'lng' property") + if (!centerJSONObject.has("lat") || !centerJSONObject.has("lng")) { + throw InvalidArgumentsError( + "LatLng object is missing the required 'lat' and/or 'lng' property" + ) } - liteMode = fromJSONObject.has("androidLiteMode") - && fromJSONObject.getBoolean("androidLiteMode") + liteMode = + fromJSONObject.has("androidLiteMode") && + fromJSONObject.getBoolean("androidLiteMode") width = fromJSONObject.getInt("width") height = fromJSONObject.getInt("height") @@ -62,4 +82,4 @@ class GoogleMapConfig(fromJSONObject: JSONObject) { val cameraPosition = CameraPosition(center, zoom.toFloat(), 0.0F, 0.0F) googleMapOptions = GoogleMapOptions().camera(cameraPosition).liteMode(liteMode) } -} \ No newline at end of file +} diff --git a/google-maps/src/definitions.ts b/google-maps/src/definitions.ts index dd34c9d5e..723b4370e 100644 --- a/google-maps/src/definitions.ts +++ b/google-maps/src/definitions.ts @@ -18,19 +18,19 @@ export interface LatLng { */ export interface GoogleMapConfig { /** - * Override width for native map + * Override width for native map. */ width?: number; /** - * Override height for native map + * Override height for native map. */ height?: number; /** - * Override absolute x coordinate position for native map + * Override absolute x coordinate position for native map. */ x?: number; /** - * Override absolute y coordinate position for native map + * Override absolute y coordinate position for native map. */ y?: number; /** @@ -47,6 +47,10 @@ export interface GoogleMapConfig { * @default false */ androidLiteMode?: boolean; + /** + * Override pixel ratio for native map. + */ + devicePixelRatio?: number; } /** @@ -160,3 +164,56 @@ export interface Marker { */ draggable?: boolean; } + +/** + * The callback function to be called when map events are emitted. + */ +export type MapListenerCallback = (data: T) => void; + +export interface MapReadyCallbackData { + mapId: string; +} + +export interface MarkerCallbackData { + markerId: string; + latitude: number; + longitude: number; + title: string; + snippet: string; +} + +export interface CameraIdleCallbackData { + mapId: string; + bearing: number; + latitude: number; + longitude: number; + tilt: number; + zoom: number; +} + +export interface CameraMoveStartedCallbackData { + mapId: string; + isGesture: boolean; +} + +export interface ClusterClickCallbackData { + mapId: string; + latitude: number; + longitude: number; + size: number; + items: MarkerCallbackData[]; +} + +export interface MapClickCallbackData { + mapId: string; + latitude: number; + longitude: number; +} + +export interface MarkerClickCallbackData extends MarkerCallbackData { + mapId: string; +} + +export interface MyLocationButtonClickCallbackData { + mapId: string; +} diff --git a/google-maps/src/implementation.ts b/google-maps/src/implementation.ts index a640d8111..dd4764137 100644 --- a/google-maps/src/implementation.ts +++ b/google-maps/src/implementation.ts @@ -9,13 +9,31 @@ import type { Marker, } from './definitions'; +/** + * An interface containing the options used when creating a map. + */ export interface CreateMapArgs { + /** + * A unique identifier for the map instance. + */ id: string; + /** + * The Google Maps SDK API Key. + */ apiKey: string; + /** + * The initial configuration settings for the map. + */ config: GoogleMapConfig; + /** + * The DOM element that the Google Map View will be mounted on which determines size and positioning. + */ element: HTMLElement; + /** + * Destroy and re-create the map instance if a map with the supplied id already exists + * @default false + */ forceCreate?: boolean; - devicePixelRatio?: number; } export interface DestroyMapArgs { @@ -86,8 +104,6 @@ export interface OnScrollArgs { }; } -export type MapListenerCallback = (data: any) => void; - export interface CapacitorGoogleMapsPlugin extends Plugin { create(options: CreateMapArgs): Promise; addMarker(args: AddMarkerArgs): Promise<{ id: string }>; diff --git a/google-maps/src/map.ts b/google-maps/src/map.ts index d1569efb8..86c0e2309 100644 --- a/google-maps/src/map.ts +++ b/google-maps/src/map.ts @@ -1,14 +1,27 @@ import { Capacitor } from '@capacitor/core'; import type { PluginListenerHandle } from '@capacitor/core'; -import type { CameraConfig, Marker, MapPadding, MapType } from './definitions'; -import type { CreateMapArgs, MapListenerCallback } from './implementation'; +import type { + CameraConfig, + Marker, + MapPadding, + MapType, + MapListenerCallback, + MapReadyCallbackData, + CameraIdleCallbackData, + CameraMoveStartedCallbackData, + ClusterClickCallbackData, + MapClickCallbackData, + MarkerClickCallbackData, + MyLocationButtonClickCallbackData, +} from './definitions'; +import type { CreateMapArgs } from './implementation'; import { CapacitorGoogleMaps } from './implementation'; export interface GoogleMapInterface { create( options: CreateMapArgs, - callback?: MapListenerCallback, + callback?: MapListenerCallback, ): Promise; enableClustering(): Promise; disableClustering(): Promise; @@ -24,19 +37,33 @@ export interface GoogleMapInterface { enableAccessibilityElements(enabled: boolean): Promise; enableCurrentLocation(enabled: boolean): Promise; setPadding(padding: MapPadding): Promise; - setOnCameraIdleListener(callback?: MapListenerCallback): Promise; - setOnCameraMoveStartedListener(callback?: MapListenerCallback): Promise; - setOnClusterClickListener(callback?: MapListenerCallback): Promise; + setOnCameraIdleListener( + callback?: MapListenerCallback, + ): Promise; + setOnCameraMoveStartedListener( + callback?: MapListenerCallback, + ): Promise; + setOnClusterClickListener( + callback?: MapListenerCallback, + ): Promise; setOnClusterInfoWindowClickListener( - callback?: MapListenerCallback, + callback?: MapListenerCallback, + ): Promise; + setOnInfoWindowClickListener( + callback?: MapListenerCallback, + ): Promise; + setOnMapClickListener( + callback?: MapListenerCallback, + ): Promise; + setOnMarkerClickListener( + callback?: MapListenerCallback, ): Promise; - setOnInfoWindowClickListener(callback?: MapListenerCallback): Promise; - setOnMapClickListener(callback?: MapListenerCallback): Promise; - setOnMarkerClickListener(callback?: MapListenerCallback): Promise; setOnMyLocationButtonClickListener( - callback?: MapListenerCallback, + callback?: MapListenerCallback, + ): Promise; + setOnMyLocationClickListener( + callback?: MapListenerCallback, ): Promise; - setOnMyLocationClickListener(callback?: MapListenerCallback): Promise; } class MapCustomElement extends HTMLElement { @@ -81,22 +108,13 @@ export class GoogleMap { /** * Creates a new instance of a Google Map - * - * @param element - * DOM element that will contain the map view and determine sizing / positioning - * @param id Unique id for the map instance - * @param apiKey - * Google Maps SDK API Key - * @param config - * Initial configuration settings for the map - * @param forceCreate - * If a map already exists with the supplied id, automatically destroy and re-create the map instance - * + * @param options + * @param callback * @returns GoogleMap */ public static async create( options: CreateMapArgs, - callback?: MapListenerCallback, + callback?: MapListenerCallback, ): Promise { const newMap = new GoogleMap(options.id); @@ -116,7 +134,7 @@ export class GoogleMap { options.config.height = elementBounds.height; options.config.x = elementBounds.x; options.config.y = elementBounds.y; - options.devicePixelRatio = window.devicePixelRatio; + options.config.devicePixelRatio = window.devicePixelRatio; if (Capacitor.getPlatform() == 'android') { newMap.initScrolling(); @@ -126,7 +144,15 @@ export class GoogleMap { await CapacitorGoogleMaps.create(options); if (callback) { - CapacitorGoogleMaps.addListener('onMapReady', callback); + const onMapReadyListener = await CapacitorGoogleMaps.addListener( + 'onMapReady', + (data: MapReadyCallbackData) => { + if (data.mapId == newMap.id) { + callback(data); + onMapReadyListener.remove(); + } + }, + ); } return newMap; @@ -398,7 +424,9 @@ export class GoogleMap { * @param callback * @returns */ - async setOnCameraIdleListener(callback?: MapListenerCallback): Promise { + async setOnCameraIdleListener( + callback?: MapListenerCallback, + ): Promise { if (this.onCameraIdleListener) { this.onCameraIdleListener.remove(); } @@ -420,7 +448,7 @@ export class GoogleMap { * @returns */ async setOnCameraMoveStartedListener( - callback?: MapListenerCallback, + callback?: MapListenerCallback, ): Promise { if (this.onCameraMoveStartedListener) { this.onCameraMoveStartedListener.remove(); @@ -443,7 +471,7 @@ export class GoogleMap { * @returns */ async setOnClusterClickListener( - callback?: MapListenerCallback, + callback?: MapListenerCallback, ): Promise { if (this.onClusterClickListener) { this.onClusterClickListener.remove(); @@ -466,7 +494,7 @@ export class GoogleMap { * @returns */ async setOnClusterInfoWindowClickListener( - callback?: MapListenerCallback, + callback?: MapListenerCallback, ): Promise { if (this.onClusterInfoWindowClickListener) { this.onClusterInfoWindowClickListener.remove(); @@ -490,7 +518,7 @@ export class GoogleMap { * @returns */ async setOnInfoWindowClickListener( - callback?: MapListenerCallback, + callback?: MapListenerCallback, ): Promise { if (this.onInfoWindowClickListener) { this.onInfoWindowClickListener.remove(); @@ -512,7 +540,9 @@ export class GoogleMap { * @param callback * @returns */ - async setOnMapClickListener(callback?: MapListenerCallback): Promise { + async setOnMapClickListener( + callback?: MapListenerCallback, + ): Promise { if (this.onMapClickListener) { this.onMapClickListener.remove(); } @@ -534,7 +564,7 @@ export class GoogleMap { * @returns */ async setOnMarkerClickListener( - callback?: MapListenerCallback, + callback?: MapListenerCallback, ): Promise { if (this.onMarkerClickListener) { this.onMarkerClickListener.remove(); @@ -557,7 +587,7 @@ export class GoogleMap { * @returns */ async setOnMyLocationButtonClickListener( - callback?: MapListenerCallback, + callback?: MapListenerCallback, ): Promise { if (this.onMyLocationButtonClickListener) { this.onMyLocationButtonClickListener.remove(); @@ -581,7 +611,7 @@ export class GoogleMap { * @returns */ async setOnMyLocationClickListener( - callback?: MapListenerCallback, + callback?: MapListenerCallback, ): Promise { if (this.onMyLocationClickListener) { this.onMyLocationClickListener.remove(); @@ -649,7 +679,9 @@ export class GoogleMap { } } - private generateCallback(callback: MapListenerCallback): MapListenerCallback { + private generateCallback( + callback: MapListenerCallback, + ): MapListenerCallback { const mapId = this.id; return (data: any) => { if (data.mapId == mapId) {