This commit is contained in:
metacryst
2026-01-09 11:14:27 -06:00
parent cf03c95664
commit 637c9e4674
2149 changed files with 527743 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
require 'json'
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
Pod::Spec.new do |s|
s.name = 'CapacitorGoogleMaps'
s.version = package['version']
s.summary = package['description']
s.license = package['license']
s.homepage = package['repository']['url']
s.author = package['author']
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
s.ios.deployment_target = '14.0'
s.dependency 'Capacitor'
s.dependency 'GoogleMaps', '~> 8.4'
s.dependency 'Google-Maps-iOS-Utils', '~> 5.0'
s.swift_version = '5.1'
s.static_framework = true
end

32
node_modules/@capacitor/google-maps/Package.swift generated vendored Normal file
View File

@@ -0,0 +1,32 @@
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "CapacitorGoogleMaps",
platforms: [.iOS(.v14)],
products: [
.library(
name: "CapacitorGoogleMaps",
targets: ["CapacitorGoogleMapsPlugin"])
],
dependencies: [
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0"),
.package(url: "https://github.com/googlemaps/ios-maps-sdk.git", .upToNextMajor(from:"8.4.0")),
.package(url: "https://github.com/googlemaps/google-maps-ios-utils.git", .upToNextMajor(from:"5.0.0"))
],
targets: [
.target(
name: "CapacitorGoogleMapsPlugin",
dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm"),
.product(name: "GoogleMaps", package: "ios-maps-sdk"),
.product(name: "GoogleMapsUtils", package: "google-maps-ios-utils")
],
path: "ios/Sources/CapacitorGoogleMapsPlugin"),
.testTarget(
name: "CapacitorGoogleMapsPluginTests",
dependencies: ["CapacitorGoogleMapsPlugin"],
path: "ios/Tests/CapacitorGoogleMapsPluginTests")
]
)

1290
node_modules/@capacitor/google-maps/README.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
ext {
capacitorVersion = System.getenv('CAPACITOR_VERSION')
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
androidxCoreKTXVersion = project.hasProperty('androidxCoreKTXVersion') ? rootProject.ext.androidxCoreKTXVersion : '1.12.0'
googleMapsPlayServicesVersion = project.hasProperty('googleMapsPlayServicesVersion') ? rootProject.ext.googleMapsPlayServicesVersion : '19.0.0'
googleMapsUtilsVersion = project.hasProperty('googleMapsUtilsVersion') ? rootProject.ext.googleMapsUtilsVersion : '3.8.2'
googleMapsKtxVersion = project.hasProperty('googleMapsKtxVersion') ? rootProject.ext.googleMapsKtxVersion : '5.1.1'
googleMapsUtilsKtxVersion = project.hasProperty('googleMapsUtilsKtxVersion') ? rootProject.ext.googleMapsUtilsKtxVersion : '5.1.1'
kotlinxCoroutinesVersion = project.hasProperty('kotlinxCoroutinesVersion') ? rootProject.ext.kotlinxCoroutinesVersion : '1.7.3'
}
buildscript {
ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.9.25'
repositories {
google()
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:8.7.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
}
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
apply plugin: 'io.github.gradle-nexus.publish-plugin'
apply from: file('../../scripts/android/publish-root.gradle')
apply from: file('../../scripts/android/publish-module.gradle')
}
android {
namespace "com.capacitorjs.plugins.googlemaps"
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
defaultConfig {
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_21
targetCompatibility JavaVersion.VERSION_21
}
publishing {
singleVariant("release")
}
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinxCoroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
}
}
kotlin {
jvmToolchain(21)
}
repositories {
google()
mavenCentral()
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
implementation "com.capacitorjs:core:$capacitorVersion"
} else {
implementation project(':capacitor-android')
}
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
testImplementation "junit:junit:$junitVersion"
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
implementation "androidx.core:core-ktx:$androidxCoreKTXVersion"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "com.google.maps.android:maps-ktx:$googleMapsKtxVersion"
implementation "com.google.maps.android:maps-utils-ktx:$googleMapsUtilsKtxVersion"
implementation "com.google.maps.android:android-maps-utils:$googleMapsUtilsVersion"
implementation "com.google.android.gms:play-services-maps:$googleMapsPlayServicesVersion"
}

View File

@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@@ -0,0 +1,37 @@
package com.capacitorjs.plugins.googlemaps
import android.content.Context
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.MarkerOptions
import com.google.maps.android.clustering.ClusterManager
import com.google.maps.android.clustering.view.DefaultClusterRenderer
class CapacitorClusterManagerRenderer(
context: Context,
map: GoogleMap?,
clusterManager: ClusterManager<CapacitorGoogleMapMarker>?,
minClusterSize: Int?
) : DefaultClusterRenderer<CapacitorGoogleMapMarker>(context, map, clusterManager) {
init {
if(minClusterSize != null && minClusterSize > 0) {
super.setMinClusterSize(minClusterSize)
}
}
override fun onBeforeClusterItemRendered(item: CapacitorGoogleMapMarker, markerOptions: MarkerOptions) {
super.onBeforeClusterItemRendered(item, markerOptions)
item.markerOptions?.let {
markerOptions.position(it.position)
markerOptions.title(it.title)
markerOptions.snippet(it.snippet)
markerOptions.alpha(it.alpha)
markerOptions.flat(it.isFlat)
markerOptions.draggable(it.isDraggable)
if(null != it.icon) {
markerOptions.icon(it.icon)
}
}
}
}

View File

@@ -0,0 +1,93 @@
package com.capacitorjs.plugins.googlemaps
import android.graphics.Color
import android.util.Size
import androidx.core.math.MathUtils
import com.google.android.gms.maps.model.*
import com.google.maps.android.clustering.ClusterItem
import org.json.JSONObject
class CapacitorGoogleMapMarker(fromJSONObject: JSONObject): ClusterItem {
var coordinate: LatLng = LatLng(0.0, 0.0)
var opacity: Float = 1.0f
private var title: String
private var snippet: String
private var zIndex: Float = 0.0f
var isFlat: Boolean = false
var iconUrl: String? = null
var iconSize: Size? = null
var iconAnchor: CapacitorGoogleMapsPoint? = null
var draggable: Boolean = false
var googleMapMarker: Marker? = null
var colorHue: Float? = null
var markerOptions: MarkerOptions? = null
init {
if (!fromJSONObject.has("coordinate")) {
throw InvalidArgumentsError("Marker object is missing the required 'coordinate' property")
}
val latLngObj = fromJSONObject.getJSONObject("coordinate")
if (!latLngObj.has("lat") || !latLngObj.has("lng")) {
throw InvalidArgumentsError("LatLng object is missing the required 'lat' and/or 'lng' property")
}
coordinate = LatLng(latLngObj.getDouble("lat"), latLngObj.getDouble("lng"))
title = fromJSONObject.optString("title")
opacity = fromJSONObject.optDouble("opacity", 1.0).toFloat()
snippet = fromJSONObject.optString("snippet")
isFlat = fromJSONObject.optBoolean("isFlat", false)
iconUrl = fromJSONObject.optString("iconUrl")
if (fromJSONObject.has("iconSize")) {
val iconSizeObject = fromJSONObject.getJSONObject("iconSize")
iconSize = Size(iconSizeObject.optInt("width", 0), iconSizeObject.optInt("height", 0))
}
if (fromJSONObject.has("iconAnchor")) {
val inputAnchorPoint = CapacitorGoogleMapsPoint(fromJSONObject.getJSONObject("iconAnchor"))
iconAnchor = this.buildIconAnchorPoint(inputAnchorPoint)
}
if (fromJSONObject.has("tintColor")) {
val tintColorObject = fromJSONObject.getJSONObject("tintColor")
val r = MathUtils.clamp(tintColorObject.optDouble("r", 0.00), 0.00, 255.0)
val g = MathUtils.clamp(tintColorObject.optDouble("g", 0.00), 0.00, 255.0)
val b = MathUtils.clamp(tintColorObject.optDouble("b", 0.00), 0.00, 255.0)
val hsl = FloatArray(3)
Color.RGBToHSV(r.toInt(), g.toInt(), b.toInt(), hsl)
colorHue = hsl[0]
}
draggable = fromJSONObject.optBoolean("draggable", false)
zIndex = fromJSONObject.optLong("zIndex").toFloat()
}
override fun getPosition(): LatLng {
return LatLng(coordinate.latitude, coordinate.longitude)
}
override fun getTitle(): String {
return title
}
override fun getSnippet(): String {
return snippet
}
override fun getZIndex(): Float {
return zIndex
}
private fun buildIconAnchorPoint(iconAnchor: CapacitorGoogleMapsPoint): CapacitorGoogleMapsPoint? {
iconSize ?: return null
val u: Float = iconAnchor.x / iconSize!!.width
val v: Float = iconAnchor.y / iconSize!!.height
return CapacitorGoogleMapsPoint(u, v)
}
}

View File

@@ -0,0 +1,78 @@
package com.capacitorjs.plugins.googlemaps
import android.graphics.Color
import androidx.core.graphics.toColor
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Polyline
import org.json.JSONObject
class CapacitorGoogleMapPolyline(fromJSONObject: JSONObject) {
var path: MutableList<LatLng> = mutableListOf<LatLng>()
var styleSpans: MutableList<CapacitorGoogleMapsStyleSpan> = mutableListOf<CapacitorGoogleMapsStyleSpan>()
var strokeWidth: Float = 1.0f
var strokeColor: Int = Color.BLUE
var clickable: Boolean
var geodesic: Boolean
var zIndex: Float = 0.00f
var tag: String = ""
var googleMapsPolyline: Polyline? = null
init {
if (!fromJSONObject.has("path")) {
throw InvalidArgumentsError("Polyline object is missing the required 'path' property")
}
val pathArray = fromJSONObject.getJSONArray("path")
for (i in 0 until pathArray.length()) {
val obj = pathArray.getJSONObject(i)
if (!obj.has("lat") || !obj.has("lng")) {
throw InvalidArgumentsError("LatLng object is missing the required 'lat' and/or 'lng' property")
}
val lat = obj.getDouble("lat")
val lng = obj.getDouble("lng")
path.add(LatLng(lat, lng))
}
if (fromJSONObject.has("styleSpans")) {
val styleSpanArray = fromJSONObject.getJSONArray("styleSpans")
for (i in 0 until styleSpanArray.length()) {
val obj = styleSpanArray.getJSONObject(i)
if (obj.has("color")) {
val color = obj.getString("color")
if (obj.has("segments")) {
val segments = obj.getDouble("segments")
styleSpans.add(CapacitorGoogleMapsStyleSpan(Color.parseColor(color), segments))
} else {
styleSpans.add(CapacitorGoogleMapsStyleSpan(Color.parseColor(color), null))
}
}
}
}
val strokeOpacity = fromJSONObject.optDouble("strokeOpacity", 1.0)
strokeColor = this.processColor(fromJSONObject.getString("strokeColor"), strokeOpacity)
strokeWidth = fromJSONObject.optDouble("strokeWeight", 1.0).toFloat()
clickable = fromJSONObject.optBoolean("clickable", false)
geodesic = fromJSONObject.optBoolean("geodesic", false)
zIndex = fromJSONObject.optDouble("zIndex", 1.0).toFloat()
tag = fromJSONObject.optString("tag", "")
}
private fun processColor(hex: String, opacity: Double): Int {
val colorInt = Color.parseColor(hex)
val alpha = (opacity * 255.0).toInt()
val red = android.graphics.Color.red(colorInt)
val green = android.graphics.Color.green(colorInt)
val blue = android.graphics.Color.blue(colorInt)
return Color.argb(alpha, red, green, blue)
}
}

View File

@@ -0,0 +1,28 @@
package com.capacitorjs.plugins.googlemaps
import com.google.android.gms.maps.model.TileOverlay
import org.json.JSONObject
class CapacitorGoogleMapTileOverlay(fromJSONObject: JSONObject) {
var url: String
var opacity: Float? = null
var zIndex: Float? = null
var visible: Boolean? = null
var googleMapTileOverlay: TileOverlay? = null
init {
if (!fromJSONObject.has("url")) {
throw InvalidArgumentsError("TileOverlay object is missing the required 'url' property")
}
url = fromJSONObject.getString("url")
if (fromJSONObject.has("opacity")) {
opacity = fromJSONObject.optDouble("opacity").toFloat()
}
if (fromJSONObject.has("visible")) {
visible = fromJSONObject.optBoolean("visible")
}
if (fromJSONObject.has("zIndex")) {
zIndex = fromJSONObject.optLong("zIndex").toFloat()
}
}
}

View File

@@ -0,0 +1,33 @@
package com.capacitorjs.plugins.googlemaps
import org.json.JSONObject
class CapacitorGoogleMapsBounds(fromJSONObject: JSONObject) {
var width: Int = 0
var height: Int = 0
var x: Int = 0
var y: Int = 0
init {
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("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")
}
width = fromJSONObject.getInt("width")
height = fromJSONObject.getInt("height")
x = fromJSONObject.getInt("x")
y = fromJSONObject.getInt("y")
}
}

View File

@@ -0,0 +1,63 @@
package com.capacitorjs.plugins.googlemaps
import android.graphics.Color
import com.google.android.gms.maps.model.Circle
import com.google.android.gms.maps.model.LatLng
import org.json.JSONObject
class CapacitorGoogleMapsCircle(fromJSONObject: JSONObject) {
var center: LatLng
var radius: Float
var strokeWidth: Float = 1.0f
var strokeColor: Int = Color.BLUE
var fillColor: Int = Color.BLUE
var clickable: Boolean
var zIndex: Float = 0.00f
var tag: String = ""
var googleMapsCircle: Circle? = null
init {
if (!fromJSONObject.has("center")) {
throw InvalidArgumentsError("Circle object is missing the required 'center' property")
}
if (!fromJSONObject.has("radius")) {
throw InvalidArgumentsError("Circle object is missing the required 'radius' property")
}
val latLng = fromJSONObject.getJSONObject("center")
if (!latLng.has("lat") || !latLng.has("lng")) {
throw InvalidArgumentsError("LatLng object is missing the required 'lat' and/or 'lng' property")
}
val lat = latLng.getDouble("lat")
val lng = latLng.getDouble("lng")
center = LatLng(lat, lng)
radius = fromJSONObject.getDouble("radius").toFloat()
val strokeOpacity = fromJSONObject.optDouble("strokeOpacity", 1.0)
strokeColor = this.processColor(fromJSONObject.getString("strokeColor"), strokeOpacity)
val fillOpacity = fromJSONObject.optDouble("fillOpacity", 1.0)
fillColor = this.processColor(fromJSONObject.getString("fillColor"), fillOpacity)
strokeWidth = fromJSONObject.optDouble("strokeWeight", 1.0).toFloat()
clickable = fromJSONObject.optBoolean("clickable", false)
zIndex = fromJSONObject.optDouble("zIndex", 1.0).toFloat()
tag = fromJSONObject.optString("tag", "")
}
private fun processColor(hex: String, opacity: Double): Int {
val colorInt = Color.parseColor(hex)
val alpha = (opacity * 255.0).toInt()
val red = android.graphics.Color.red(colorInt)
val green = android.graphics.Color.green(colorInt)
val blue = android.graphics.Color.blue(colorInt)
return Color.argb(alpha, red, green, blue)
}
}

View File

@@ -0,0 +1,23 @@
package com.capacitorjs.plugins.googlemaps
import org.json.JSONObject
class CapacitorGoogleMapsPoint() {
var x: Float = 0.00f
var y: Float = 0.00f
constructor(fromJSONObject: JSONObject) : this() {
if(fromJSONObject.has("x")) {
this.x = fromJSONObject.getDouble("x").toFloat()
}
if(fromJSONObject.has("y")) {
this.y = fromJSONObject.getDouble("y").toFloat()
}
}
constructor(x: Float, y: Float) : this() {
this.x = x;
this.y = y
}
}

View File

@@ -0,0 +1,80 @@
package com.capacitorjs.plugins.googlemaps
import android.graphics.Color
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Polygon
import org.json.JSONArray
import org.json.JSONObject
class CapacitorGoogleMapsPolygon(fromJSONObject: JSONObject) {
var shapes: MutableList<MutableList<LatLng>> = mutableListOf<MutableList<LatLng>>()
var strokeWidth: Float = 1.0f
var strokeColor: Int = Color.BLUE
var fillColor: Int = Color.BLUE
var clickable: Boolean
var geodesic: Boolean
var zIndex: Float = 0.00f
var tag: String = ""
var googleMapsPolygon: Polygon? = null
init {
if (!fromJSONObject.has("paths")) {
throw InvalidArgumentsError("Polygon object is missing the required 'paths' property")
}
val pathsArray = fromJSONObject.getJSONArray("paths")
for (i in 0 until pathsArray.length()) {
val arr = pathsArray.optJSONArray(i)
if (arr == null) {
// is a single shape
val shape = this.processShape(pathsArray)
this.shapes.add(shape)
break
} else {
val shape = this.processShape(arr)
this.shapes.add(shape)
}
}
val strokeOpacity = fromJSONObject.optDouble("strokeOpacity", 1.0)
strokeColor = this.processColor(fromJSONObject.getString("strokeColor"), strokeOpacity)
val fillOpacity = fromJSONObject.optDouble("fillOpacity", 1.0)
fillColor = this.processColor(fromJSONObject.getString("fillColor"), fillOpacity)
strokeWidth = fromJSONObject.optDouble("strokeWeight", 1.0).toFloat()
clickable = fromJSONObject.optBoolean("clickable", false)
geodesic = fromJSONObject.optBoolean("geodesic", false)
zIndex = fromJSONObject.optDouble("zIndex", 1.0).toFloat()
tag = fromJSONObject.optString("tag", "")
}
private fun processShape(shapeArr: JSONArray): MutableList<LatLng> {
var shape = mutableListOf<LatLng>()
for (i in 0 until shapeArr.length()) {
val obj = shapeArr.getJSONObject(i)
if (!obj.has("lat") || !obj.has("lng")) {
throw InvalidArgumentsError("LatLng object is missing the required 'lat' and/or 'lng' property")
}
val lat = obj.getDouble("lat")
val lng = obj.getDouble("lng")
shape.add(LatLng(lat, lng))
}
return shape
}
private fun processColor(hex: String, opacity: Double): Int {
val colorInt = Color.parseColor(hex)
val alpha = (opacity * 255.0).toInt()
val red = android.graphics.Color.red(colorInt)
val green = android.graphics.Color.green(colorInt)
val blue = android.graphics.Color.blue(colorInt)
return Color.argb(alpha, red, green, blue)
}
}

View File

@@ -0,0 +1,5 @@
package com.capacitorjs.plugins.googlemaps
import android.graphics.Color
data class CapacitorGoogleMapsStyleSpan(val color: Int, val segments: Double?)

View File

@@ -0,0 +1,50 @@
package com.capacitorjs.plugins.googlemaps
import com.google.android.gms.maps.model.LatLng
import org.json.JSONObject
class GoogleMapCameraConfig(fromJSONObject: JSONObject) {
var coordinate: LatLng? = null
var zoom: Double? = null
var angle: Double? = null
var bearing: Double? = null
var animate: Boolean? = null
var animationDuration: Double? = null
init {
if (fromJSONObject.has("zoom")) {
zoom = fromJSONObject.getDouble("zoom")
}
if(fromJSONObject.has("angle")) {
angle = fromJSONObject.getDouble("angle")
}
if (fromJSONObject.has("bearing")) {
bearing = fromJSONObject.getDouble("bearing")
}
if (fromJSONObject.has("animate")) {
animate = fromJSONObject.getBoolean("animate")
}
if (fromJSONObject.has("animationDuration")) {
animationDuration = fromJSONObject.getDouble("animationDuration")
}
if (fromJSONObject.has("coordinate")) {
val coordinateJSONObject = fromJSONObject.getJSONObject("coordinate")
if(!coordinateJSONObject.has("lat") || !coordinateJSONObject.has("lng")) {
throw InvalidArgumentsError("LatLng object is missing the required 'lat' and/or 'lng' property")
}
val lat = coordinateJSONObject.getDouble("lat")
val lng = coordinateJSONObject.getDouble("lng")
coordinate = LatLng(lat, lng)
} else {
coordinate = null
}
}
}

View File

@@ -0,0 +1,165 @@
package com.capacitorjs.plugins.googlemaps
import com.google.android.gms.maps.GoogleMapOptions
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import org.json.JSONObject
class GoogleMapConfig(fromJSONObject: JSONObject) {
var width: Int = 0
var height: Int = 0
var x: Int = 0
var y: Int = 0
var center: LatLng = LatLng(0.0, 0.0)
var googleMapOptions: GoogleMapOptions? = null
var zoom: Int = 0
var liteMode: Boolean = false
var devicePixelRatio: Float = 1.00f
var styles: String? = null
var mapId: String? = null
var minZoom: Int? = null
var maxZoom: Int? = null
var mapTypeId: String? = null
var restriction: GoogleMapConfigRestriction? = null
var heading: Double? = null
init {
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("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("zoom")) {
throw InvalidArgumentsError(
"GoogleMapConfig object is missing the required 'zoom' 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"
)
}
liteMode =
fromJSONObject.has("androidLiteMode") &&
fromJSONObject.getBoolean("androidLiteMode")
width = fromJSONObject.getInt("width")
height = fromJSONObject.getInt("height")
x = fromJSONObject.getInt("x")
y = fromJSONObject.getInt("y")
val tempZoom = fromJSONObject.getInt("zoom")
var tempMinZoom = fromJSONObject.optInt("minZoom").takeIf { fromJSONObject.has("minZoom") }
var tempMaxZoom = fromJSONObject.optInt("maxZoom").takeIf { fromJSONObject.has("maxZoom") }
if (tempMinZoom != null && tempMaxZoom != null && tempMinZoom > tempMaxZoom) {
tempMinZoom = tempMaxZoom.also { tempMaxZoom = tempMinZoom }
}
minZoom = tempMinZoom
maxZoom = tempMaxZoom
zoom = tempZoom.coerceIn(
tempMinZoom ?: Int.MIN_VALUE,
tempMaxZoom ?: Int.MAX_VALUE
)
mapTypeId = fromJSONObject.optString("mapTypeId").takeIf { fromJSONObject.has("mapTypeId") }
val lat = centerJSONObject.getDouble("lat")
val lng = centerJSONObject.getDouble("lng")
center = LatLng(lat, lng)
val cameraPosition = CameraPosition(center, zoom.toFloat(), 0.0F, 0.0F)
styles = fromJSONObject.getString("styles")
mapId = fromJSONObject.getString("androidMapId")
restriction = fromJSONObject.optJSONObject("restriction")?.let { GoogleMapConfigRestriction(it) }
heading = fromJSONObject.optDouble("heading").takeIf { fromJSONObject.has("heading") }
googleMapOptions = GoogleMapOptions().camera(cameraPosition).liteMode(liteMode)
if (mapId != null) {
googleMapOptions?.mapId(mapId!!)
}
}
}
class GoogleMapConfigRestriction(fromJSONObject: JSONObject) {
var latLngBounds: LatLngBounds
init {
if (!fromJSONObject.has("latLngBounds")) {
throw InvalidArgumentsError(
"GoogleMapConfigRestriction object is missing the required 'latLngBounds' property"
)
}
val latLngBoundsObj = fromJSONObject.getJSONObject("latLngBounds")
if (!latLngBoundsObj.has("north")) {
throw InvalidArgumentsError(
"GoogleMapConfigRestriction object is missing the required 'latLngBounds.north' property"
)
}
if (!latLngBoundsObj.has("south")) {
throw InvalidArgumentsError(
"GoogleMapConfigRestriction object is missing the required 'latLngBounds.south' property"
)
}
if (!latLngBoundsObj.has("east")) {
throw InvalidArgumentsError(
"GoogleMapConfigRestriction object is missing the required 'latLngBounds.east' property"
)
}
if (!latLngBoundsObj.has("west")) {
throw InvalidArgumentsError(
"GoogleMapConfigRestriction object is missing the required 'latLngBounds.west' property"
)
}
val north = latLngBoundsObj.getDouble("north")
val south = latLngBoundsObj.getDouble("south")
val east = latLngBoundsObj.getDouble("east")
val west = latLngBoundsObj.getDouble("west")
latLngBounds = LatLngBounds(
LatLng(south, west),
LatLng(north, east)
)
}
}

View File

@@ -0,0 +1,114 @@
package com.capacitorjs.plugins.googlemaps
import org.json.JSONObject
import kotlin.Exception
enum class GoogleMapErrors {
UNHANDLED_ERROR, INVALID_MAP_ID, MAP_NOT_FOUND, MARKER_NOT_FOUND, INVALID_ARGUMENTS, PERMISSIONS_DENIED_LOCATION, GOOGLE_MAP_NOT_AVAILABLE, BOUNDS_NOT_FOUND, TILE_OVERLAY_NOT_FOUND
}
class GoogleMapErrorObject(val code: Int, val message: String, val extra: HashMap<String,Any> = HashMap()) {
private fun asJSONObject(): JSONObject {
val returnJSONObject = JSONObject()
returnJSONObject.put("code", code)
returnJSONObject.put("message", message)
returnJSONObject.put("extra", extra)
return returnJSONObject
}
override fun toString(): String {
return this.asJSONObject().toString()
}
}
fun getErrorObject(err: GoogleMapsError): GoogleMapErrorObject {
return when(err) {
is InvalidArgumentsError -> {
GoogleMapErrorObject(err.getErrorCode(), "Invalid Arguments Provided: ${err.message}.")
}
is InvalidMapIdError -> {
GoogleMapErrorObject(err.getErrorCode(), "Missing or invalid map id.")
}
is MapNotFoundError -> {
GoogleMapErrorObject(err.getErrorCode(), "Map not found for provided id.")
}
is MarkerNotFoundError -> {
GoogleMapErrorObject(err.getErrorCode(), "Marker not found for provided id.")
}
is PermissionDeniedLocation -> {
GoogleMapErrorObject(err.getErrorCode(), "Permissions denied for accessing device location.")
}
is GoogleMapNotAvailable -> {
GoogleMapErrorObject(err.getErrorCode(), "Google Map is not available.")
}
is BoundsNotFoundError -> {
GoogleMapErrorObject(err.getErrorCode(), "Google Map Bounds could not be found.")
}
is TileOverlayNotFoundError -> {
GoogleMapErrorObject(err.getErrorCode(), "Tile overlay not found for provided id.")
}
else -> {
GoogleMapErrorObject(err.getErrorCode(), "Unhandled Error: ${err.message}.")
}
}
}
fun getErrorObject(err: Exception): GoogleMapErrorObject {
return GoogleMapErrorObject(0, "Unhandled Error: ${err.message}.")
}
open class GoogleMapsError(message: String? = ""): Throwable(message) {
open fun getErrorCode(): Int {
return GoogleMapErrors.UNHANDLED_ERROR.ordinal
}
}
class InvalidMapIdError(message: String? = ""): GoogleMapsError(message) {
override fun getErrorCode(): Int {
return GoogleMapErrors.INVALID_MAP_ID.ordinal
}
}
class MapNotFoundError(message: String? = ""): GoogleMapsError(message) {
override fun getErrorCode(): Int {
return GoogleMapErrors.MAP_NOT_FOUND.ordinal
}
}
class MarkerNotFoundError(message: String? = ""): GoogleMapsError(message) {
override fun getErrorCode(): Int {
return GoogleMapErrors.MARKER_NOT_FOUND.ordinal
}
}
class TileOverlayNotFoundError(message: String? = ""): GoogleMapsError(message) {
override fun getErrorCode(): Int {
return GoogleMapErrors.TILE_OVERLAY_NOT_FOUND.ordinal
}
}
class InvalidArgumentsError(message: String? = ""): GoogleMapsError(message) {
override fun getErrorCode(): Int {
return GoogleMapErrors.INVALID_ARGUMENTS.ordinal
}
}
class PermissionDeniedLocation(message: String? = ""): GoogleMapsError(message) {
override fun getErrorCode(): Int {
return GoogleMapErrors.PERMISSIONS_DENIED_LOCATION.ordinal
}
}
class GoogleMapNotAvailable(message: String? = ""): GoogleMapsError(message) {
override fun getErrorCode(): Int {
return GoogleMapErrors.GOOGLE_MAP_NOT_AVAILABLE.ordinal
}
}
class BoundsNotFoundError(message: String? = ""): GoogleMapsError(message) {
override fun getErrorCode(): Int {
return GoogleMapErrors.BOUNDS_NOT_FOUND.ordinal
}
}

View File

@@ -0,0 +1,28 @@
package com.capacitorjs.plugins.googlemaps
import org.json.JSONObject
class GoogleMapPadding(fromJSONObject: JSONObject) {
var top: Int = 0
var bottom: Int = 0
var left: Int = 0
var right: Int = 0
init {
if(fromJSONObject.has("top")) {
top = fromJSONObject.getInt("top")
}
if(fromJSONObject.has("bottom")) {
bottom = fromJSONObject.getInt("bottom")
}
if(fromJSONObject.has("left")) {
left = fromJSONObject.getInt("left")
}
if(fromJSONObject.has("right")) {
right = fromJSONObject.getInt("right")
}
}
}

View File

2036
node_modules/@capacitor/google-maps/dist/docs.json generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
import { CapacitorGoogleMaps } from './implementation';
export class LatLngBounds {
constructor(bounds) {
this.southwest = bounds.southwest;
this.center = bounds.center;
this.northeast = bounds.northeast;
}
async contains(point) {
const result = await CapacitorGoogleMaps.mapBoundsContains({
bounds: this,
point,
});
return result['contains'];
}
async extend(point) {
const result = await CapacitorGoogleMaps.mapBoundsExtend({
bounds: this,
point,
});
this.southwest = result['bounds']['southwest'];
this.center = result['bounds']['center'];
this.northeast = result['bounds']['northeast'];
return this;
}
}
export var MapType;
(function (MapType) {
/**
* Basic map.
*/
MapType["Normal"] = "Normal";
/**
* Satellite imagery with roads and labels.
*/
MapType["Hybrid"] = "Hybrid";
/**
* Satellite imagery with no labels.
*/
MapType["Satellite"] = "Satellite";
/**
* Topographic data.
*/
MapType["Terrain"] = "Terrain";
/**
* No base map tiles.
*/
MapType["None"] = "None";
})(MapType || (MapType = {}));
//# sourceMappingURL=definitions.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
import { registerPlugin } from '@capacitor/core';
const CapacitorGoogleMaps = registerPlugin('CapacitorGoogleMaps', {
web: () => import('./web').then((m) => new m.CapacitorGoogleMapsWeb()),
});
CapacitorGoogleMaps.addListener('isMapInFocus', (data) => {
var _a;
const x = data.x;
const y = data.y;
const elem = document.elementFromPoint(x, y);
const internalId = (_a = elem === null || elem === void 0 ? void 0 : elem.dataset) === null || _a === void 0 ? void 0 : _a.internalId;
const mapInFocus = internalId === data.mapId;
CapacitorGoogleMaps.dispatchMapEvent({ id: data.mapId, focus: mapInFocus });
});
export { CapacitorGoogleMaps };
//# sourceMappingURL=implementation.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
/* eslint-disable @typescript-eslint/no-namespace */
import { LatLngBounds, MapType } from './definitions';
import { GoogleMap } from './map';
export { GoogleMap, LatLngBounds, MapType };
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,OAAO,EAAE,YAAY,EAAE,OAAO,EAAgD,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAgD,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\nimport { LatLngBounds, MapType, Marker, Polygon, Circle, Polyline, StyleSpan } from './definitions';\nimport { GoogleMap } from './map';\n\nexport { GoogleMap, LatLngBounds, MapType, Marker, Polygon, Circle, Polyline, StyleSpan };\n\ndeclare global {\n export namespace JSX {\n export interface IntrinsicElements {\n 'capacitor-google-map': any;\n }\n }\n}\n"]}

861
node_modules/@capacitor/google-maps/dist/esm/map.js generated vendored Normal file
View File

@@ -0,0 +1,861 @@
import { Capacitor } from '@capacitor/core';
import { LatLngBounds, MapType } from './definitions';
import { CapacitorGoogleMaps } from './implementation';
class MapCustomElement extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.innerHTML = '';
if (Capacitor.getPlatform() == 'ios') {
this.style.overflow = 'scroll';
this.style['-webkit-overflow-scrolling'] = 'touch';
const overflowDiv = document.createElement('div');
overflowDiv.style.height = '200%';
this.appendChild(overflowDiv);
}
}
}
customElements.define('capacitor-google-map', MapCustomElement);
export class GoogleMap {
constructor(id) {
this.element = null;
this.resizeObserver = null;
this.handleScrollEvent = () => this.updateMapBounds();
this.id = id;
}
/**
* Creates a new instance of a Google Map
* @param options
* @param callback
* @returns GoogleMap
*/
static async create(options, callback) {
const newMap = new GoogleMap(options.id);
if (!options.element) {
throw new Error('container element is required');
}
if (options.config.androidLiteMode === undefined) {
options.config.androidLiteMode = false;
}
newMap.element = options.element;
newMap.element.dataset.internalId = options.id;
const elementBounds = await GoogleMap.getElementBounds(options.element);
options.config.width = elementBounds.width;
options.config.height = elementBounds.height;
options.config.x = elementBounds.x;
options.config.y = elementBounds.y;
options.config.devicePixelRatio = window.devicePixelRatio;
if (Capacitor.getPlatform() == 'android') {
newMap.initScrolling();
}
if (Capacitor.isNativePlatform()) {
options.element = {};
const getMapBounds = () => {
var _a, _b;
const mapRect = (_b = (_a = newMap.element) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) !== null && _b !== void 0 ? _b : {};
return {
x: mapRect.x,
y: mapRect.y,
width: mapRect.width,
height: mapRect.height,
};
};
const onDisplay = () => {
CapacitorGoogleMaps.onDisplay({
id: newMap.id,
mapBounds: getMapBounds(),
});
};
const onResize = () => {
CapacitorGoogleMaps.onResize({
id: newMap.id,
mapBounds: getMapBounds(),
});
};
const ionicPage = newMap.element.closest('.ion-page');
if (Capacitor.getPlatform() === 'ios' && ionicPage) {
ionicPage.addEventListener('ionViewWillEnter', () => {
setTimeout(() => {
onDisplay();
}, 100);
});
ionicPage.addEventListener('ionViewDidEnter', () => {
setTimeout(() => {
onDisplay();
}, 100);
});
}
const lastState = {
width: elementBounds.width,
height: elementBounds.height,
isHidden: false,
};
newMap.resizeObserver = new ResizeObserver(() => {
if (newMap.element != null) {
const mapRect = newMap.element.getBoundingClientRect();
const isHidden = mapRect.width === 0 && mapRect.height === 0;
if (!isHidden) {
if (lastState.isHidden) {
if (Capacitor.getPlatform() === 'ios' && !ionicPage) {
onDisplay();
}
}
else if (lastState.width !== mapRect.width || lastState.height !== mapRect.height) {
onResize();
}
}
lastState.width = mapRect.width;
lastState.height = mapRect.height;
lastState.isHidden = isHidden;
}
});
newMap.resizeObserver.observe(newMap.element);
}
// small delay to allow for iOS WKWebView to setup corresponding element sub-scroll views ???
await new Promise((resolve, reject) => {
setTimeout(async () => {
try {
await CapacitorGoogleMaps.create(options);
resolve(undefined);
}
catch (err) {
reject(err);
}
}, 200);
});
if (callback) {
const onMapReadyListener = await CapacitorGoogleMaps.addListener('onMapReady', (data) => {
if (data.mapId == newMap.id) {
callback(data);
onMapReadyListener.remove();
}
});
}
return newMap;
}
static async getElementBounds(element) {
return new Promise((resolve) => {
let elementBounds = element.getBoundingClientRect();
if (elementBounds.width == 0) {
let retries = 0;
const boundsInterval = setInterval(function () {
if (elementBounds.width == 0 && retries < 30) {
elementBounds = element.getBoundingClientRect();
retries++;
}
else {
if (retries == 30) {
console.warn('Map size could not be determined');
}
clearInterval(boundsInterval);
resolve(elementBounds);
}
}, 100);
}
else {
resolve(elementBounds);
}
});
}
/**
* Enable touch events on native map
*
* @returns void
*/
async enableTouch() {
return CapacitorGoogleMaps.enableTouch({
id: this.id,
});
}
/**
* Disable touch events on native map
*
* @returns void
*/
async disableTouch() {
return CapacitorGoogleMaps.disableTouch({
id: this.id,
});
}
/**
* Enable marker clustering
*
* @param minClusterSize - The minimum number of markers that can be clustered together.
* @defaultValue 4
*
* @returns void
*/
async enableClustering(minClusterSize) {
return CapacitorGoogleMaps.enableClustering({
id: this.id,
minClusterSize,
});
}
/**
* Disable marker clustering
*
* @returns void
*/
async disableClustering() {
return CapacitorGoogleMaps.disableClustering({
id: this.id,
});
}
/**
* Adds a tile overlay to the map
*
* @param tileOverlay
* @returns created tile overlay id
*/
async addTileOverlay(tileOverlay) {
const res = await CapacitorGoogleMaps.addTileOverlay({
id: this.id,
tileOverlay,
});
return res.id;
}
/**
* Removes a tile overlay from the map
*
* @param id of the tile overlay to remove from the map
* @returns void
*/
async removeTileOverlay(id) {
return CapacitorGoogleMaps.removeTileOverlay({
id: this.id,
tileOverlayId: id,
});
}
/**
* Adds a marker to the map
*
* @param marker
* @returns created marker id
*/
async addMarker(marker) {
const res = await CapacitorGoogleMaps.addMarker({
id: this.id,
marker,
});
return res.id;
}
/**
* Adds multiple markers to the map
*
* @param markers
* @returns array of created marker IDs
*/
async addMarkers(markers) {
const res = await CapacitorGoogleMaps.addMarkers({
id: this.id,
markers,
});
return res.ids;
}
/**
* Remove marker from the map
*
* @param id id of the marker to remove from the map
* @returns
*/
async removeMarker(id) {
return CapacitorGoogleMaps.removeMarker({
id: this.id,
markerId: id,
});
}
/**
* Remove markers from the map
*
* @param ids array of ids to remove from the map
* @returns
*/
async removeMarkers(ids) {
return CapacitorGoogleMaps.removeMarkers({
id: this.id,
markerIds: ids,
});
}
async addPolygons(polygons) {
const res = await CapacitorGoogleMaps.addPolygons({
id: this.id,
polygons,
});
return res.ids;
}
async addPolylines(polylines) {
const res = await CapacitorGoogleMaps.addPolylines({
id: this.id,
polylines,
});
return res.ids;
}
async removePolygons(ids) {
return CapacitorGoogleMaps.removePolygons({
id: this.id,
polygonIds: ids,
});
}
async addCircles(circles) {
const res = await CapacitorGoogleMaps.addCircles({
id: this.id,
circles,
});
return res.ids;
}
async removeCircles(ids) {
return CapacitorGoogleMaps.removeCircles({
id: this.id,
circleIds: ids,
});
}
async removePolylines(ids) {
return CapacitorGoogleMaps.removePolylines({
id: this.id,
polylineIds: ids,
});
}
/**
* Destroy the current instance of the map
*/
async destroy() {
var _a;
if (Capacitor.getPlatform() == 'android') {
this.disableScrolling();
}
if (Capacitor.isNativePlatform()) {
(_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
}
this.removeAllMapListeners();
return CapacitorGoogleMaps.destroy({
id: this.id,
});
}
/**
* Update the map camera configuration
*
* @param config
* @returns
*/
async setCamera(config) {
return CapacitorGoogleMaps.setCamera({
id: this.id,
config,
});
}
async getMapType() {
const { type } = await CapacitorGoogleMaps.getMapType({ id: this.id });
return MapType[type];
}
/**
* Sets the type of map tiles that should be displayed.
*
* @param mapType
* @returns
*/
async setMapType(mapType) {
return CapacitorGoogleMaps.setMapType({
id: this.id,
mapType,
});
}
/**
* Sets whether indoor maps are shown, where available.
*
* @param enabled
* @returns
*/
async enableIndoorMaps(enabled) {
return CapacitorGoogleMaps.enableIndoorMaps({
id: this.id,
enabled,
});
}
/**
* Controls whether the map is drawing traffic data, if available.
*
* @param enabled
* @returns
*/
async enableTrafficLayer(enabled) {
return CapacitorGoogleMaps.enableTrafficLayer({
id: this.id,
enabled,
});
}
/**
* Show accessibility elements for overlay objects, such as Marker and Polyline.
*
* Only available on iOS.
*
* @param enabled
* @returns
*/
async enableAccessibilityElements(enabled) {
return CapacitorGoogleMaps.enableAccessibilityElements({
id: this.id,
enabled,
});
}
/**
* Set whether the My Location dot and accuracy circle is enabled.
*
* @param enabled
* @returns
*/
async enableCurrentLocation(enabled) {
return CapacitorGoogleMaps.enableCurrentLocation({
id: this.id,
enabled,
});
}
/**
* Set padding on the 'visible' region of the view.
*
* @param padding
* @returns
*/
async setPadding(padding) {
return CapacitorGoogleMaps.setPadding({
id: this.id,
padding,
});
}
/**
* Get the map's current viewport latitude and longitude bounds.
*
* @returns {LatLngBounds}
*/
async getMapBounds() {
return new LatLngBounds(await CapacitorGoogleMaps.getMapBounds({
id: this.id,
}));
}
async fitBounds(bounds, padding) {
return CapacitorGoogleMaps.fitBounds({
id: this.id,
bounds,
padding,
});
}
initScrolling() {
const ionContents = document.getElementsByTagName('ion-content');
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (let i = 0; i < ionContents.length; i++) {
ionContents[i].scrollEvents = true;
}
window.addEventListener('ionScroll', this.handleScrollEvent);
window.addEventListener('scroll', this.handleScrollEvent);
window.addEventListener('resize', this.handleScrollEvent);
if (screen.orientation) {
screen.orientation.addEventListener('change', () => {
setTimeout(this.updateMapBounds, 500);
});
}
else {
window.addEventListener('orientationchange', () => {
setTimeout(this.updateMapBounds, 500);
});
}
}
disableScrolling() {
window.removeEventListener('ionScroll', this.handleScrollEvent);
window.removeEventListener('scroll', this.handleScrollEvent);
window.removeEventListener('resize', this.handleScrollEvent);
if (screen.orientation) {
screen.orientation.removeEventListener('change', () => {
setTimeout(this.updateMapBounds, 1000);
});
}
else {
window.removeEventListener('orientationchange', () => {
setTimeout(this.updateMapBounds, 1000);
});
}
}
updateMapBounds() {
if (this.element) {
const mapRect = this.element.getBoundingClientRect();
CapacitorGoogleMaps.onScroll({
id: this.id,
mapBounds: {
x: mapRect.x,
y: mapRect.y,
width: mapRect.width,
height: mapRect.height,
},
});
}
}
/*
private findContainerElement(): HTMLElement | null {
if (!this.element) {
return null;
}
let parentElement = this.element.parentElement;
while (parentElement !== null) {
if (window.getComputedStyle(parentElement).overflowY !== 'hidden') {
return parentElement;
}
parentElement = parentElement.parentElement;
}
return null;
}
*/
/**
* Set the event listener on the map for 'onCameraIdle' events.
*
* @param callback
* @returns
*/
async setOnCameraIdleListener(callback) {
if (this.onCameraIdleListener) {
this.onCameraIdleListener.remove();
}
if (callback) {
this.onCameraIdleListener = await CapacitorGoogleMaps.addListener('onCameraIdle', this.generateCallback(callback));
}
else {
this.onCameraIdleListener = undefined;
}
}
/**
* Set the event listener on the map for 'onBoundsChanged' events.
*
* @param callback
* @returns
*/
async setOnBoundsChangedListener(callback) {
if (this.onBoundsChangedListener) {
this.onBoundsChangedListener.remove();
}
if (callback) {
this.onBoundsChangedListener = await CapacitorGoogleMaps.addListener('onBoundsChanged', this.generateCallback(callback));
}
else {
this.onBoundsChangedListener = undefined;
}
}
/**
* Set the event listener on the map for 'onCameraMoveStarted' events.
*
* @param callback
* @returns
*/
async setOnCameraMoveStartedListener(callback) {
if (this.onCameraMoveStartedListener) {
this.onCameraMoveStartedListener.remove();
}
if (callback) {
this.onCameraMoveStartedListener = await CapacitorGoogleMaps.addListener('onCameraMoveStarted', this.generateCallback(callback));
}
else {
this.onCameraMoveStartedListener = undefined;
}
}
/**
* Set the event listener on the map for 'onClusterClick' events.
*
* @param callback
* @returns
*/
async setOnClusterClickListener(callback) {
if (this.onClusterClickListener) {
this.onClusterClickListener.remove();
}
if (callback) {
this.onClusterClickListener = await CapacitorGoogleMaps.addListener('onClusterClick', this.generateCallback(callback));
}
else {
this.onClusterClickListener = undefined;
}
}
/**
* Set the event listener on the map for 'onClusterInfoWindowClick' events.
*
* @param callback
* @returns
*/
async setOnClusterInfoWindowClickListener(callback) {
if (this.onClusterInfoWindowClickListener) {
this.onClusterInfoWindowClickListener.remove();
}
if (callback) {
this.onClusterInfoWindowClickListener = await CapacitorGoogleMaps.addListener('onClusterInfoWindowClick', this.generateCallback(callback));
}
else {
this.onClusterInfoWindowClickListener = undefined;
}
}
/**
* Set the event listener on the map for 'onInfoWindowClick' events.
*
* @param callback
* @returns
*/
async setOnInfoWindowClickListener(callback) {
if (this.onInfoWindowClickListener) {
this.onInfoWindowClickListener.remove();
}
if (callback) {
this.onInfoWindowClickListener = await CapacitorGoogleMaps.addListener('onInfoWindowClick', this.generateCallback(callback));
}
else {
this.onInfoWindowClickListener = undefined;
}
}
/**
* Set the event listener on the map for 'onMapClick' events.
*
* @param callback
* @returns
*/
async setOnMapClickListener(callback) {
if (this.onMapClickListener) {
this.onMapClickListener.remove();
}
if (callback) {
this.onMapClickListener = await CapacitorGoogleMaps.addListener('onMapClick', this.generateCallback(callback));
}
else {
this.onMapClickListener = undefined;
}
}
/**
* Set the event listener on the map for 'onPolygonClick' events.
*
* @param callback
* @returns
*/
async setOnPolygonClickListener(callback) {
if (this.onPolygonClickListener) {
this.onPolygonClickListener.remove();
}
if (callback) {
this.onPolygonClickListener = await CapacitorGoogleMaps.addListener('onPolygonClick', this.generateCallback(callback));
}
else {
this.onPolygonClickListener = undefined;
}
}
/**
* Set the event listener on the map for 'onCircleClick' events.
*
* @param callback
* @returns
*/
async setOnCircleClickListener(callback) {
if (this.onCircleClickListener)
[this.onCircleClickListener.remove()];
if (callback) {
this.onCircleClickListener = await CapacitorGoogleMaps.addListener('onCircleClick', this.generateCallback(callback));
}
else {
this.onCircleClickListener = undefined;
}
}
/**
* Set the event listener on the map for 'onMarkerClick' events.
*
* @param callback
* @returns
*/
async setOnMarkerClickListener(callback) {
if (this.onMarkerClickListener) {
this.onMarkerClickListener.remove();
}
if (callback) {
this.onMarkerClickListener = await CapacitorGoogleMaps.addListener('onMarkerClick', this.generateCallback(callback));
}
else {
this.onMarkerClickListener = undefined;
}
}
/**
* Set the event listener on the map for 'onPolylineClick' events.
*
* @param callback
* @returns
*/
async setOnPolylineClickListener(callback) {
if (this.onPolylineClickListener) {
this.onPolylineClickListener.remove();
}
if (callback) {
this.onPolylineClickListener = await CapacitorGoogleMaps.addListener('onPolylineClick', this.generateCallback(callback));
}
else {
this.onPolylineClickListener = undefined;
}
}
/**
* Set the event listener on the map for 'onMarkerDragStart' events.
*
* @param callback
* @returns
*/
async setOnMarkerDragStartListener(callback) {
if (this.onMarkerDragStartListener) {
this.onMarkerDragStartListener.remove();
}
if (callback) {
this.onMarkerDragStartListener = await CapacitorGoogleMaps.addListener('onMarkerDragStart', this.generateCallback(callback));
}
else {
this.onMarkerDragStartListener = undefined;
}
}
/**
* Set the event listener on the map for 'onMarkerDrag' events.
*
* @param callback
* @returns
*/
async setOnMarkerDragListener(callback) {
if (this.onMarkerDragListener) {
this.onMarkerDragListener.remove();
}
if (callback) {
this.onMarkerDragListener = await CapacitorGoogleMaps.addListener('onMarkerDrag', this.generateCallback(callback));
}
else {
this.onMarkerDragListener = undefined;
}
}
/**
* Set the event listener on the map for 'onMarkerDragEnd' events.
*
* @param callback
* @returns
*/
async setOnMarkerDragEndListener(callback) {
if (this.onMarkerDragEndListener) {
this.onMarkerDragEndListener.remove();
}
if (callback) {
this.onMarkerDragEndListener = await CapacitorGoogleMaps.addListener('onMarkerDragEnd', this.generateCallback(callback));
}
else {
this.onMarkerDragEndListener = undefined;
}
}
/**
* Set the event listener on the map for 'onMyLocationButtonClick' events.
*
* @param callback
* @returns
*/
async setOnMyLocationButtonClickListener(callback) {
if (this.onMyLocationButtonClickListener) {
this.onMyLocationButtonClickListener.remove();
}
if (callback) {
this.onMyLocationButtonClickListener = await CapacitorGoogleMaps.addListener('onMyLocationButtonClick', this.generateCallback(callback));
}
else {
this.onMyLocationButtonClickListener = undefined;
}
}
/**
* Set the event listener on the map for 'onMyLocationClick' events.
*
* @param callback
* @returns
*/
async setOnMyLocationClickListener(callback) {
if (this.onMyLocationClickListener) {
this.onMyLocationClickListener.remove();
}
if (callback) {
this.onMyLocationClickListener = await CapacitorGoogleMaps.addListener('onMyLocationClick', this.generateCallback(callback));
}
else {
this.onMyLocationClickListener = undefined;
}
}
/**
* Remove all event listeners on the map.
*
* @param callback
* @returns
*/
async removeAllMapListeners() {
if (this.onBoundsChangedListener) {
this.onBoundsChangedListener.remove();
this.onBoundsChangedListener = undefined;
}
if (this.onCameraIdleListener) {
this.onCameraIdleListener.remove();
this.onCameraIdleListener = undefined;
}
if (this.onCameraMoveStartedListener) {
this.onCameraMoveStartedListener.remove();
this.onCameraMoveStartedListener = undefined;
}
if (this.onClusterClickListener) {
this.onClusterClickListener.remove();
this.onClusterClickListener = undefined;
}
if (this.onClusterInfoWindowClickListener) {
this.onClusterInfoWindowClickListener.remove();
this.onClusterInfoWindowClickListener = undefined;
}
if (this.onInfoWindowClickListener) {
this.onInfoWindowClickListener.remove();
this.onInfoWindowClickListener = undefined;
}
if (this.onMapClickListener) {
this.onMapClickListener.remove();
this.onMapClickListener = undefined;
}
if (this.onPolylineClickListener) {
this.onPolylineClickListener.remove();
this.onPolylineClickListener = undefined;
}
if (this.onMarkerClickListener) {
this.onMarkerClickListener.remove();
this.onMarkerClickListener = undefined;
}
if (this.onPolygonClickListener) {
this.onPolygonClickListener.remove();
this.onPolygonClickListener = undefined;
}
if (this.onCircleClickListener) {
this.onCircleClickListener.remove();
this.onCircleClickListener = undefined;
}
if (this.onMarkerDragStartListener) {
this.onMarkerDragStartListener.remove();
this.onMarkerDragStartListener = undefined;
}
if (this.onMarkerDragListener) {
this.onMarkerDragListener.remove();
this.onMarkerDragListener = undefined;
}
if (this.onMarkerDragEndListener) {
this.onMarkerDragEndListener.remove();
this.onMarkerDragEndListener = undefined;
}
if (this.onMyLocationButtonClickListener) {
this.onMyLocationButtonClickListener.remove();
this.onMyLocationButtonClickListener = undefined;
}
if (this.onMyLocationClickListener) {
this.onMyLocationClickListener.remove();
this.onMyLocationClickListener = undefined;
}
}
generateCallback(callback) {
const mapId = this.id;
return (data) => {
if (data.mapId == mapId) {
callback(data);
}
};
}
}
//# sourceMappingURL=map.js.map

File diff suppressed because one or more lines are too long

565
node_modules/@capacitor/google-maps/dist/esm/web.js generated vendored Normal file
View File

@@ -0,0 +1,565 @@
import { WebPlugin } from '@capacitor/core';
import { MarkerClusterer, SuperClusterAlgorithm } from '@googlemaps/markerclusterer';
import { MapType, LatLngBounds } from './definitions';
export class CapacitorGoogleMapsWeb extends WebPlugin {
constructor() {
super(...arguments);
this.gMapsRef = undefined;
this.AdvancedMarkerElement = undefined;
this.PinElement = undefined;
this.maps = {};
this.currMarkerId = 0;
this.currTileOverlayId = 0;
this.currPolygonId = 0;
this.currCircleId = 0;
this.currPolylineId = 0;
this.currMapId = 0;
this.onClusterClickHandler = (_, cluster, map) => {
var _a;
const mapId = this.getIdFromMap(map);
const items = [];
if (cluster.markers != undefined && this.AdvancedMarkerElement) {
for (const marker of cluster.markers) {
if (marker instanceof this.AdvancedMarkerElement) {
const markerId = this.getIdFromMarker(mapId, marker);
const position = marker.position;
items.push({
markerId: markerId,
latitude: position.lat,
longitude: position.lng,
title: (_a = marker.title) !== null && _a !== void 0 ? _a : '',
snippet: '',
});
}
}
}
this.notifyListeners('onClusterClick', {
mapId: mapId,
latitude: cluster.position.lat,
longitude: cluster.position.lng,
size: cluster.count,
items: items,
});
};
}
getIdFromMap(map) {
for (const id in this.maps) {
if (this.maps[id].map == map) {
return id;
}
}
return '';
}
getIdFromMarker(mapId, marker) {
for (const id in this.maps[mapId].markers) {
if (this.maps[mapId].markers[id] == marker) {
return id;
}
}
return '';
}
async importGoogleLib(apiKey, region, language) {
if (this.gMapsRef === undefined) {
const lib = await import('@googlemaps/js-api-loader');
const loader = new lib.Loader({
apiKey: apiKey !== null && apiKey !== void 0 ? apiKey : '',
version: 'weekly',
libraries: ['places'],
language,
region,
});
const google = await loader.load();
this.gMapsRef = google.maps;
// Import marker library once
const { AdvancedMarkerElement, PinElement } = (await google.maps.importLibrary('marker'));
this.AdvancedMarkerElement = AdvancedMarkerElement;
this.PinElement = PinElement;
console.log('Loaded google maps API');
}
}
async enableTouch(_args) {
this.maps[_args.id].map.setOptions({ gestureHandling: 'auto' });
}
async disableTouch(_args) {
this.maps[_args.id].map.setOptions({ gestureHandling: 'none' });
}
async setCamera(_args) {
// Animation not supported yet...
this.maps[_args.id].map.moveCamera({
center: _args.config.coordinate,
heading: _args.config.bearing,
tilt: _args.config.angle,
zoom: _args.config.zoom,
});
}
async getMapType(_args) {
let type = this.maps[_args.id].map.getMapTypeId();
if (type !== undefined) {
if (type === 'roadmap') {
type = MapType.Normal;
}
return { type: `${type.charAt(0).toUpperCase()}${type.slice(1)}` };
}
throw new Error('Map type is undefined');
}
async setMapType(_args) {
let mapType = _args.mapType.toLowerCase();
if (_args.mapType === MapType.Normal) {
mapType = 'roadmap';
}
this.maps[_args.id].map.setMapTypeId(mapType);
}
async enableIndoorMaps() {
throw new Error('Method not supported on web.');
}
async enableTrafficLayer(_args) {
var _a;
const trafficLayer = (_a = this.maps[_args.id].trafficLayer) !== null && _a !== void 0 ? _a : new google.maps.TrafficLayer();
if (_args.enabled) {
trafficLayer.setMap(this.maps[_args.id].map);
this.maps[_args.id].trafficLayer = trafficLayer;
}
else if (this.maps[_args.id].trafficLayer) {
trafficLayer.setMap(null);
this.maps[_args.id].trafficLayer = undefined;
}
}
async enableAccessibilityElements() {
throw new Error('Method not supported on web.');
}
dispatchMapEvent() {
throw new Error('Method not supported on web.');
}
async enableCurrentLocation(_args) {
if (_args.enabled) {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
const pos = {
lat: position.coords.latitude,
lng: position.coords.longitude,
};
this.maps[_args.id].map.setCenter(pos);
this.notifyListeners('onMyLocationButtonClick', {});
this.notifyListeners('onMyLocationClick', {});
}, () => {
throw new Error('Geolocation not supported on web browser.');
});
}
else {
throw new Error('Geolocation not supported on web browser.');
}
}
}
async setPadding(_args) {
const bounds = this.maps[_args.id].map.getBounds();
if (bounds !== undefined) {
this.maps[_args.id].map.fitBounds(bounds, _args.padding);
}
}
async getMapBounds(_args) {
const bounds = this.maps[_args.id].map.getBounds();
if (!bounds) {
throw new Error('Google Map Bounds could not be found.');
}
return new LatLngBounds({
southwest: {
lat: bounds.getSouthWest().lat(),
lng: bounds.getSouthWest().lng(),
},
center: {
lat: bounds.getCenter().lat(),
lng: bounds.getCenter().lng(),
},
northeast: {
lat: bounds.getNorthEast().lat(),
lng: bounds.getNorthEast().lng(),
},
});
}
async fitBounds(_args) {
const map = this.maps[_args.id].map;
const bounds = this.getLatLngBounds(_args.bounds);
map.fitBounds(bounds, _args.padding);
}
async addTileOverlay(_args) {
const tileOverlay = _args.tileOverlay;
const map = this.maps[_args.id].map;
const id = '' + this.currTileOverlayId;
const customMapOverlay = new google.maps.ImageMapType({
getTileUrl: function (coord, zoom) {
return tileOverlay.url.replace('{x}', `${coord.x}`).replace('{y}', `${coord.y}`).replace('{z}', `${zoom}`);
},
tileSize: new google.maps.Size(256, 256),
opacity: tileOverlay.opacity,
});
this.maps[_args.id].tileOverlays[id] = customMapOverlay;
map.overlayMapTypes.push(customMapOverlay);
this.currTileOverlayId++;
return { id: id };
}
async removeTileOverlay(_args) {
const map = this.maps[_args.id].map;
if (!map) {
return;
}
for (let i = 0; i < map.overlayMapTypes.getLength(); i++) {
if (map.overlayMapTypes.getAt(i) === this.maps[_args.id].tileOverlays[_args.tileOverlayId]) {
map.overlayMapTypes.removeAt(i);
delete this.maps[_args.id].tileOverlays[_args.tileOverlayId];
break;
}
}
}
async addMarkers(_args) {
const markerIds = [];
const map = this.maps[_args.id];
for (const markerArgs of _args.markers) {
const advancedMarker = this.buildMarkerOpts(markerArgs, map.map);
const id = '' + this.currMarkerId;
map.markers[id] = advancedMarker;
await this.setMarkerListeners(_args.id, id, advancedMarker);
markerIds.push(id);
this.currMarkerId++;
}
return { ids: markerIds };
}
async addMarker(_args) {
const advancedMarker = this.buildMarkerOpts(_args.marker, this.maps[_args.id].map);
const id = '' + this.currMarkerId;
this.maps[_args.id].markers[id] = advancedMarker;
await this.setMarkerListeners(_args.id, id, advancedMarker);
this.currMarkerId++;
return { id: id };
}
async removeMarkers(_args) {
const map = this.maps[_args.id];
for (const id of _args.markerIds) {
if (map.markers[id]) {
map.markers[id].map = null;
delete map.markers[id];
}
}
}
async removeMarker(_args) {
if (this.maps[_args.id].markers[_args.markerId]) {
this.maps[_args.id].markers[_args.markerId].map = null;
delete this.maps[_args.id].markers[_args.markerId];
}
}
async addPolygons(args) {
const polygonIds = [];
const map = this.maps[args.id];
for (const polygonArgs of args.polygons) {
const polygon = new google.maps.Polygon(polygonArgs);
polygon.setMap(map.map);
const id = '' + this.currPolygonId;
this.maps[args.id].polygons[id] = polygon;
this.setPolygonListeners(args.id, id, polygon);
polygonIds.push(id);
this.currPolygonId++;
}
return { ids: polygonIds };
}
async removePolygons(args) {
const map = this.maps[args.id];
for (const id of args.polygonIds) {
map.polygons[id].setMap(null);
delete map.polygons[id];
}
}
async addCircles(args) {
const circleIds = [];
const map = this.maps[args.id];
for (const circleArgs of args.circles) {
const circle = new google.maps.Circle(circleArgs);
circle.setMap(map.map);
const id = '' + this.currCircleId;
this.maps[args.id].circles[id] = circle;
this.setCircleListeners(args.id, id, circle);
circleIds.push(id);
this.currCircleId++;
}
return { ids: circleIds };
}
async removeCircles(args) {
const map = this.maps[args.id];
for (const id of args.circleIds) {
map.circles[id].setMap(null);
delete map.circles[id];
}
}
async addPolylines(args) {
const lineIds = [];
const map = this.maps[args.id];
for (const polylineArgs of args.polylines) {
const polyline = new google.maps.Polyline(polylineArgs);
polyline.set('tag', polylineArgs.tag);
polyline.setMap(map.map);
const id = '' + this.currPolylineId;
this.maps[args.id].polylines[id] = polyline;
this.setPolylineListeners(args.id, id, polyline);
lineIds.push(id);
this.currPolylineId++;
}
return {
ids: lineIds,
};
}
async removePolylines(args) {
const map = this.maps[args.id];
for (const id of args.polylineIds) {
map.polylines[id].setMap(null);
delete map.polylines[id];
}
}
async enableClustering(_args) {
var _a;
const markers = [];
for (const id in this.maps[_args.id].markers) {
markers.push(this.maps[_args.id].markers[id]);
}
this.maps[_args.id].markerClusterer = new MarkerClusterer({
map: this.maps[_args.id].map,
markers: markers,
algorithm: new SuperClusterAlgorithm({
minPoints: (_a = _args.minClusterSize) !== null && _a !== void 0 ? _a : 4,
}),
onClusterClick: this.onClusterClickHandler,
});
}
async disableClustering(_args) {
const mapInstance = this.maps[_args.id];
if (mapInstance.markerClusterer) {
const markers = Object.values(mapInstance.markers);
mapInstance.markerClusterer.setMap(null);
mapInstance.markerClusterer = undefined;
for (const marker of markers) {
marker.map = mapInstance.map;
}
}
}
async onScroll() {
throw new Error('Method not supported on web.');
}
async onResize() {
throw new Error('Method not supported on web.');
}
async onDisplay() {
throw new Error('Method not supported on web.');
}
async create(_args) {
console.log(`Create map: ${_args.id}`);
await this.importGoogleLib(_args.apiKey, _args.region, _args.language);
// Ensure we have a Map ID for Advanced Markers
const config = Object.assign({}, _args.config);
if (!config.mapId) {
config.mapId = `capacitor_map_${this.currMapId++}`;
}
this.maps[_args.id] = {
map: new window.google.maps.Map(_args.element, config),
element: _args.element,
markers: {},
tileOverlays: {},
polygons: {},
circles: {},
polylines: {},
};
this.setMapListeners(_args.id);
}
async destroy(_args) {
console.log(`Destroy map: ${_args.id}`);
const mapItem = this.maps[_args.id];
mapItem.element.innerHTML = '';
mapItem.map.unbindAll();
delete this.maps[_args.id];
}
async mapBoundsContains(_args) {
const bounds = this.getLatLngBounds(_args.bounds);
const point = new google.maps.LatLng(_args.point.lat, _args.point.lng);
return { contains: bounds.contains(point) };
}
async mapBoundsExtend(_args) {
const bounds = this.getLatLngBounds(_args.bounds);
const point = new google.maps.LatLng(_args.point.lat, _args.point.lng);
bounds.extend(point);
const result = new LatLngBounds({
southwest: {
lat: bounds.getSouthWest().lat(),
lng: bounds.getSouthWest().lng(),
},
center: {
lat: bounds.getCenter().lat(),
lng: bounds.getCenter().lng(),
},
northeast: {
lat: bounds.getNorthEast().lat(),
lng: bounds.getNorthEast().lng(),
},
});
return { bounds: result };
}
getLatLngBounds(_args) {
return new google.maps.LatLngBounds(new google.maps.LatLng(_args.southwest.lat, _args.southwest.lng), new google.maps.LatLng(_args.northeast.lat, _args.northeast.lng));
}
async setCircleListeners(mapId, circleId, circle) {
circle.addListener('click', () => {
this.notifyListeners('onCircleClick', {
mapId: mapId,
circleId: circleId,
tag: circle.get('tag'),
});
});
}
async setPolygonListeners(mapId, polygonId, polygon) {
polygon.addListener('click', () => {
this.notifyListeners('onPolygonClick', {
mapId: mapId,
polygonId: polygonId,
tag: polygon.get('tag'),
});
});
}
async setPolylineListeners(mapId, polylineId, polyline) {
polyline.addListener('click', () => {
this.notifyListeners('onPolylineClick', {
mapId: mapId,
polylineId: polylineId,
tag: polyline.get('tag'),
});
});
}
async setMarkerListeners(mapId, markerId, marker) {
marker.addListener('click', () => {
var _a;
const position = marker.position;
this.notifyListeners('onMarkerClick', {
mapId: mapId,
markerId: markerId,
latitude: position.lat,
longitude: position.lng,
title: (_a = marker.title) !== null && _a !== void 0 ? _a : '',
snippet: '',
});
});
if (marker.gmpDraggable) {
marker.addListener('dragstart', () => {
var _a;
const position = marker.position;
this.notifyListeners('onMarkerDragStart', {
mapId: mapId,
markerId: markerId,
latitude: position.lat,
longitude: position.lng,
title: (_a = marker.title) !== null && _a !== void 0 ? _a : '',
snippet: '',
});
});
marker.addListener('drag', () => {
var _a;
const position = marker.position;
this.notifyListeners('onMarkerDrag', {
mapId: mapId,
markerId: markerId,
latitude: position.lat,
longitude: position.lng,
title: (_a = marker.title) !== null && _a !== void 0 ? _a : '',
snippet: '',
});
});
marker.addListener('dragend', () => {
var _a;
const position = marker.position;
this.notifyListeners('onMarkerDragEnd', {
mapId: mapId,
markerId: markerId,
latitude: position.lat,
longitude: position.lng,
title: (_a = marker.title) !== null && _a !== void 0 ? _a : '',
snippet: '',
});
});
}
}
async setMapListeners(mapId) {
const map = this.maps[mapId].map;
map.addListener('idle', async () => {
var _a, _b;
const bounds = await this.getMapBounds({ id: mapId });
this.notifyListeners('onCameraIdle', {
mapId: mapId,
bearing: map.getHeading(),
bounds: bounds,
latitude: (_a = map.getCenter()) === null || _a === void 0 ? void 0 : _a.lat(),
longitude: (_b = map.getCenter()) === null || _b === void 0 ? void 0 : _b.lng(),
tilt: map.getTilt(),
zoom: map.getZoom(),
});
});
map.addListener('center_changed', () => {
this.notifyListeners('onCameraMoveStarted', {
mapId: mapId,
isGesture: true,
});
});
map.addListener('bounds_changed', async () => {
var _a, _b;
const bounds = await this.getMapBounds({ id: mapId });
this.notifyListeners('onBoundsChanged', {
mapId: mapId,
bearing: map.getHeading(),
bounds: bounds,
latitude: (_a = map.getCenter()) === null || _a === void 0 ? void 0 : _a.lat(),
longitude: (_b = map.getCenter()) === null || _b === void 0 ? void 0 : _b.lng(),
tilt: map.getTilt(),
zoom: map.getZoom(),
});
});
map.addListener('click', (e) => {
var _a, _b;
this.notifyListeners('onMapClick', {
mapId: mapId,
latitude: (_a = e.latLng) === null || _a === void 0 ? void 0 : _a.lat(),
longitude: (_b = e.latLng) === null || _b === void 0 ? void 0 : _b.lng(),
});
});
this.notifyListeners('onMapReady', {
mapId: mapId,
});
}
buildMarkerOpts(marker, map) {
var _a;
if (!this.AdvancedMarkerElement || !this.PinElement) {
throw new Error('Marker library not loaded');
}
let content = undefined;
if (marker.iconUrl) {
const img = document.createElement('img');
img.src = marker.iconUrl;
if (marker.iconSize) {
img.style.width = `${marker.iconSize.width}px`;
img.style.height = `${marker.iconSize.height}px`;
}
content = img;
}
else {
const pinOptions = {
scale: (_a = marker.opacity) !== null && _a !== void 0 ? _a : 1,
glyph: marker.title,
background: marker.tintColor
? `rgb(${marker.tintColor.r}, ${marker.tintColor.g}, ${marker.tintColor.b})`
: undefined,
};
const pin = new this.PinElement(pinOptions);
content = pin.element;
}
const advancedMarker = new this.AdvancedMarkerElement({
position: marker.coordinate,
map: map,
content: content,
title: marker.title,
gmpDraggable: marker.draggable,
});
return advancedMarker;
}
}
//# sourceMappingURL=web.js.map

File diff suppressed because one or more lines are too long

1514
node_modules/@capacitor/google-maps/dist/plugin.cjs.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1498
node_modules/@capacitor/google-maps/dist/plugin.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,475 @@
/**
* An interface representing the viewports latitude and longitude bounds.
*/
export interface LatLngBoundsInterface {
southwest: LatLng;
center: LatLng;
northeast: LatLng;
}
export declare class LatLngBounds {
southwest: LatLng;
center: LatLng;
northeast: LatLng;
constructor(bounds: LatLngBoundsInterface);
contains(point: LatLng): Promise<boolean>;
extend(point: LatLng): Promise<LatLngBounds>;
}
/**
* An interface representing a pair of latitude and longitude coordinates.
*/
export interface LatLng {
/**
* Coordinate latitude, in degrees. This value is in the range [-90, 90].
*/
lat: number;
/**
* Coordinate longitude, in degrees. This value is in the range [-180, 180].
*/
lng: number;
}
export interface Size {
width: number;
height: number;
}
export interface Point {
x: number;
y: number;
}
/**
* For web, all the javascript Polygon options are available as
* Polygon extends google.maps.PolygonOptions.
* For iOS and Android only the config options declared on Polygon are available.
*/
export interface Polygon extends google.maps.PolygonOptions {
paths?: google.maps.MVCArray<any> | any[];
strokeColor?: string;
strokeOpacity?: number;
strokeWeight?: number;
fillColor?: string;
fillOpacity?: number;
geodesic?: boolean;
clickable?: boolean;
/**
* Title, a short description of the overlay. Some overlays, such as markers, will display the title on the map. The title is also the default accessibility text.
*
* Only available on iOS.
*/
title?: string;
tag?: string;
}
/**
* For web, all the javascript Circle options are available as
* Circle extends google.maps.CircleOptions.
* For iOS and Android only the config options declared on Circle are available.
*/
export interface Circle extends google.maps.CircleOptions {
fillColor?: string;
fillOpacity?: number;
strokeColor?: string;
strokeWeight?: number;
geodesic?: boolean;
clickable?: boolean;
/**
* Title, a short description of the overlay. Some overlays, such as markers, will display the title on the map. The title is also the default accessibility text.
*
* Only available on iOS.
*/
title?: string;
tag?: string;
}
/**
* For web, all the javascript Polyline options are available as
* Polyline extends google.maps.PolylineOptions.
* For iOS and Android only the config options declared on Polyline are available.
*/
export interface Polyline extends google.maps.PolylineOptions {
strokeColor?: string;
strokeOpacity?: number;
strokeWeight?: number;
geodesic?: boolean;
clickable?: boolean;
tag?: string;
/**
* Used to specify the color of one or more segments of a polyline. The styleSpans property is an array of StyleSpan objects.
* Setting the spans property is the preferred way to change the color of a polyline.
*
* Only on iOS and Android.
*/
styleSpans?: StyleSpan[];
}
/**
* Describes the style for some region of a polyline.
*/
export interface StyleSpan {
/**
* The stroke color. All CSS3 colors are supported except for extended named colors.
*/
color: string;
/**
* The length of this span in number of segments.
*/
segments?: number;
}
/**
* For web, all the javascript Google Maps options are available as
* GoogleMapConfig extends google.maps.MapOptions.
* For iOS and Android only the config options declared on GoogleMapConfig are available.
*/
export interface GoogleMapConfig extends google.maps.MapOptions {
/**
* Override width for native map.
*/
width?: number;
/**
* Override height for native map.
*/
height?: number;
/**
* Override absolute x coordinate position for native map.
*/
x?: number;
/**
* Override absolute y coordinate position for native map.
*/
y?: number;
/**
* Default location on the Earth towards which the camera points.
*/
center: LatLng;
/**
* Sets the zoom of the map.
*/
zoom: number;
/**
* Enables image-based lite mode on Android.
*
* @default false
*/
androidLiteMode?: boolean;
/**
* Override pixel ratio for native map.
*/
devicePixelRatio?: number;
/**
* Styles to apply to each of the default map types. Note that for
* satellite, hybrid and terrain modes,
* these styles will only apply to labels and geometry.
*
* @since 4.3.0
*/
styles?: google.maps.MapTypeStyle[] | null;
/**
* A map id associated with a specific map style or feature.
*
* [Use Map IDs](https://developers.google.com/maps/documentation/get-map-id)
*
* Only for Web.
*
* @since 5.4.0
*/
mapId?: string;
/**
* A map id associated with a specific map style or feature.
*
* [Use Map IDs](https://developers.google.com/maps/documentation/get-map-id)
*
* Only for Android.
*
* @since 5.4.0
*/
androidMapId?: string;
/**
* A map id associated with a specific map style or feature.
*
* [Use Map IDs](https://developers.google.com/maps/documentation/get-map-id)
*
* Only for iOS.
*
* @since 5.4.0
*/
iOSMapId?: string;
/**
* The maximum zoom level which will be displayed on the map. If omitted, or
* set to <code>null</code>, the maximum zoom from the current map type is
* used instead. Valid zoom values are numbers from zero up to the supported
* <a
* href="https://developers.google.com/maps/documentation/javascript/maxzoom">maximum
* zoom level</a>.
*/
maxZoom?: number | null;
/**
* The minimum zoom level which will be displayed on the map. If omitted, or
* set to <code>null</code>, the minimum zoom from the current map type is
* used instead. Valid zoom values are numbers from zero up to the supported
* <a
* href="https://developers.google.com/maps/documentation/javascript/maxzoom">maximum
* zoom level</a>.
*/
minZoom?: number | null;
/**
* The initial Map mapTypeId. Defaults to <code>ROADMAP</code>.
*/
mapTypeId?: string | null;
/**
* The heading for aerial imagery in degrees measured clockwise from
* cardinal direction North. Headings are snapped to the nearest available
* angle for which imagery is available.
*/
heading?: number | null;
/**
* Defines a boundary that restricts the area of the map accessible to
* users. When set, a user can only pan and zoom while the camera view stays
* inside the limits of the boundary.
*/
restriction?: google.maps.MapRestriction | null;
}
/**
* Configuration properties for a Google Map Camera
*/
export interface CameraConfig {
/**
* Location on the Earth towards which the camera points.
*/
coordinate?: LatLng;
/**
* Sets the zoom of the map.
*/
zoom?: number;
/**
* Bearing of the camera, in degrees clockwise from true north.
*
* @default 0
*/
bearing?: number;
/**
* The angle, in degrees, of the camera from the nadir (directly facing the Earth).
*
* The only allowed values are 0 and 45.
*
* @default 0
*/
angle?: number;
/**
* Animate the transition to the new Camera properties.
*
* @default false
*/
animate?: boolean;
/**
* This configuration option is not being used.
*/
animationDuration?: number;
}
export declare enum MapType {
/**
* Basic map.
*/
Normal = "Normal",
/**
* Satellite imagery with roads and labels.
*/
Hybrid = "Hybrid",
/**
* Satellite imagery with no labels.
*/
Satellite = "Satellite",
/**
* Topographic data.
*/
Terrain = "Terrain",
/**
* No base map tiles.
*/
None = "None"
}
/**
* Controls for setting padding on the 'visible' region of the view.
*/
export interface MapPadding {
top: number;
left: number;
right: number;
bottom: number;
}
/**
* A tile overlay is an image placed on top of your map at a specific zoom level. Available on iOS, Android and Web
*/
export interface TileOverlay {
/**
* A string representing the tile url. Should contain `{x}`, `{y}` and `{z}` so they can be replaced with actual values for x, y and zoom. Available on iOS, Android and Web
*
* @type {string}
*/
url: string;
/**
* The opacity of the tile overlay, between 0 (completely transparent) and 1 inclusive. Available on iOS, Android and Web
*
* @type {number | undefined}
* @default undefined
*/
opacity?: number;
/**
* Controls whether this tile overlay should be visible. Available only on Android
*
* @type {boolean | undefined}
* @default undefined
*/
visible?: boolean;
/**
* The zIndex of the tile overlay. Available on iOS and Android
*
* @type {number | undefined}
* @default undefined
*/
zIndex?: number;
}
/**
* A marker is an icon placed at a particular point on the map's surface.
*/
export interface Marker {
/**
* Marker position
*/
coordinate: LatLng;
/**
* Sets the opacity of the marker, between 0 (completely transparent) and 1 inclusive.
*
* @default 1
*/
opacity?: number;
/**
* Title, a short description of the overlay.
*/
title?: string;
/**
* Snippet text, shown beneath the title in the info window when selected.
*/
snippet?: string;
/**
* Controls whether this marker should be flat against the Earth's surface or a billboard facing the camera.
*
* @default false
*/
isFlat?: boolean;
/**
* Path to a marker icon to render. It can be relative to the web app public directory,
* or a https url of a remote marker icon.
*
* **SVGs are not supported on native platforms.**
*
* @usage
* ```typescript
* {
* ...
* iconUrl: 'assets/icon/pin.png',
* ...
* }
* ```
*
* @since 4.2.0
*/
iconUrl?: string;
/**
* Controls the scaled size of the marker image set in `iconUrl`.
*
* @since 4.2.0
*/
iconSize?: Size;
/**
* The position of the image within a sprite, if any. By default, the origin is located at the top left corner of the image .
*
* @since 4.2.0
*/
iconOrigin?: Point;
/**
* The position at which to anchor an image in correspondence to the location of the marker on the map. By default, the anchor is located along the center point of the bottom of the image.
*
* @since 4.2.0
*/
iconAnchor?: Point;
/**
* Customizes the color of the default marker image. Each value must be between 0 and 255.
*
* Only for iOS and Android.
*
* @since 4.2.0
*/
tintColor?: {
r: number;
g: number;
b: number;
a: number;
};
/**
* Controls whether this marker can be dragged interactively
*
* @default false
*/
draggable?: boolean;
/**
* Specifies the stack order of this marker, relative to other markers on the map.
* A marker with a high z-index is drawn on top of markers with lower z-indexes
*
* @default 0
*/
zIndex?: number;
}
/**
* The callback function to be called when map events are emitted.
*/
export type MapListenerCallback<T> = (data: T) => void;
export interface MapReadyCallbackData {
mapId: string;
}
export interface MarkerCallbackData {
markerId: string;
latitude: number;
longitude: number;
title: string;
snippet: string;
}
export interface PolylineCallbackData {
polylineId: string;
tag?: string;
}
export interface CameraIdleCallbackData {
mapId: string;
bounds: LatLngBounds;
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 PolygonClickCallbackData {
mapId: string;
polygonId: string;
tag?: string;
}
export interface CircleClickCallbackData {
mapId: string;
circleId: string;
tag?: string;
}
export interface MyLocationButtonClickCallbackData {
mapId: string;
}

View File

@@ -0,0 +1,211 @@
import type { Plugin } from '@capacitor/core';
import type { CameraConfig, Circle, GoogleMapConfig, LatLng, LatLngBounds, MapPadding, MapType, Marker, Polygon, Polyline, TileOverlay } 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;
/**
* The region parameter alters your application to serve different map tiles or bias the application (such as biasing geocoding results towards the region).
*
* Only available for web.
*/
region?: string;
/**
* The language parameter affects the names of controls, copyright notices, driving directions, and control labels, as well as the responses to service requests.
*
* Only available for web.
*/
language?: string;
}
export interface DestroyMapArgs {
id: string;
}
export interface RemoveMarkerArgs {
id: string;
markerId: string;
}
export interface RemoveMarkersArgs {
id: string;
markerIds: string[];
}
export interface AddMarkerArgs {
id: string;
marker: Marker;
}
export interface AddPolygonsArgs {
id: string;
polygons: Polygon[];
}
export interface RemovePolygonsArgs {
id: string;
polygonIds: string[];
}
export interface AddCirclesArgs {
id: string;
circles: Circle[];
}
export interface RemoveCirclesArgs {
id: string;
circleIds: string[];
}
export interface AddPolylinesArgs {
id: string;
polylines: Polyline[];
}
export interface RemovePolylinesArgs {
id: string;
polylineIds: string[];
}
export interface CameraArgs {
id: string;
config: CameraConfig;
}
export interface MapTypeArgs {
id: string;
mapType: MapType;
}
export interface IndoorMapArgs {
id: string;
enabled: boolean;
}
export interface RemoveTileOverlayArgs {
id: string;
tileOverlayId: string;
}
export interface AddTileOverlayArgs {
id: string;
tileOverlay: TileOverlay;
}
export interface TrafficLayerArgs {
id: string;
enabled: boolean;
}
export interface AccElementsArgs {
id: string;
enabled: boolean;
}
export interface PaddingArgs {
id: string;
padding: MapPadding;
}
export interface CurrentLocArgs {
id: string;
enabled: boolean;
}
export interface AddMarkersArgs {
id: string;
markers: Marker[];
}
export interface MapBoundsArgs {
id: string;
mapBounds: {
x: number;
y: number;
width: number;
height: number;
};
}
export interface MapBoundsContainsArgs {
bounds: LatLngBounds;
point: LatLng;
}
export type MapBoundsExtendArgs = MapBoundsContainsArgs;
export interface EnableClusteringArgs {
id: string;
minClusterSize?: number;
}
export interface FitBoundsArgs {
id: string;
bounds: LatLngBounds;
padding?: number;
}
export interface CapacitorGoogleMapsPlugin extends Plugin {
create(options: CreateMapArgs): Promise<void>;
enableTouch(args: {
id: string;
}): Promise<void>;
disableTouch(args: {
id: string;
}): Promise<void>;
addTileOverlay(args: AddTileOverlayArgs): Promise<{
id: string;
}>;
removeTileOverlay(args: RemoveTileOverlayArgs): Promise<void>;
addMarker(args: AddMarkerArgs): Promise<{
id: string;
}>;
addMarkers(args: AddMarkersArgs): Promise<{
ids: string[];
}>;
removeMarker(args: RemoveMarkerArgs): Promise<void>;
removeMarkers(args: RemoveMarkersArgs): Promise<void>;
addPolygons(args: AddPolygonsArgs): Promise<{
ids: string[];
}>;
removePolygons(args: RemovePolygonsArgs): Promise<void>;
addCircles(args: AddCirclesArgs): Promise<{
ids: string[];
}>;
removeCircles(args: RemoveCirclesArgs): Promise<void>;
addPolylines(args: AddPolylinesArgs): Promise<{
ids: string[];
}>;
removePolylines(args: RemovePolylinesArgs): Promise<void>;
enableClustering(args: EnableClusteringArgs): Promise<void>;
disableClustering(args: {
id: string;
}): Promise<void>;
destroy(args: DestroyMapArgs): Promise<void>;
setCamera(args: CameraArgs): Promise<void>;
getMapType(args: {
id: string;
}): Promise<{
type: string;
}>;
setMapType(args: MapTypeArgs): Promise<void>;
enableIndoorMaps(args: IndoorMapArgs): Promise<void>;
enableTrafficLayer(args: TrafficLayerArgs): Promise<void>;
enableAccessibilityElements(args: AccElementsArgs): Promise<void>;
enableCurrentLocation(args: CurrentLocArgs): Promise<void>;
setPadding(args: PaddingArgs): Promise<void>;
onScroll(args: MapBoundsArgs): Promise<void>;
onResize(args: MapBoundsArgs): Promise<void>;
onDisplay(args: MapBoundsArgs): Promise<void>;
dispatchMapEvent(args: {
id: string;
focus: boolean;
}): Promise<void>;
getMapBounds(args: {
id: string;
}): Promise<LatLngBounds>;
fitBounds(args: FitBoundsArgs): Promise<void>;
mapBoundsContains(args: MapBoundsContainsArgs): Promise<{
contains: boolean;
}>;
mapBoundsExtend(args: MapBoundsExtendArgs): Promise<{
bounds: LatLngBounds;
}>;
}
declare const CapacitorGoogleMaps: CapacitorGoogleMapsPlugin;
export { CapacitorGoogleMaps };

View File

@@ -0,0 +1,10 @@
import { LatLngBounds, MapType, Marker, Polygon, Circle, Polyline, StyleSpan } from './definitions';
import { GoogleMap } from './map';
export { GoogleMap, LatLngBounds, MapType, Marker, Polygon, Circle, Polyline, StyleSpan };
declare global {
export namespace JSX {
interface IntrinsicElements {
'capacitor-google-map': any;
}
}
}

View File

@@ -0,0 +1,360 @@
import type { CameraConfig, Marker, MapPadding, MapListenerCallback, MapReadyCallbackData, CameraIdleCallbackData, CameraMoveStartedCallbackData, ClusterClickCallbackData, MapClickCallbackData, MarkerClickCallbackData, MyLocationButtonClickCallbackData, Polygon, PolygonClickCallbackData, Circle, CircleClickCallbackData, Polyline, PolylineCallbackData, TileOverlay } from './definitions';
import { LatLngBounds, MapType } from './definitions';
import type { CreateMapArgs } from './implementation';
export interface GoogleMapInterface {
create(options: CreateMapArgs, callback?: MapListenerCallback<MapReadyCallbackData>): Promise<GoogleMap>;
enableTouch(): Promise<void>;
disableTouch(): Promise<void>;
enableClustering(
/**
* The minimum number of markers that can be clustered together. The default is 4 markers.
*/
minClusterSize?: number): Promise<void>;
disableClustering(): Promise<void>;
addTileOverlay(tileOverlay: TileOverlay): Promise<{
id: string;
}>;
removeTileOverlay(id: string): Promise<void>;
addMarker(marker: Marker): Promise<string>;
addMarkers(markers: Marker[]): Promise<string[]>;
removeMarker(id: string): Promise<void>;
removeMarkers(ids: string[]): Promise<void>;
addPolygons(polygons: Polygon[]): Promise<string[]>;
removePolygons(ids: string[]): Promise<void>;
addCircles(circles: Circle[]): Promise<string[]>;
removeCircles(ids: string[]): Promise<void>;
addPolylines(polylines: Polyline[]): Promise<string[]>;
removePolylines(ids: string[]): Promise<void>;
destroy(): Promise<void>;
setCamera(config: CameraConfig): Promise<void>;
/**
* Get current map type
*/
getMapType(): 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>;
/**
* Get the map's current viewport latitude and longitude bounds.
*
* @returns {LatLngBounds}
*/
getMapBounds(): Promise<LatLngBounds>;
/**
* Sets the map viewport to contain the given bounds.
* @param bounds The bounds to fit in the viewport.
* @param padding Optional padding to apply in pixels. The bounds will be fit in the part of the map that remains after padding is removed.
*/
fitBounds(bounds: LatLngBounds, padding?: number): Promise<void>;
setOnBoundsChangedListener(callback?: MapListenerCallback<CameraIdleCallbackData>): Promise<void>;
setOnCameraIdleListener(callback?: MapListenerCallback<CameraIdleCallbackData>): Promise<void>;
setOnCameraMoveStartedListener(callback?: MapListenerCallback<CameraMoveStartedCallbackData>): Promise<void>;
setOnClusterClickListener(callback?: MapListenerCallback<ClusterClickCallbackData>): Promise<void>;
setOnClusterInfoWindowClickListener(callback?: MapListenerCallback<ClusterClickCallbackData>): Promise<void>;
setOnInfoWindowClickListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
setOnMapClickListener(callback?: MapListenerCallback<MapClickCallbackData>): Promise<void>;
setOnMarkerClickListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
setOnPolygonClickListener(callback?: MapListenerCallback<PolygonClickCallbackData>): Promise<void>;
setOnCircleClickListener(callback?: MapListenerCallback<CircleClickCallbackData>): Promise<void>;
setOnPolylineClickListener(callback?: MapListenerCallback<PolylineCallbackData>): Promise<void>;
setOnMarkerDragStartListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
setOnMarkerDragListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
setOnMarkerDragEndListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
setOnMyLocationButtonClickListener(callback?: MapListenerCallback<MyLocationButtonClickCallbackData>): Promise<void>;
setOnMyLocationClickListener(callback?: MapListenerCallback<MapClickCallbackData>): Promise<void>;
}
export declare class GoogleMap {
private id;
private element;
private resizeObserver;
private onBoundsChangedListener?;
private onCameraIdleListener?;
private onCameraMoveStartedListener?;
private onClusterClickListener?;
private onClusterInfoWindowClickListener?;
private onInfoWindowClickListener?;
private onMapClickListener?;
private onPolylineClickListener?;
private onMarkerClickListener?;
private onPolygonClickListener?;
private onCircleClickListener?;
private onMarkerDragStartListener?;
private onMarkerDragListener?;
private onMarkerDragEndListener?;
private onMyLocationButtonClickListener?;
private onMyLocationClickListener?;
private constructor();
/**
* Creates a new instance of a Google Map
* @param options
* @param callback
* @returns GoogleMap
*/
static create(options: CreateMapArgs, callback?: MapListenerCallback<MapReadyCallbackData>): Promise<GoogleMap>;
private static getElementBounds;
/**
* Enable touch events on native map
*
* @returns void
*/
enableTouch(): Promise<void>;
/**
* Disable touch events on native map
*
* @returns void
*/
disableTouch(): Promise<void>;
/**
* Enable marker clustering
*
* @param minClusterSize - The minimum number of markers that can be clustered together.
* @defaultValue 4
*
* @returns void
*/
enableClustering(minClusterSize?: number): Promise<void>;
/**
* Disable marker clustering
*
* @returns void
*/
disableClustering(): Promise<void>;
/**
* Adds a tile overlay to the map
*
* @param tileOverlay
* @returns created tile overlay id
*/
addTileOverlay(tileOverlay: TileOverlay): Promise<string>;
/**
* Removes a tile overlay from the map
*
* @param id of the tile overlay to remove from the map
* @returns void
*/
removeTileOverlay(id: string): Promise<void>;
/**
* Adds a marker to the map
*
* @param marker
* @returns created marker id
*/
addMarker(marker: Marker): Promise<string>;
/**
* Adds multiple markers to the map
*
* @param markers
* @returns array of created marker IDs
*/
addMarkers(markers: Marker[]): Promise<string[]>;
/**
* Remove marker from the map
*
* @param id id of the marker to remove from the map
* @returns
*/
removeMarker(id: string): Promise<void>;
/**
* Remove markers from the map
*
* @param ids array of ids to remove from the map
* @returns
*/
removeMarkers(ids: string[]): Promise<void>;
addPolygons(polygons: Polygon[]): Promise<string[]>;
addPolylines(polylines: Polyline[]): Promise<string[]>;
removePolygons(ids: string[]): Promise<void>;
addCircles(circles: Circle[]): Promise<string[]>;
removeCircles(ids: string[]): Promise<void>;
removePolylines(ids: string[]): Promise<void>;
/**
* Destroy the current instance of the map
*/
destroy(): Promise<void>;
/**
* Update the map camera configuration
*
* @param config
* @returns
*/
setCamera(config: CameraConfig): Promise<void>;
getMapType(): Promise<MapType>;
/**
* Sets the type of map tiles that should be displayed.
*
* @param mapType
* @returns
*/
setMapType(mapType: MapType): Promise<void>;
/**
* Sets whether indoor maps are shown, where available.
*
* @param enabled
* @returns
*/
enableIndoorMaps(enabled: boolean): Promise<void>;
/**
* Controls whether the map is drawing traffic data, if available.
*
* @param enabled
* @returns
*/
enableTrafficLayer(enabled: boolean): Promise<void>;
/**
* Show accessibility elements for overlay objects, such as Marker and Polyline.
*
* Only available on iOS.
*
* @param enabled
* @returns
*/
enableAccessibilityElements(enabled: boolean): Promise<void>;
/**
* Set whether the My Location dot and accuracy circle is enabled.
*
* @param enabled
* @returns
*/
enableCurrentLocation(enabled: boolean): Promise<void>;
/**
* Set padding on the 'visible' region of the view.
*
* @param padding
* @returns
*/
setPadding(padding: MapPadding): Promise<void>;
/**
* Get the map's current viewport latitude and longitude bounds.
*
* @returns {LatLngBounds}
*/
getMapBounds(): Promise<LatLngBounds>;
fitBounds(bounds: LatLngBounds, padding?: number): Promise<void>;
initScrolling(): void;
disableScrolling(): void;
handleScrollEvent: () => void;
private updateMapBounds;
/**
* Set the event listener on the map for 'onCameraIdle' events.
*
* @param callback
* @returns
*/
setOnCameraIdleListener(callback?: MapListenerCallback<CameraIdleCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onBoundsChanged' events.
*
* @param callback
* @returns
*/
setOnBoundsChangedListener(callback?: MapListenerCallback<CameraIdleCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onCameraMoveStarted' events.
*
* @param callback
* @returns
*/
setOnCameraMoveStartedListener(callback?: MapListenerCallback<CameraMoveStartedCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onClusterClick' events.
*
* @param callback
* @returns
*/
setOnClusterClickListener(callback?: MapListenerCallback<ClusterClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onClusterInfoWindowClick' events.
*
* @param callback
* @returns
*/
setOnClusterInfoWindowClickListener(callback?: MapListenerCallback<ClusterClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onInfoWindowClick' events.
*
* @param callback
* @returns
*/
setOnInfoWindowClickListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMapClick' events.
*
* @param callback
* @returns
*/
setOnMapClickListener(callback?: MapListenerCallback<MapClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onPolygonClick' events.
*
* @param callback
* @returns
*/
setOnPolygonClickListener(callback?: MapListenerCallback<PolygonClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onCircleClick' events.
*
* @param callback
* @returns
*/
setOnCircleClickListener(callback?: MapListenerCallback<CircleClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMarkerClick' events.
*
* @param callback
* @returns
*/
setOnMarkerClickListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onPolylineClick' events.
*
* @param callback
* @returns
*/
setOnPolylineClickListener(callback?: MapListenerCallback<PolylineCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMarkerDragStart' events.
*
* @param callback
* @returns
*/
setOnMarkerDragStartListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMarkerDrag' events.
*
* @param callback
* @returns
*/
setOnMarkerDragListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMarkerDragEnd' events.
*
* @param callback
* @returns
*/
setOnMarkerDragEndListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMyLocationButtonClick' events.
*
* @param callback
* @returns
*/
setOnMyLocationButtonClickListener(callback?: MapListenerCallback<MyLocationButtonClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMyLocationClick' events.
*
* @param callback
* @returns
*/
setOnMyLocationClickListener(callback?: MapListenerCallback<MapClickCallbackData>): Promise<void>;
/**
* Remove all event listeners on the map.
*
* @param callback
* @returns
*/
removeAllMapListeners(): Promise<void>;
private generateCallback;
}

View File

@@ -0,0 +1,475 @@
/**
* An interface representing the viewports latitude and longitude bounds.
*/
export interface LatLngBoundsInterface {
southwest: LatLng;
center: LatLng;
northeast: LatLng;
}
export declare class LatLngBounds {
southwest: LatLng;
center: LatLng;
northeast: LatLng;
constructor(bounds: LatLngBoundsInterface);
contains(point: LatLng): Promise<boolean>;
extend(point: LatLng): Promise<LatLngBounds>;
}
/**
* An interface representing a pair of latitude and longitude coordinates.
*/
export interface LatLng {
/**
* Coordinate latitude, in degrees. This value is in the range [-90, 90].
*/
lat: number;
/**
* Coordinate longitude, in degrees. This value is in the range [-180, 180].
*/
lng: number;
}
export interface Size {
width: number;
height: number;
}
export interface Point {
x: number;
y: number;
}
/**
* For web, all the javascript Polygon options are available as
* Polygon extends google.maps.PolygonOptions.
* For iOS and Android only the config options declared on Polygon are available.
*/
export interface Polygon extends google.maps.PolygonOptions {
paths?: google.maps.MVCArray<any> | any[];
strokeColor?: string;
strokeOpacity?: number;
strokeWeight?: number;
fillColor?: string;
fillOpacity?: number;
geodesic?: boolean;
clickable?: boolean;
/**
* Title, a short description of the overlay. Some overlays, such as markers, will display the title on the map. The title is also the default accessibility text.
*
* Only available on iOS.
*/
title?: string;
tag?: string;
}
/**
* For web, all the javascript Circle options are available as
* Circle extends google.maps.CircleOptions.
* For iOS and Android only the config options declared on Circle are available.
*/
export interface Circle extends google.maps.CircleOptions {
fillColor?: string;
fillOpacity?: number;
strokeColor?: string;
strokeWeight?: number;
geodesic?: boolean;
clickable?: boolean;
/**
* Title, a short description of the overlay. Some overlays, such as markers, will display the title on the map. The title is also the default accessibility text.
*
* Only available on iOS.
*/
title?: string;
tag?: string;
}
/**
* For web, all the javascript Polyline options are available as
* Polyline extends google.maps.PolylineOptions.
* For iOS and Android only the config options declared on Polyline are available.
*/
export interface Polyline extends google.maps.PolylineOptions {
strokeColor?: string;
strokeOpacity?: number;
strokeWeight?: number;
geodesic?: boolean;
clickable?: boolean;
tag?: string;
/**
* Used to specify the color of one or more segments of a polyline. The styleSpans property is an array of StyleSpan objects.
* Setting the spans property is the preferred way to change the color of a polyline.
*
* Only on iOS and Android.
*/
styleSpans?: StyleSpan[];
}
/**
* Describes the style for some region of a polyline.
*/
export interface StyleSpan {
/**
* The stroke color. All CSS3 colors are supported except for extended named colors.
*/
color: string;
/**
* The length of this span in number of segments.
*/
segments?: number;
}
/**
* For web, all the javascript Google Maps options are available as
* GoogleMapConfig extends google.maps.MapOptions.
* For iOS and Android only the config options declared on GoogleMapConfig are available.
*/
export interface GoogleMapConfig extends google.maps.MapOptions {
/**
* Override width for native map.
*/
width?: number;
/**
* Override height for native map.
*/
height?: number;
/**
* Override absolute x coordinate position for native map.
*/
x?: number;
/**
* Override absolute y coordinate position for native map.
*/
y?: number;
/**
* Default location on the Earth towards which the camera points.
*/
center: LatLng;
/**
* Sets the zoom of the map.
*/
zoom: number;
/**
* Enables image-based lite mode on Android.
*
* @default false
*/
androidLiteMode?: boolean;
/**
* Override pixel ratio for native map.
*/
devicePixelRatio?: number;
/**
* Styles to apply to each of the default map types. Note that for
* satellite, hybrid and terrain modes,
* these styles will only apply to labels and geometry.
*
* @since 4.3.0
*/
styles?: google.maps.MapTypeStyle[] | null;
/**
* A map id associated with a specific map style or feature.
*
* [Use Map IDs](https://developers.google.com/maps/documentation/get-map-id)
*
* Only for Web.
*
* @since 5.4.0
*/
mapId?: string;
/**
* A map id associated with a specific map style or feature.
*
* [Use Map IDs](https://developers.google.com/maps/documentation/get-map-id)
*
* Only for Android.
*
* @since 5.4.0
*/
androidMapId?: string;
/**
* A map id associated with a specific map style or feature.
*
* [Use Map IDs](https://developers.google.com/maps/documentation/get-map-id)
*
* Only for iOS.
*
* @since 5.4.0
*/
iOSMapId?: string;
/**
* The maximum zoom level which will be displayed on the map. If omitted, or
* set to <code>null</code>, the maximum zoom from the current map type is
* used instead. Valid zoom values are numbers from zero up to the supported
* <a
* href="https://developers.google.com/maps/documentation/javascript/maxzoom">maximum
* zoom level</a>.
*/
maxZoom?: number | null;
/**
* The minimum zoom level which will be displayed on the map. If omitted, or
* set to <code>null</code>, the minimum zoom from the current map type is
* used instead. Valid zoom values are numbers from zero up to the supported
* <a
* href="https://developers.google.com/maps/documentation/javascript/maxzoom">maximum
* zoom level</a>.
*/
minZoom?: number | null;
/**
* The initial Map mapTypeId. Defaults to <code>ROADMAP</code>.
*/
mapTypeId?: string | null;
/**
* The heading for aerial imagery in degrees measured clockwise from
* cardinal direction North. Headings are snapped to the nearest available
* angle for which imagery is available.
*/
heading?: number | null;
/**
* Defines a boundary that restricts the area of the map accessible to
* users. When set, a user can only pan and zoom while the camera view stays
* inside the limits of the boundary.
*/
restriction?: google.maps.MapRestriction | null;
}
/**
* Configuration properties for a Google Map Camera
*/
export interface CameraConfig {
/**
* Location on the Earth towards which the camera points.
*/
coordinate?: LatLng;
/**
* Sets the zoom of the map.
*/
zoom?: number;
/**
* Bearing of the camera, in degrees clockwise from true north.
*
* @default 0
*/
bearing?: number;
/**
* The angle, in degrees, of the camera from the nadir (directly facing the Earth).
*
* The only allowed values are 0 and 45.
*
* @default 0
*/
angle?: number;
/**
* Animate the transition to the new Camera properties.
*
* @default false
*/
animate?: boolean;
/**
* This configuration option is not being used.
*/
animationDuration?: number;
}
export declare enum MapType {
/**
* Basic map.
*/
Normal = "Normal",
/**
* Satellite imagery with roads and labels.
*/
Hybrid = "Hybrid",
/**
* Satellite imagery with no labels.
*/
Satellite = "Satellite",
/**
* Topographic data.
*/
Terrain = "Terrain",
/**
* No base map tiles.
*/
None = "None"
}
/**
* Controls for setting padding on the 'visible' region of the view.
*/
export interface MapPadding {
top: number;
left: number;
right: number;
bottom: number;
}
/**
* A tile overlay is an image placed on top of your map at a specific zoom level. Available on iOS, Android and Web
*/
export interface TileOverlay {
/**
* A string representing the tile url. Should contain `{x}`, `{y}` and `{z}` so they can be replaced with actual values for x, y and zoom. Available on iOS, Android and Web
*
* @type {string}
*/
url: string;
/**
* The opacity of the tile overlay, between 0 (completely transparent) and 1 inclusive. Available on iOS, Android and Web
*
* @type {number | undefined}
* @default undefined
*/
opacity?: number;
/**
* Controls whether this tile overlay should be visible. Available only on Android
*
* @type {boolean | undefined}
* @default undefined
*/
visible?: boolean;
/**
* The zIndex of the tile overlay. Available on iOS and Android
*
* @type {number | undefined}
* @default undefined
*/
zIndex?: number;
}
/**
* A marker is an icon placed at a particular point on the map's surface.
*/
export interface Marker {
/**
* Marker position
*/
coordinate: LatLng;
/**
* Sets the opacity of the marker, between 0 (completely transparent) and 1 inclusive.
*
* @default 1
*/
opacity?: number;
/**
* Title, a short description of the overlay.
*/
title?: string;
/**
* Snippet text, shown beneath the title in the info window when selected.
*/
snippet?: string;
/**
* Controls whether this marker should be flat against the Earth's surface or a billboard facing the camera.
*
* @default false
*/
isFlat?: boolean;
/**
* Path to a marker icon to render. It can be relative to the web app public directory,
* or a https url of a remote marker icon.
*
* **SVGs are not supported on native platforms.**
*
* @usage
* ```typescript
* {
* ...
* iconUrl: 'assets/icon/pin.png',
* ...
* }
* ```
*
* @since 4.2.0
*/
iconUrl?: string;
/**
* Controls the scaled size of the marker image set in `iconUrl`.
*
* @since 4.2.0
*/
iconSize?: Size;
/**
* The position of the image within a sprite, if any. By default, the origin is located at the top left corner of the image .
*
* @since 4.2.0
*/
iconOrigin?: Point;
/**
* The position at which to anchor an image in correspondence to the location of the marker on the map. By default, the anchor is located along the center point of the bottom of the image.
*
* @since 4.2.0
*/
iconAnchor?: Point;
/**
* Customizes the color of the default marker image. Each value must be between 0 and 255.
*
* Only for iOS and Android.
*
* @since 4.2.0
*/
tintColor?: {
r: number;
g: number;
b: number;
a: number;
};
/**
* Controls whether this marker can be dragged interactively
*
* @default false
*/
draggable?: boolean;
/**
* Specifies the stack order of this marker, relative to other markers on the map.
* A marker with a high z-index is drawn on top of markers with lower z-indexes
*
* @default 0
*/
zIndex?: number;
}
/**
* The callback function to be called when map events are emitted.
*/
export type MapListenerCallback<T> = (data: T) => void;
export interface MapReadyCallbackData {
mapId: string;
}
export interface MarkerCallbackData {
markerId: string;
latitude: number;
longitude: number;
title: string;
snippet: string;
}
export interface PolylineCallbackData {
polylineId: string;
tag?: string;
}
export interface CameraIdleCallbackData {
mapId: string;
bounds: LatLngBounds;
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 PolygonClickCallbackData {
mapId: string;
polygonId: string;
tag?: string;
}
export interface CircleClickCallbackData {
mapId: string;
circleId: string;
tag?: string;
}
export interface MyLocationButtonClickCallbackData {
mapId: string;
}

View File

@@ -0,0 +1,211 @@
import { Plugin } from '@capacitor/core';
import { CameraConfig, Circle, GoogleMapConfig, LatLng, LatLngBounds, MapPadding, MapType, Marker, Polygon, Polyline, TileOverlay } 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;
/**
* The region parameter alters your application to serve different map tiles or bias the application (such as biasing geocoding results towards the region).
*
* Only available for web.
*/
region?: string;
/**
* The language parameter affects the names of controls, copyright notices, driving directions, and control labels, as well as the responses to service requests.
*
* Only available for web.
*/
language?: string;
}
export interface DestroyMapArgs {
id: string;
}
export interface RemoveMarkerArgs {
id: string;
markerId: string;
}
export interface RemoveMarkersArgs {
id: string;
markerIds: string[];
}
export interface AddMarkerArgs {
id: string;
marker: Marker;
}
export interface AddPolygonsArgs {
id: string;
polygons: Polygon[];
}
export interface RemovePolygonsArgs {
id: string;
polygonIds: string[];
}
export interface AddCirclesArgs {
id: string;
circles: Circle[];
}
export interface RemoveCirclesArgs {
id: string;
circleIds: string[];
}
export interface AddPolylinesArgs {
id: string;
polylines: Polyline[];
}
export interface RemovePolylinesArgs {
id: string;
polylineIds: string[];
}
export interface CameraArgs {
id: string;
config: CameraConfig;
}
export interface MapTypeArgs {
id: string;
mapType: MapType;
}
export interface IndoorMapArgs {
id: string;
enabled: boolean;
}
export interface RemoveTileOverlayArgs {
id: string;
tileOverlayId: string;
}
export interface AddTileOverlayArgs {
id: string;
tileOverlay: TileOverlay;
}
export interface TrafficLayerArgs {
id: string;
enabled: boolean;
}
export interface AccElementsArgs {
id: string;
enabled: boolean;
}
export interface PaddingArgs {
id: string;
padding: MapPadding;
}
export interface CurrentLocArgs {
id: string;
enabled: boolean;
}
export interface AddMarkersArgs {
id: string;
markers: Marker[];
}
export interface MapBoundsArgs {
id: string;
mapBounds: {
x: number;
y: number;
width: number;
height: number;
};
}
export interface MapBoundsContainsArgs {
bounds: LatLngBounds;
point: LatLng;
}
export type MapBoundsExtendArgs = MapBoundsContainsArgs;
export interface EnableClusteringArgs {
id: string;
minClusterSize?: number;
}
export interface FitBoundsArgs {
id: string;
bounds: LatLngBounds;
padding?: number;
}
export interface CapacitorGoogleMapsPlugin extends Plugin {
create(options: CreateMapArgs): Promise<void>;
enableTouch(args: {
id: string;
}): Promise<void>;
disableTouch(args: {
id: string;
}): Promise<void>;
addTileOverlay(args: AddTileOverlayArgs): Promise<{
id: string;
}>;
removeTileOverlay(args: RemoveTileOverlayArgs): Promise<void>;
addMarker(args: AddMarkerArgs): Promise<{
id: string;
}>;
addMarkers(args: AddMarkersArgs): Promise<{
ids: string[];
}>;
removeMarker(args: RemoveMarkerArgs): Promise<void>;
removeMarkers(args: RemoveMarkersArgs): Promise<void>;
addPolygons(args: AddPolygonsArgs): Promise<{
ids: string[];
}>;
removePolygons(args: RemovePolygonsArgs): Promise<void>;
addCircles(args: AddCirclesArgs): Promise<{
ids: string[];
}>;
removeCircles(args: RemoveCirclesArgs): Promise<void>;
addPolylines(args: AddPolylinesArgs): Promise<{
ids: string[];
}>;
removePolylines(args: RemovePolylinesArgs): Promise<void>;
enableClustering(args: EnableClusteringArgs): Promise<void>;
disableClustering(args: {
id: string;
}): Promise<void>;
destroy(args: DestroyMapArgs): Promise<void>;
setCamera(args: CameraArgs): Promise<void>;
getMapType(args: {
id: string;
}): Promise<{
type: string;
}>;
setMapType(args: MapTypeArgs): Promise<void>;
enableIndoorMaps(args: IndoorMapArgs): Promise<void>;
enableTrafficLayer(args: TrafficLayerArgs): Promise<void>;
enableAccessibilityElements(args: AccElementsArgs): Promise<void>;
enableCurrentLocation(args: CurrentLocArgs): Promise<void>;
setPadding(args: PaddingArgs): Promise<void>;
onScroll(args: MapBoundsArgs): Promise<void>;
onResize(args: MapBoundsArgs): Promise<void>;
onDisplay(args: MapBoundsArgs): Promise<void>;
dispatchMapEvent(args: {
id: string;
focus: boolean;
}): Promise<void>;
getMapBounds(args: {
id: string;
}): Promise<LatLngBounds>;
fitBounds(args: FitBoundsArgs): Promise<void>;
mapBoundsContains(args: MapBoundsContainsArgs): Promise<{
contains: boolean;
}>;
mapBoundsExtend(args: MapBoundsExtendArgs): Promise<{
bounds: LatLngBounds;
}>;
}
declare const CapacitorGoogleMaps: CapacitorGoogleMapsPlugin;
export { CapacitorGoogleMaps };

View File

@@ -0,0 +1,10 @@
import { LatLngBounds, MapType, Marker, Polygon, Circle, Polyline, StyleSpan } from './definitions';
import { GoogleMap } from './map';
export { GoogleMap, LatLngBounds, MapType, Marker, Polygon, Circle, Polyline, StyleSpan };
declare global {
export namespace JSX {
interface IntrinsicElements {
'capacitor-google-map': any;
}
}
}

View File

@@ -0,0 +1,360 @@
import { CameraConfig, Marker, MapPadding, MapListenerCallback, MapReadyCallbackData, CameraIdleCallbackData, CameraMoveStartedCallbackData, ClusterClickCallbackData, MapClickCallbackData, MarkerClickCallbackData, MyLocationButtonClickCallbackData, Polygon, PolygonClickCallbackData, Circle, CircleClickCallbackData, Polyline, PolylineCallbackData, TileOverlay } from './definitions';
import { LatLngBounds, MapType } from './definitions';
import { CreateMapArgs } from './implementation';
export interface GoogleMapInterface {
create(options: CreateMapArgs, callback?: MapListenerCallback<MapReadyCallbackData>): Promise<GoogleMap>;
enableTouch(): Promise<void>;
disableTouch(): Promise<void>;
enableClustering(
/**
* The minimum number of markers that can be clustered together. The default is 4 markers.
*/
minClusterSize?: number): Promise<void>;
disableClustering(): Promise<void>;
addTileOverlay(tileOverlay: TileOverlay): Promise<{
id: string;
}>;
removeTileOverlay(id: string): Promise<void>;
addMarker(marker: Marker): Promise<string>;
addMarkers(markers: Marker[]): Promise<string[]>;
removeMarker(id: string): Promise<void>;
removeMarkers(ids: string[]): Promise<void>;
addPolygons(polygons: Polygon[]): Promise<string[]>;
removePolygons(ids: string[]): Promise<void>;
addCircles(circles: Circle[]): Promise<string[]>;
removeCircles(ids: string[]): Promise<void>;
addPolylines(polylines: Polyline[]): Promise<string[]>;
removePolylines(ids: string[]): Promise<void>;
destroy(): Promise<void>;
setCamera(config: CameraConfig): Promise<void>;
/**
* Get current map type
*/
getMapType(): 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>;
/**
* Get the map's current viewport latitude and longitude bounds.
*
* @returns {LatLngBounds}
*/
getMapBounds(): Promise<LatLngBounds>;
/**
* Sets the map viewport to contain the given bounds.
* @param bounds The bounds to fit in the viewport.
* @param padding Optional padding to apply in pixels. The bounds will be fit in the part of the map that remains after padding is removed.
*/
fitBounds(bounds: LatLngBounds, padding?: number): Promise<void>;
setOnBoundsChangedListener(callback?: MapListenerCallback<CameraIdleCallbackData>): Promise<void>;
setOnCameraIdleListener(callback?: MapListenerCallback<CameraIdleCallbackData>): Promise<void>;
setOnCameraMoveStartedListener(callback?: MapListenerCallback<CameraMoveStartedCallbackData>): Promise<void>;
setOnClusterClickListener(callback?: MapListenerCallback<ClusterClickCallbackData>): Promise<void>;
setOnClusterInfoWindowClickListener(callback?: MapListenerCallback<ClusterClickCallbackData>): Promise<void>;
setOnInfoWindowClickListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
setOnMapClickListener(callback?: MapListenerCallback<MapClickCallbackData>): Promise<void>;
setOnMarkerClickListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
setOnPolygonClickListener(callback?: MapListenerCallback<PolygonClickCallbackData>): Promise<void>;
setOnCircleClickListener(callback?: MapListenerCallback<CircleClickCallbackData>): Promise<void>;
setOnPolylineClickListener(callback?: MapListenerCallback<PolylineCallbackData>): Promise<void>;
setOnMarkerDragStartListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
setOnMarkerDragListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
setOnMarkerDragEndListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
setOnMyLocationButtonClickListener(callback?: MapListenerCallback<MyLocationButtonClickCallbackData>): Promise<void>;
setOnMyLocationClickListener(callback?: MapListenerCallback<MapClickCallbackData>): Promise<void>;
}
export declare class GoogleMap {
private id;
private element;
private resizeObserver;
private onBoundsChangedListener?;
private onCameraIdleListener?;
private onCameraMoveStartedListener?;
private onClusterClickListener?;
private onClusterInfoWindowClickListener?;
private onInfoWindowClickListener?;
private onMapClickListener?;
private onPolylineClickListener?;
private onMarkerClickListener?;
private onPolygonClickListener?;
private onCircleClickListener?;
private onMarkerDragStartListener?;
private onMarkerDragListener?;
private onMarkerDragEndListener?;
private onMyLocationButtonClickListener?;
private onMyLocationClickListener?;
private constructor();
/**
* Creates a new instance of a Google Map
* @param options
* @param callback
* @returns GoogleMap
*/
static create(options: CreateMapArgs, callback?: MapListenerCallback<MapReadyCallbackData>): Promise<GoogleMap>;
private static getElementBounds;
/**
* Enable touch events on native map
*
* @returns void
*/
enableTouch(): Promise<void>;
/**
* Disable touch events on native map
*
* @returns void
*/
disableTouch(): Promise<void>;
/**
* Enable marker clustering
*
* @param minClusterSize - The minimum number of markers that can be clustered together.
* @defaultValue 4
*
* @returns void
*/
enableClustering(minClusterSize?: number): Promise<void>;
/**
* Disable marker clustering
*
* @returns void
*/
disableClustering(): Promise<void>;
/**
* Adds a tile overlay to the map
*
* @param tileOverlay
* @returns created tile overlay id
*/
addTileOverlay(tileOverlay: TileOverlay): Promise<string>;
/**
* Removes a tile overlay from the map
*
* @param id of the tile overlay to remove from the map
* @returns void
*/
removeTileOverlay(id: string): Promise<void>;
/**
* Adds a marker to the map
*
* @param marker
* @returns created marker id
*/
addMarker(marker: Marker): Promise<string>;
/**
* Adds multiple markers to the map
*
* @param markers
* @returns array of created marker IDs
*/
addMarkers(markers: Marker[]): Promise<string[]>;
/**
* Remove marker from the map
*
* @param id id of the marker to remove from the map
* @returns
*/
removeMarker(id: string): Promise<void>;
/**
* Remove markers from the map
*
* @param ids array of ids to remove from the map
* @returns
*/
removeMarkers(ids: string[]): Promise<void>;
addPolygons(polygons: Polygon[]): Promise<string[]>;
addPolylines(polylines: Polyline[]): Promise<string[]>;
removePolygons(ids: string[]): Promise<void>;
addCircles(circles: Circle[]): Promise<string[]>;
removeCircles(ids: string[]): Promise<void>;
removePolylines(ids: string[]): Promise<void>;
/**
* Destroy the current instance of the map
*/
destroy(): Promise<void>;
/**
* Update the map camera configuration
*
* @param config
* @returns
*/
setCamera(config: CameraConfig): Promise<void>;
getMapType(): Promise<MapType>;
/**
* Sets the type of map tiles that should be displayed.
*
* @param mapType
* @returns
*/
setMapType(mapType: MapType): Promise<void>;
/**
* Sets whether indoor maps are shown, where available.
*
* @param enabled
* @returns
*/
enableIndoorMaps(enabled: boolean): Promise<void>;
/**
* Controls whether the map is drawing traffic data, if available.
*
* @param enabled
* @returns
*/
enableTrafficLayer(enabled: boolean): Promise<void>;
/**
* Show accessibility elements for overlay objects, such as Marker and Polyline.
*
* Only available on iOS.
*
* @param enabled
* @returns
*/
enableAccessibilityElements(enabled: boolean): Promise<void>;
/**
* Set whether the My Location dot and accuracy circle is enabled.
*
* @param enabled
* @returns
*/
enableCurrentLocation(enabled: boolean): Promise<void>;
/**
* Set padding on the 'visible' region of the view.
*
* @param padding
* @returns
*/
setPadding(padding: MapPadding): Promise<void>;
/**
* Get the map's current viewport latitude and longitude bounds.
*
* @returns {LatLngBounds}
*/
getMapBounds(): Promise<LatLngBounds>;
fitBounds(bounds: LatLngBounds, padding?: number): Promise<void>;
initScrolling(): void;
disableScrolling(): void;
handleScrollEvent: () => void;
private updateMapBounds;
/**
* Set the event listener on the map for 'onCameraIdle' events.
*
* @param callback
* @returns
*/
setOnCameraIdleListener(callback?: MapListenerCallback<CameraIdleCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onBoundsChanged' events.
*
* @param callback
* @returns
*/
setOnBoundsChangedListener(callback?: MapListenerCallback<CameraIdleCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onCameraMoveStarted' events.
*
* @param callback
* @returns
*/
setOnCameraMoveStartedListener(callback?: MapListenerCallback<CameraMoveStartedCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onClusterClick' events.
*
* @param callback
* @returns
*/
setOnClusterClickListener(callback?: MapListenerCallback<ClusterClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onClusterInfoWindowClick' events.
*
* @param callback
* @returns
*/
setOnClusterInfoWindowClickListener(callback?: MapListenerCallback<ClusterClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onInfoWindowClick' events.
*
* @param callback
* @returns
*/
setOnInfoWindowClickListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMapClick' events.
*
* @param callback
* @returns
*/
setOnMapClickListener(callback?: MapListenerCallback<MapClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onPolygonClick' events.
*
* @param callback
* @returns
*/
setOnPolygonClickListener(callback?: MapListenerCallback<PolygonClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onCircleClick' events.
*
* @param callback
* @returns
*/
setOnCircleClickListener(callback?: MapListenerCallback<CircleClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMarkerClick' events.
*
* @param callback
* @returns
*/
setOnMarkerClickListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onPolylineClick' events.
*
* @param callback
* @returns
*/
setOnPolylineClickListener(callback?: MapListenerCallback<PolylineCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMarkerDragStart' events.
*
* @param callback
* @returns
*/
setOnMarkerDragStartListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMarkerDrag' events.
*
* @param callback
* @returns
*/
setOnMarkerDragListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMarkerDragEnd' events.
*
* @param callback
* @returns
*/
setOnMarkerDragEndListener(callback?: MapListenerCallback<MarkerClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMyLocationButtonClick' events.
*
* @param callback
* @returns
*/
setOnMyLocationButtonClickListener(callback?: MapListenerCallback<MyLocationButtonClickCallbackData>): Promise<void>;
/**
* Set the event listener on the map for 'onMyLocationClick' events.
*
* @param callback
* @returns
*/
setOnMyLocationClickListener(callback?: MapListenerCallback<MapClickCallbackData>): Promise<void>;
/**
* Remove all event listeners on the map.
*
* @param callback
* @returns
*/
removeAllMapListeners(): Promise<void>;
private generateCallback;
}

View File

@@ -0,0 +1,88 @@
import { WebPlugin } from '@capacitor/core';
import { LatLngBounds } from './definitions';
import { AddTileOverlayArgs, AddMarkerArgs, CameraArgs, AddMarkersArgs, CapacitorGoogleMapsPlugin, CreateMapArgs, CurrentLocArgs, DestroyMapArgs, MapTypeArgs, PaddingArgs, RemoveMarkerArgs, TrafficLayerArgs, RemoveMarkersArgs, MapBoundsContainsArgs, EnableClusteringArgs, FitBoundsArgs, MapBoundsExtendArgs, AddPolygonsArgs, RemovePolygonsArgs, AddCirclesArgs, RemoveCirclesArgs, AddPolylinesArgs, RemovePolylinesArgs, RemoveTileOverlayArgs } from './implementation';
export declare class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogleMapsPlugin {
private gMapsRef;
private AdvancedMarkerElement;
private PinElement;
private maps;
private currMarkerId;
private currTileOverlayId;
private currPolygonId;
private currCircleId;
private currPolylineId;
private currMapId;
private onClusterClickHandler;
private getIdFromMap;
private getIdFromMarker;
private importGoogleLib;
enableTouch(_args: {
id: string;
}): Promise<void>;
disableTouch(_args: {
id: string;
}): Promise<void>;
setCamera(_args: CameraArgs): Promise<void>;
getMapType(_args: {
id: string;
}): Promise<{
type: string;
}>;
setMapType(_args: MapTypeArgs): Promise<void>;
enableIndoorMaps(): Promise<void>;
enableTrafficLayer(_args: TrafficLayerArgs): Promise<void>;
enableAccessibilityElements(): Promise<void>;
dispatchMapEvent(): Promise<void>;
enableCurrentLocation(_args: CurrentLocArgs): Promise<void>;
setPadding(_args: PaddingArgs): Promise<void>;
getMapBounds(_args: {
id: string;
}): Promise<LatLngBounds>;
fitBounds(_args: FitBoundsArgs): Promise<void>;
addTileOverlay(_args: AddTileOverlayArgs): Promise<{
id: string;
}>;
removeTileOverlay(_args: RemoveTileOverlayArgs): Promise<void>;
addMarkers(_args: AddMarkersArgs): Promise<{
ids: string[];
}>;
addMarker(_args: AddMarkerArgs): Promise<{
id: string;
}>;
removeMarkers(_args: RemoveMarkersArgs): Promise<void>;
removeMarker(_args: RemoveMarkerArgs): Promise<void>;
addPolygons(args: AddPolygonsArgs): Promise<{
ids: string[];
}>;
removePolygons(args: RemovePolygonsArgs): Promise<void>;
addCircles(args: AddCirclesArgs): Promise<{
ids: string[];
}>;
removeCircles(args: RemoveCirclesArgs): Promise<void>;
addPolylines(args: AddPolylinesArgs): Promise<{
ids: string[];
}>;
removePolylines(args: RemovePolylinesArgs): Promise<void>;
enableClustering(_args: EnableClusteringArgs): Promise<void>;
disableClustering(_args: {
id: string;
}): Promise<void>;
onScroll(): Promise<void>;
onResize(): Promise<void>;
onDisplay(): Promise<void>;
create(_args: CreateMapArgs): Promise<void>;
destroy(_args: DestroyMapArgs): Promise<void>;
mapBoundsContains(_args: MapBoundsContainsArgs): Promise<{
contains: boolean;
}>;
mapBoundsExtend(_args: MapBoundsExtendArgs): Promise<{
bounds: LatLngBounds;
}>;
private getLatLngBounds;
setCircleListeners(mapId: string, circleId: string, circle: google.maps.Circle): Promise<void>;
setPolygonListeners(mapId: string, polygonId: string, polygon: google.maps.Polygon): Promise<void>;
setPolylineListeners(mapId: string, polylineId: string, polyline: google.maps.Polyline): Promise<void>;
setMarkerListeners(mapId: string, markerId: string, marker: google.maps.marker.AdvancedMarkerElement): Promise<void>;
setMapListeners(mapId: string): Promise<void>;
private buildMarkerOpts;
}

View File

@@ -0,0 +1,88 @@
import { WebPlugin } from '@capacitor/core';
import { LatLngBounds } from './definitions';
import type { AddTileOverlayArgs, AddMarkerArgs, CameraArgs, AddMarkersArgs, CapacitorGoogleMapsPlugin, CreateMapArgs, CurrentLocArgs, DestroyMapArgs, MapTypeArgs, PaddingArgs, RemoveMarkerArgs, TrafficLayerArgs, RemoveMarkersArgs, MapBoundsContainsArgs, EnableClusteringArgs, FitBoundsArgs, MapBoundsExtendArgs, AddPolygonsArgs, RemovePolygonsArgs, AddCirclesArgs, RemoveCirclesArgs, AddPolylinesArgs, RemovePolylinesArgs, RemoveTileOverlayArgs } from './implementation';
export declare class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogleMapsPlugin {
private gMapsRef;
private AdvancedMarkerElement;
private PinElement;
private maps;
private currMarkerId;
private currTileOverlayId;
private currPolygonId;
private currCircleId;
private currPolylineId;
private currMapId;
private onClusterClickHandler;
private getIdFromMap;
private getIdFromMarker;
private importGoogleLib;
enableTouch(_args: {
id: string;
}): Promise<void>;
disableTouch(_args: {
id: string;
}): Promise<void>;
setCamera(_args: CameraArgs): Promise<void>;
getMapType(_args: {
id: string;
}): Promise<{
type: string;
}>;
setMapType(_args: MapTypeArgs): Promise<void>;
enableIndoorMaps(): Promise<void>;
enableTrafficLayer(_args: TrafficLayerArgs): Promise<void>;
enableAccessibilityElements(): Promise<void>;
dispatchMapEvent(): Promise<void>;
enableCurrentLocation(_args: CurrentLocArgs): Promise<void>;
setPadding(_args: PaddingArgs): Promise<void>;
getMapBounds(_args: {
id: string;
}): Promise<LatLngBounds>;
fitBounds(_args: FitBoundsArgs): Promise<void>;
addTileOverlay(_args: AddTileOverlayArgs): Promise<{
id: string;
}>;
removeTileOverlay(_args: RemoveTileOverlayArgs): Promise<void>;
addMarkers(_args: AddMarkersArgs): Promise<{
ids: string[];
}>;
addMarker(_args: AddMarkerArgs): Promise<{
id: string;
}>;
removeMarkers(_args: RemoveMarkersArgs): Promise<void>;
removeMarker(_args: RemoveMarkerArgs): Promise<void>;
addPolygons(args: AddPolygonsArgs): Promise<{
ids: string[];
}>;
removePolygons(args: RemovePolygonsArgs): Promise<void>;
addCircles(args: AddCirclesArgs): Promise<{
ids: string[];
}>;
removeCircles(args: RemoveCirclesArgs): Promise<void>;
addPolylines(args: AddPolylinesArgs): Promise<{
ids: string[];
}>;
removePolylines(args: RemovePolylinesArgs): Promise<void>;
enableClustering(_args: EnableClusteringArgs): Promise<void>;
disableClustering(_args: {
id: string;
}): Promise<void>;
onScroll(): Promise<void>;
onResize(): Promise<void>;
onDisplay(): Promise<void>;
create(_args: CreateMapArgs): Promise<void>;
destroy(_args: DestroyMapArgs): Promise<void>;
mapBoundsContains(_args: MapBoundsContainsArgs): Promise<{
contains: boolean;
}>;
mapBoundsExtend(_args: MapBoundsExtendArgs): Promise<{
bounds: LatLngBounds;
}>;
private getLatLngBounds;
setCircleListeners(mapId: string, circleId: string, circle: google.maps.Circle): Promise<void>;
setPolygonListeners(mapId: string, polygonId: string, polygon: google.maps.Polygon): Promise<void>;
setPolylineListeners(mapId: string, polylineId: string, polyline: google.maps.Polyline): Promise<void>;
setMarkerListeners(mapId: string, markerId: string, marker: google.maps.marker.AdvancedMarkerElement): Promise<void>;
setMapListeners(mapId: string): Promise<void>;
private buildMarkerOpts;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
import Foundation
import Capacitor
public struct Circle {
let center: LatLng
let radius: Double
let strokeWidth: CGFloat
let strokeColor: UIColor
let fillColor: UIColor
let tappable: Bool?
let title: String?
let zIndex: Int32
let tag: String?
init(from jsObject: JSObject) throws {
var strokeColor = UIColor.blue
var strokeWidth: CGFloat = 1.0
var fillColor = UIColor.blue
guard let centerLatLng = jsObject["center"] as? JSObject else {
throw GoogleMapErrors.invalidArguments("Circle object is missing the required 'center' property")
}
guard let lat = centerLatLng["lat"] as? Double, let lng = centerLatLng["lng"] as? Double else {
throw GoogleMapErrors.invalidArguments("LatLng object is missing the required 'lat' and/or 'lng' property")
}
guard let radius = jsObject["radius"] as? Double else {
throw GoogleMapErrors.invalidArguments("Circle object is missing the required 'radius' property")
}
if let width = jsObject["strokeWeight"] as? Float {
strokeWidth = CGFloat(width)
}
let strokeOpacity = jsObject["strokeOpacity"] as? Double
if let hexColor = jsObject["strokeColor"] as? String {
strokeColor = UIColor(hex: hexColor) ?? UIColor.blue
}
strokeColor = strokeColor.withAlphaComponent(strokeOpacity ?? 1.0)
let fillOpacity = jsObject["fillOpacity"] as? Double
if let hexColor = jsObject["fillColor"] as? String {
fillColor = UIColor(hex: hexColor) ?? UIColor.blue
}
fillColor = fillColor.withAlphaComponent(fillOpacity ?? 1.0)
self.center = LatLng(lat: lat, lng: lng)
self.radius = radius
self.fillColor = fillColor
self.strokeColor = strokeColor
self.strokeWidth = strokeWidth
self.tag = jsObject["tag"] as? String
self.tappable = jsObject["clickable"] as? Bool
self.title = jsObject["title"] as? String
self.zIndex = Int32((jsObject["zIndex"] as? Int) ?? 0)
}
}

View File

@@ -0,0 +1,29 @@
import Foundation
import Capacitor
public struct GoogleMapCameraConfig {
let coordinate: LatLng?
let zoom: Float?
let bearing: Double?
let angle: Double?
let animate: Bool?
let animationDuration: Double?
init(fromJSObject: JSObject) throws {
zoom = fromJSObject["zoom"] as? Float
bearing = fromJSObject["bearing"] as? Double
angle = fromJSObject["angle"] as? Double
animate = fromJSObject["animate"] as? Bool
animationDuration = fromJSObject["animationDuration"] as? Double
if let latLngObj = fromJSObject["coordinate"] as? JSObject {
guard let lat = latLngObj["lat"] as? Double, let lng = latLngObj["lng"] as? Double else {
throw GoogleMapErrors.invalidArguments("LatLng object is missing the required 'lat' and/or 'lng' property")
}
self.coordinate = LatLng(lat: lat, lng: lng)
} else {
self.coordinate = nil
}
}
}

View File

@@ -0,0 +1,157 @@
import Foundation
import Capacitor
import GoogleMaps
public struct GoogleMapConfig: Codable {
let width: Double
let height: Double
let x: Double
let y: Double
let center: LatLng
let zoom: Double
let styles: String?
var mapId: String?
let mapTypeId: String?
let maxZoom: Double?
let minZoom: Double?
let restriction: GoogleMapConfigRestriction?
let heading: Double?
init(fromJSObject: JSObject) throws {
guard let width = fromJSObject["width"] as? Double else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfig object is missing the required 'width' property")
}
guard let height = fromJSObject["height"] as? Double else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfig object is missing the required 'height' property")
}
guard let x = fromJSObject["x"] as? Double else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfig object is missing the required 'x' property")
}
guard let y = fromJSObject["y"] as? Double else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfig object is missing the required 'y' property")
}
guard let zoom = fromJSObject["zoom"] as? Double else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfig object is missing the required 'zoom' property")
}
guard let latLngObj = fromJSObject["center"] as? JSObject else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfig object is missing the required 'center' property")
}
guard let lat = latLngObj["lat"] as? Double, let lng = latLngObj["lng"] as? Double else {
throw GoogleMapErrors.invalidArguments("LatLng object is missing the required 'lat' and/or 'lng' property")
}
self.width = round(width)
self.height = round(height)
self.x = x
self.y = y
self.center = LatLng(lat: lat, lng: lng)
if let stylesArray = fromJSObject["styles"] as? JSArray, let jsonData = try? JSONSerialization.data(withJSONObject: stylesArray, options: []) {
self.styles = String(data: jsonData, encoding: .utf8)
} else {
self.styles = nil
}
self.mapId = fromJSObject["iOSMapId"] as? String
self.mapTypeId = fromJSObject["mapTypeId"] as? String
var maxZoom = fromJSObject["maxZoom"] as? Double
var minZoom = fromJSObject["minZoom"] as? Double
if let unwrappedMinZoom = minZoom, let unwrappedMaxZoom = maxZoom, unwrappedMinZoom > unwrappedMaxZoom {
swap(&minZoom, &maxZoom)
}
self.minZoom = minZoom
self.maxZoom = maxZoom
if let maxZoom, zoom > maxZoom {
self.zoom = maxZoom
} else if let minZoom, zoom < minZoom {
self.zoom = minZoom
} else {
self.zoom = zoom
}
if let restrictionObj = fromJSObject["restriction"] as? JSObject {
self.restriction = try GoogleMapConfigRestriction(fromJSObject: restrictionObj)
} else {
self.restriction = nil
}
self.heading = fromJSObject["heading"] as? Double
}
}
public struct GoogleMapConfigRestriction: Codable {
let latLngBounds: GMSCoordinateBounds
init(fromJSObject: JSObject) throws {
guard let latLngBoundsObj = fromJSObject["latLngBounds"] as? JSObject else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfigRestriction object is missing the required 'latLngBounds' property")
}
guard let north = latLngBoundsObj["north"] as? Double else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfigRestriction object is missing the required 'latLngBounds.north' property")
}
guard let south = latLngBoundsObj["south"] as? Double else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfigRestriction object is missing the required 'latLngBounds.south' property")
}
guard let east = latLngBoundsObj["east"] as? Double else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfigRestriction object is missing the required 'latLngBounds.east' property")
}
guard let west = latLngBoundsObj["west"] as? Double else {
throw GoogleMapErrors.invalidArguments("GoogleMapConfigRestriction object is missing the required 'latLngBounds.west' property")
}
let southWest = CLLocationCoordinate2D(latitude: south, longitude: west)
let northEast = CLLocationCoordinate2D(latitude: north, longitude: east)
self.latLngBounds = GMSCoordinateBounds(coordinate: southWest, coordinate: northEast)
}
enum CodingKeys: String, CodingKey {
case latLngBounds
}
struct LatLngBounds: Codable {
let north: CLLocationDegrees
let south: CLLocationDegrees
let east: CLLocationDegrees
let west: CLLocationDegrees
init(north: CLLocationDegrees, south: CLLocationDegrees, east: CLLocationDegrees, west: CLLocationDegrees) {
self.north = north
self.south = south
self.east = east
self.west = west
}
}
public func encode(to encoder: any Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
let latLngBounds = LatLngBounds(
north: self.latLngBounds.northEast.latitude,
south: self.latLngBounds.southWest.latitude,
east: self.latLngBounds.northEast.longitude,
west: self.latLngBounds.southWest.longitude
)
try container.encode(latLngBounds, forKey: .latLngBounds)
}
public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let latLngBounds = try container.decode(LatLngBounds.self, forKey: .latLngBounds)
let southWest = CLLocationCoordinate2D(latitude: latLngBounds.south, longitude: latLngBounds.west)
let northEast = CLLocationCoordinate2D(latitude: latLngBounds.north, longitude: latLngBounds.east)
self.latLngBounds = GMSCoordinateBounds(coordinate: southWest, coordinate: northEast)
}
}

View File

@@ -0,0 +1,50 @@
import Foundation
public enum GoogleMapErrors: Error {
case invalidMapId
case mapNotFound
case markerNotFound
case invalidArguments(_ description: String)
case invalidAPIKey
case permissionsDeniedLocation
case unhandledError(_ description: String)
case tileOverlayNotFound
}
public struct GoogleMapErrorObject {
let extra: [String: Any]?
let code: Int
let message: String
init(_ code: Int, _ message: String, _ extra: [String: Any]? = nil) {
self.code = code
self.message = message
self.extra = extra
}
var asDictionary: [String: Any] {
return ["code": code, "message": message, "extra": extra ?? []]
}
}
public func getErrorObject(_ error: Error) -> GoogleMapErrorObject {
switch error {
case GoogleMapErrors.invalidMapId:
return GoogleMapErrorObject(1, "Missing or invalid map id.")
case GoogleMapErrors.mapNotFound:
return GoogleMapErrorObject(2, "Map not found for provided id.")
case GoogleMapErrors.markerNotFound:
return GoogleMapErrorObject(3, "Marker not found for provided id.")
case GoogleMapErrors.invalidArguments(let msg):
return GoogleMapErrorObject(4, "Invalid Arguments Provided: \(msg)")
case GoogleMapErrors.permissionsDeniedLocation:
return GoogleMapErrorObject(5, "Permissions denied for accessing device location.")
case GoogleMapErrors.invalidAPIKey:
return GoogleMapErrorObject(6, "Missing or invalid Google Maps SDK API key.")
case GoogleMapErrors.tileOverlayNotFound:
return GoogleMapErrorObject(7, "Tile overlay not found for provided id.")
case GoogleMapErrors.unhandledError(let msg):
return GoogleMapErrorObject(0, "Unhandled Error: \(msg)")
default:
return GoogleMapErrorObject(0, "Unhandled Error: \(error.localizedDescription)")
}
}

View File

@@ -0,0 +1,16 @@
import Foundation
import Capacitor
public struct GoogleMapPadding {
let top: Float
let bottom: Float
let left: Float
let right: Float
init(fromJSObject: JSObject) throws {
top = fromJSObject["top"] as? Float ?? 0
bottom = fromJSObject["bottom"] as? Float ?? 0
left = fromJSObject["left"] as? Float ?? 0
right = fromJSObject["right"] as? Float ?? 0
}
}

View File

@@ -0,0 +1,807 @@
import Foundation
import GoogleMaps
import Capacitor
import GoogleMapsUtils
public struct LatLng: Codable {
let lat: Double
let lng: Double
}
class GMViewController: UIViewController {
var mapViewBounds: [String: Double]!
var GMapView: GMSMapView!
var cameraPosition: [String: Double]!
var minimumClusterSize: Int?
var mapId: String?
var onViewDidLoad: (() -> Void)?
private var clusterManager: GMUClusterManager?
var clusteringEnabled: Bool {
return clusterManager != nil
}
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.camera(withLatitude: cameraPosition["latitude"] ?? 0, longitude: cameraPosition["longitude"] ?? 0, zoom: Float(cameraPosition["zoom"] ?? 12))
let frame = CGRect(x: mapViewBounds["x"] ?? 0, y: mapViewBounds["y"] ?? 0, width: mapViewBounds["width"] ?? 0, height: mapViewBounds["height"] ?? 0)
if let id = mapId {
let gmsId = GMSMapID(identifier: id)
self.GMapView = GMSMapView(frame: frame, mapID: gmsId, camera: camera)
} else {
self.GMapView = GMSMapView(frame: frame, camera: camera)
}
self.view = GMapView
self.onViewDidLoad?()
}
func initClusterManager(_ minClusterSize: Int?) {
let iconGenerator = GMUDefaultClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = GMUDefaultClusterRenderer(mapView: self.GMapView, clusterIconGenerator: iconGenerator)
self.minimumClusterSize = minClusterSize
if let minClusterSize = minClusterSize {
renderer.minimumClusterSize = UInt(minClusterSize)
}
self.clusterManager = GMUClusterManager(map: self.GMapView, algorithm: algorithm, renderer: renderer)
}
func destroyClusterManager() {
self.clusterManager = nil
}
func addMarkersToCluster(markers: [GMSMarker]) {
if let clusterManager = clusterManager {
clusterManager.add(markers)
clusterManager.cluster()
}
}
func removeMarkersFromCluster(markers: [GMSMarker]) {
if let clusterManager = clusterManager {
markers.forEach { marker in
clusterManager.remove(marker)
}
clusterManager.cluster()
}
}
}
// swiftlint:disable type_body_length
public class Map {
var id: String
var config: GoogleMapConfig
var mapViewController: GMViewController
var targetViewController: UIView?
var markers = [Int: GMSMarker]()
var tileOverlays = [Int: GMSURLTileLayer]()
var polygons = [Int: GMSPolygon]()
var circles = [Int: GMSCircle]()
var polylines = [Int: GMSPolyline]()
var markerIcons = [String: UIImage]()
// swiftlint:disable identifier_name
public static let MAP_TAG = 99999
// swiftlint:enable identifier_name
// swiftlint:disable weak_delegate
private var delegate: CapacitorGoogleMapsPlugin
init(id: String, config: GoogleMapConfig, delegate: CapacitorGoogleMapsPlugin) {
self.id = id
self.config = config
self.delegate = delegate
self.mapViewController = GMViewController()
self.mapViewController.mapId = config.mapId
self.mapViewController.onViewDidLoad = { [weak self] in
self?.finishMapConfiguration()
}
self.render()
}
func render() {
DispatchQueue.main.async {
self.mapViewController.mapViewBounds = [
"width": self.config.width,
"height": self.config.height,
"x": self.config.x,
"y": self.config.y
]
self.mapViewController.cameraPosition = [
"latitude": self.config.center.lat,
"longitude": self.config.center.lng,
"zoom": self.config.zoom
]
self.targetViewController = self.getTargetContainer(refWidth: self.config.width, refHeight: self.config.height)
if let target = self.targetViewController {
target.tag = Map.MAP_TAG
target.removeAllSubview()
self.mapViewController.view.frame = target.bounds
target.addSubview(self.mapViewController.view)
}
}
}
func finishMapConfiguration() {
DispatchQueue.main.async {
self.mapViewController.GMapView.delegate = self.delegate
if let styles = self.config.styles {
do {
self.mapViewController.GMapView.mapStyle = try GMSMapStyle(jsonString: styles)
} catch {
CAPLog.print("Invalid Google Maps styles")
}
}
let minZoom = self.config.minZoom.map { Float($0) } ?? self.mapViewController.GMapView.minZoom
let maxZoom = self.config.maxZoom.map { Float($0) } ?? self.mapViewController.GMapView.maxZoom
self.mapViewController.GMapView.setMinZoom(minZoom, maxZoom: maxZoom)
if let mapTypeId = self.config.mapTypeId {
switch mapTypeId {
case "hybrid":
self.mapViewController.GMapView.mapType = .hybrid
case "roadmap":
self.mapViewController.GMapView.mapType = .normal
case "satellite":
self.mapViewController.GMapView.mapType = .satellite
case "terrain":
self.mapViewController.GMapView.mapType = .terrain
default:
break
}
}
if let restriction = self.config.restriction {
self.mapViewController.GMapView.cameraTargetBounds = restriction.latLngBounds
}
if let heading = self.config.heading {
self.mapViewController.GMapView.animate(toBearing: heading)
}
self.delegate.notifyListeners("onMapReady", data: [
"mapId": self.id
])
}
}
func updateRender(mapBounds: CGRect) {
DispatchQueue.main.sync {
let newWidth = round(Double(mapBounds.width))
let newHeight = round(Double(mapBounds.height))
let isWidthEqual = round(Double(self.mapViewController.view.bounds.width)) == newWidth
let isHeightEqual = round(Double(self.mapViewController.view.bounds.height)) == newHeight
if !isWidthEqual || !isHeightEqual {
CATransaction.begin()
CATransaction.setDisableActions(true)
self.mapViewController.view.frame.size.width = newWidth
self.mapViewController.view.frame.size.height = newHeight
CATransaction.commit()
}
}
}
func rebindTargetContainer(mapBounds: CGRect) {
DispatchQueue.main.sync {
if let target = self.getTargetContainer(refWidth: round(Double(mapBounds.width)), refHeight: round(Double(mapBounds.height))) {
self.targetViewController = target
target.tag = Map.MAP_TAG
target.removeAllSubview()
CATransaction.begin()
CATransaction.setDisableActions(true)
self.mapViewController.view.frame.size.width = mapBounds.width
self.mapViewController.view.frame.size.height = mapBounds.height
CATransaction.commit()
target.addSubview(self.mapViewController.view)
}
}
}
private func getTargetContainer(refWidth: Double, refHeight: Double) -> UIView? {
if let bridge = self.delegate.bridge {
for item in bridge.webView!.getAllSubViews() {
let isScrollView = item.isKind(of: NSClassFromString("WKChildScrollView")!) || item.isKind(of: NSClassFromString("WKScrollView")!)
let isBridgeScrollView = item.isEqual(bridge.webView?.scrollView)
if isScrollView && !isBridgeScrollView {
(item as? UIScrollView)?.isScrollEnabled = true
let height = Double((item as? UIScrollView)?.contentSize.height ?? 0)
let width = Double((item as? UIScrollView)?.contentSize.width ?? 0)
let actualHeightFloor = floor(height / 2)
let actualHeightCeil = ceil(height / 2)
let isWidthEqual = width == refWidth
let isHeightEqual = actualHeightFloor == refHeight || actualHeightCeil == refHeight
if isWidthEqual && isHeightEqual && item.tag < self.targetViewController?.tag ?? Map.MAP_TAG {
return item
}
}
}
}
return nil
}
func destroy() {
DispatchQueue.main.async {
self.mapViewController.GMapView = nil
self.targetViewController?.tag = 0
self.mapViewController.view = nil
self.enableTouch()
}
}
func enableTouch() {
DispatchQueue.main.async {
if let target = self.targetViewController, let itemIndex = WKWebView.disabledTargets.firstIndex(of: target) {
WKWebView.disabledTargets.remove(at: itemIndex)
}
}
}
func addTileOverlay(tileOverlay: TileOverlay) throws -> Int {
var tileOverlayHash = 0
DispatchQueue.main.sync {
let urlConstructor: GMSTileURLConstructor = { x, y, zoom in
URL(string: tileOverlay.url
.replacingOccurrences(of: "{x}", with: "\(x)")
.replacingOccurrences(of: "{y}", with: "\(y)")
.replacingOccurrences(of: "{z}", with: "\(zoom)")
)
}
let layer = GMSURLTileLayer(urlConstructor: urlConstructor)
layer.opacity = tileOverlay.opacity ?? 1
layer.zIndex = tileOverlay.zIndex
layer.map = self.mapViewController.GMapView
self.tileOverlays[layer.hash.hashValue] = layer
tileOverlayHash = layer.hash.hashValue
}
return tileOverlayHash
}
func removeTileOverlay(id: Int) throws {
if let tileOverlay = self.tileOverlays[id] {
DispatchQueue.main.async {
tileOverlay.map = nil
self.tileOverlays.removeValue(forKey: id)
}
} else {
throw GoogleMapErrors.tileOverlayNotFound
}
}
func disableTouch() {
DispatchQueue.main.async {
if let target = self.targetViewController, !WKWebView.disabledTargets.contains(target) {
WKWebView.disabledTargets.append(target)
}
}
}
func addMarker(marker: Marker) throws -> Int {
var markerHash = 0
DispatchQueue.main.sync {
let newMarker = self.buildMarker(marker: marker)
if self.mapViewController.clusteringEnabled {
self.mapViewController.addMarkersToCluster(markers: [newMarker])
} else {
newMarker.map = self.mapViewController.GMapView
}
self.markers[newMarker.hash.hashValue] = newMarker
markerHash = newMarker.hash.hashValue
}
return markerHash
}
func addMarkers(markers: [Marker]) throws -> [Int] {
var markerHashes: [Int] = []
DispatchQueue.main.sync {
var googleMapsMarkers: [GMSMarker] = []
markers.forEach { marker in
let newMarker = self.buildMarker(marker: marker)
if self.mapViewController.clusteringEnabled {
googleMapsMarkers.append(newMarker)
} else {
newMarker.map = self.mapViewController.GMapView
}
self.markers[newMarker.hash.hashValue] = newMarker
markerHashes.append(newMarker.hash.hashValue)
}
if self.mapViewController.clusteringEnabled {
self.mapViewController.addMarkersToCluster(markers: googleMapsMarkers)
}
}
return markerHashes
}
func addPolygons(polygons: [Polygon]) throws -> [Int] {
var polygonHashes: [Int] = []
DispatchQueue.main.sync {
polygons.forEach { polygon in
let newPolygon = self.buildPolygon(polygon: polygon)
newPolygon.map = self.mapViewController.GMapView
self.polygons[newPolygon.hash.hashValue] = newPolygon
polygonHashes.append(newPolygon.hash.hashValue)
}
}
return polygonHashes
}
func addCircles(circles: [Circle]) throws -> [Int] {
var circleHashes: [Int] = []
DispatchQueue.main.sync {
circles.forEach { circle in
let newCircle = self.buildCircle(circle: circle)
newCircle.map = self.mapViewController.GMapView
self.circles[newCircle.hash.hashValue] = newCircle
circleHashes.append(newCircle.hash.hashValue)
}
}
return circleHashes
}
func addPolylines(lines: [Polyline]) throws -> [Int] {
var polylineHashes: [Int] = []
DispatchQueue.main.sync {
lines.forEach { line in
let newLine = self.buildPolyline(line: line)
newLine.map = self.mapViewController.GMapView
self.polylines[newLine.hash.hashValue] = newLine
polylineHashes.append(newLine.hash.hashValue)
}
}
return polylineHashes
}
func enableClustering(_ minClusterSize: Int?) {
if !self.mapViewController.clusteringEnabled {
DispatchQueue.main.sync {
self.mapViewController.initClusterManager(minClusterSize)
// add existing markers to the cluster
if !self.markers.isEmpty {
var existingMarkers: [GMSMarker] = []
for (_, marker) in self.markers {
marker.map = nil
existingMarkers.append(marker)
}
self.mapViewController.addMarkersToCluster(markers: existingMarkers)
}
}
} else if self.mapViewController.minimumClusterSize != minClusterSize {
self.mapViewController.destroyClusterManager()
enableClustering(minClusterSize)
}
}
func disableClustering() {
DispatchQueue.main.sync {
self.mapViewController.destroyClusterManager()
// add existing markers back to the map
if !self.markers.isEmpty {
for (_, marker) in self.markers {
marker.map = self.mapViewController.GMapView
}
}
}
}
func removeMarker(id: Int) throws {
if let marker = self.markers[id] {
DispatchQueue.main.async {
if self.mapViewController.clusteringEnabled {
self.mapViewController.removeMarkersFromCluster(markers: [marker])
}
marker.map = nil
self.markers.removeValue(forKey: id)
}
} else {
throw GoogleMapErrors.markerNotFound
}
}
func removePolygons(ids: [Int]) throws {
DispatchQueue.main.sync {
ids.forEach { id in
if let polygon = self.polygons[id] {
polygon.map = nil
self.polygons.removeValue(forKey: id)
}
}
}
}
func removeCircles(ids: [Int]) throws {
DispatchQueue.main.sync {
ids.forEach { id in
if let circle = self.circles[id] {
circle.map = nil
self.circles.removeValue(forKey: id)
}
}
}
}
func removePolylines(ids: [Int]) throws {
DispatchQueue.main.sync {
ids.forEach { id in
if let line = self.polylines[id] {
line.map = nil
self.polylines.removeValue(forKey: id)
}
}
}
}
func setCamera(config: GoogleMapCameraConfig) throws {
let currentCamera = self.mapViewController.GMapView.camera
let lat = config.coordinate?.lat ?? currentCamera.target.latitude
let lng = config.coordinate?.lng ?? currentCamera.target.longitude
let zoom = config.zoom ?? currentCamera.zoom
let bearing = config.bearing ?? Double(currentCamera.bearing)
let angle = config.angle ?? currentCamera.viewingAngle
let animate = config.animate ?? false
DispatchQueue.main.sync {
let newCamera = GMSCameraPosition(latitude: lat, longitude: lng, zoom: zoom, bearing: bearing, viewingAngle: angle)
if animate {
self.mapViewController.GMapView.animate(to: newCamera)
} else {
self.mapViewController.GMapView.camera = newCamera
}
}
}
func getMapType() -> GMSMapViewType {
return self.mapViewController.GMapView.mapType
}
func setMapType(mapType: GMSMapViewType) throws {
DispatchQueue.main.sync {
self.mapViewController.GMapView.mapType = mapType
}
}
func enableIndoorMaps(enabled: Bool) throws {
DispatchQueue.main.sync {
self.mapViewController.GMapView.isIndoorEnabled = enabled
}
}
func enableTrafficLayer(enabled: Bool) throws {
DispatchQueue.main.sync {
self.mapViewController.GMapView.isTrafficEnabled = enabled
}
}
func enableAccessibilityElements(enabled: Bool) throws {
DispatchQueue.main.sync {
self.mapViewController.GMapView.accessibilityElementsHidden = enabled
}
}
func enableCurrentLocation(enabled: Bool) throws {
DispatchQueue.main.sync {
self.mapViewController.GMapView.isMyLocationEnabled = enabled
}
}
func setPadding(padding: GoogleMapPadding) throws {
DispatchQueue.main.sync {
let mapInsets = UIEdgeInsets(top: CGFloat(padding.top), left: CGFloat(padding.left), bottom: CGFloat(padding.bottom), right: CGFloat(padding.right))
self.mapViewController.GMapView.padding = mapInsets
}
}
func removeMarkers(ids: [Int]) throws {
DispatchQueue.main.sync {
var markers: [GMSMarker] = []
ids.forEach { id in
if let marker = self.markers[id] {
marker.map = nil
self.markers.removeValue(forKey: id)
markers.append(marker)
}
}
if self.mapViewController.clusteringEnabled {
self.mapViewController.removeMarkersFromCluster(markers: markers)
}
}
}
func getMapLatLngBounds() -> GMSCoordinateBounds? {
return GMSCoordinateBounds(region: self.mapViewController.GMapView.projection.visibleRegion())
}
func fitBounds(bounds: GMSCoordinateBounds, padding: CGFloat) {
DispatchQueue.main.sync {
let cameraUpdate = GMSCameraUpdate.fit(bounds, withPadding: padding)
self.mapViewController.GMapView.animate(with: cameraUpdate)
}
}
private func getFrameOverflowBounds(frame: CGRect, mapBounds: CGRect) -> [CGRect] {
var intersections: [CGRect] = []
// get top overflow
if mapBounds.origin.y < frame.origin.y {
let height = frame.origin.y - mapBounds.origin.y
let width = mapBounds.width
intersections.append(CGRect(x: 0, y: 0, width: width, height: height))
}
// get bottom overflow
if (mapBounds.origin.y + mapBounds.height) > (frame.origin.y + frame.height) {
let height = (mapBounds.origin.y + mapBounds.height) - (frame.origin.y + frame.height)
let width = mapBounds.width
intersections.append(CGRect(x: 0, y: mapBounds.height, width: width, height: height))
}
return intersections
}
private func buildCircle(circle: Circle) -> GMSCircle {
let newCircle = GMSCircle()
newCircle.title = circle.title
newCircle.strokeColor = circle.strokeColor
newCircle.strokeWidth = circle.strokeWidth
newCircle.fillColor = circle.fillColor
newCircle.position = CLLocationCoordinate2D(latitude: circle.center.lat, longitude: circle.center.lng)
newCircle.radius = CLLocationDistance(circle.radius)
newCircle.isTappable = circle.tappable ?? false
newCircle.zIndex = circle.zIndex
newCircle.userData = circle.tag
return newCircle
}
private func buildPolygon(polygon: Polygon) -> GMSPolygon {
let newPolygon = GMSPolygon()
newPolygon.title = polygon.title
newPolygon.strokeColor = polygon.strokeColor
newPolygon.strokeWidth = polygon.strokeWidth
newPolygon.fillColor = polygon.fillColor
newPolygon.isTappable = polygon.tappable ?? false
newPolygon.geodesic = polygon.geodesic ?? false
newPolygon.zIndex = polygon.zIndex
newPolygon.userData = polygon.tag
var shapeIndex = 0
let outerShape = GMSMutablePath()
var holes: [GMSMutablePath] = []
polygon.shapes.forEach { shape in
if shapeIndex == 0 {
shape.forEach { coord in
outerShape.add(CLLocationCoordinate2D(latitude: coord.lat, longitude: coord.lng))
}
} else {
let holeShape = GMSMutablePath()
shape.forEach { coord in
holeShape.add(CLLocationCoordinate2D(latitude: coord.lat, longitude: coord.lng))
}
holes.append(holeShape)
}
shapeIndex += 1
}
newPolygon.path = outerShape
newPolygon.holes = holes
return newPolygon
}
private func buildPolyline(line: Polyline) -> GMSPolyline {
let newPolyline = GMSPolyline()
newPolyline.title = line.title
newPolyline.strokeColor = line.strokeColor
newPolyline.strokeWidth = line.strokeWidth
newPolyline.isTappable = line.tappable ?? false
newPolyline.geodesic = line.geodesic ?? false
newPolyline.zIndex = line.zIndex
newPolyline.userData = line.tag
let path = GMSMutablePath()
line.path.forEach { coord in
path.add(CLLocationCoordinate2D(latitude: coord.lat, longitude: coord.lng))
}
newPolyline.path = path
if line.styleSpans.count > 0 {
var spans: [GMSStyleSpan] = []
line.styleSpans.forEach { span in
if let segments = span.segments {
spans.append(GMSStyleSpan(color: span.color, segments: segments))
} else {
spans.append(GMSStyleSpan(color: span.color))
}
}
newPolyline.spans = spans
}
return newPolyline
}
private func buildMarker(marker: Marker) -> GMSMarker {
let newMarker = GMSMarker()
newMarker.position = CLLocationCoordinate2D(latitude: marker.coordinate.lat, longitude: marker.coordinate.lng)
newMarker.title = marker.title
newMarker.snippet = marker.snippet
newMarker.isFlat = marker.isFlat ?? false
newMarker.opacity = marker.opacity ?? 1
newMarker.isDraggable = marker.draggable ?? false
newMarker.zIndex = marker.zIndex
if let iconAnchor = marker.iconAnchor {
newMarker.groundAnchor = iconAnchor
}
// cache and reuse marker icon uiimages
if let iconUrl = marker.iconUrl {
if let iconImage = self.markerIcons[iconUrl] {
newMarker.icon = getResizedIcon(iconImage, marker)
} else {
if iconUrl.starts(with: "https:") {
if let url = URL(string: iconUrl) {
URLSession.shared.dataTask(with: url) { (data, _, _) in
DispatchQueue.main.async {
if let data = data, let iconImage = UIImage(data: data) {
self.markerIcons[iconUrl] = iconImage
newMarker.icon = getResizedIcon(iconImage, marker)
}
}
}.resume()
}
} else if let iconImage = UIImage(named: "public/\(iconUrl)") {
self.markerIcons[iconUrl] = iconImage
newMarker.icon = getResizedIcon(iconImage, marker)
} else {
var detailedMessage = ""
if iconUrl.hasSuffix(".svg") {
detailedMessage = "SVG not supported."
}
print("CapacitorGoogleMaps Warning: could not load image '\(iconUrl)'. \(detailedMessage) Using default marker icon.")
}
}
} else {
if let color = marker.color {
newMarker.icon = GMSMarker.markerImage(with: color)
}
}
return newMarker
}
}
private func getResizedIcon(_ iconImage: UIImage, _ marker: Marker) -> UIImage? {
if let iconSize = marker.iconSize {
return iconImage.resizeImageTo(size: iconSize)
} else {
return iconImage
}
}
extension WKWebView {
static var disabledTargets: [UIView] = []
override open func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
var hitView = super.hitTest(point, with: event)
if let tempHitView = hitView, WKWebView.disabledTargets.contains(tempHitView) {
return nil
}
if let typeClass = NSClassFromString("WKChildScrollView"), let tempHitView = hitView, tempHitView.isKind(of: typeClass) {
for item in tempHitView.subviews.reversed() {
let convertPoint = item.convert(point, from: self)
if let hitTestView = item.hitTest(convertPoint, with: event) {
hitView = hitTestView
break
}
}
}
return hitView
}
}
extension UIView {
private static var allSubviews: [UIView] = []
private func viewArray(root: UIView) -> [UIView] {
var index = root.tag
for view in root.subviews {
if view.tag == Map.MAP_TAG {
// view already in use as in map
continue
}
// tag the index depth of the uiview
view.tag = index
if view.isKind(of: UIView.self) {
UIView.allSubviews.append(view)
}
_ = viewArray(root: view)
index += 1
}
return UIView.allSubviews
}
fileprivate func getAllSubViews() -> [UIView] {
UIView.allSubviews = []
return viewArray(root: self).reversed()
}
fileprivate func removeAllSubview() {
subviews.forEach {
$0.removeFromSuperview()
}
}
}
extension UIImage {
func resizeImageTo(size: CGSize) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
self.draw(in: CGRect(origin: CGPoint.zero, size: size))
let resizedImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return resizedImage
}
}

View File

@@ -0,0 +1,80 @@
import Foundation
import Capacitor
public struct Marker {
let coordinate: LatLng
let opacity: Float?
let title: String?
let snippet: String?
let isFlat: Bool?
let iconUrl: String?
let iconSize: CGSize?
let iconAnchor: CGPoint?
let draggable: Bool?
let color: UIColor?
let zIndex: Int32
init(fromJSObject: JSObject) throws {
guard let latLngObj = fromJSObject["coordinate"] as? JSObject else {
throw GoogleMapErrors.invalidArguments("Marker object is missing the required 'coordinate' property")
}
guard let lat = latLngObj["lat"] as? Double, let lng = latLngObj["lng"] as? Double else {
throw GoogleMapErrors.invalidArguments("LatLng object is missing the required 'lat' and/or 'lng' property")
}
var iconSize: CGSize?
if let sizeObj = fromJSObject["iconSize"] as? JSObject {
if let width = sizeObj["width"] as? Double, let height = sizeObj["height"] as? Double {
iconSize = CGSize(width: width, height: height)
}
}
var iconAnchor: CGPoint?
if let anchorObject = fromJSObject["iconAnchor"] as? JSObject {
if let x = anchorObject["x"] as? Double, let y = anchorObject["y"] as? Double {
if let size = iconSize {
let u = x / size.width
let v = y / size.height
iconAnchor = CGPoint(x: u, y: v)
}
}
}
var tintColor: UIColor?
if let rgbObject = fromJSObject["tintColor"] as? JSObject {
if let r = rgbObject["r"] as? Double, let g = rgbObject["g"] as? Double, let b = rgbObject["b"] as? Double, let a = rgbObject["a"] as? Double {
let uiColorR = CGFloat(r / 255).clamp(min: 0, max: 255)
let uiColorG = CGFloat(g / 255).clamp(min: 0, max: 255)
let uiColorB = CGFloat(b / 255).clamp(min: 0, max: 255)
tintColor = UIColor(red: uiColorR, green: uiColorG, blue: uiColorB, alpha: CGFloat(a))
}
}
self.coordinate = LatLng(lat: lat, lng: lng)
self.opacity = fromJSObject["opacity"] as? Float
self.title = fromJSObject["title"] as? String
self.snippet = fromJSObject["snippet"] as? String
self.isFlat = fromJSObject["isFlat"] as? Bool
self.iconUrl = fromJSObject["iconUrl"] as? String
self.draggable = fromJSObject["draggable"] as? Bool
self.iconSize = iconSize
self.iconAnchor = iconAnchor
self.color = tintColor
self.zIndex = Int32((fromJSObject["zIndex"] as? Int) ?? 0)
}
}
extension CGFloat {
func clamp(min: CGFloat, max: CGFloat) -> CGFloat {
if self < min {
return min
}
if self > max {
return max
}
return self
}
}

View File

@@ -0,0 +1,84 @@
import Foundation
import Capacitor
public struct Polygon {
let shapes: [[LatLng]]
let strokeWidth: CGFloat
let strokeColor: UIColor
let fillColor: UIColor
let tappable: Bool?
let geodesic: Bool?
let title: String?
let zIndex: Int32
let tag: String?
init(fromJSObject: JSObject) throws {
var strokeColor = UIColor.blue
var strokeWidth: CGFloat = 1.0
var fillColor = UIColor.blue
var processedShapes: [[LatLng]] = []
if let width = fromJSObject["strokeWeight"] as? Float {
strokeWidth = CGFloat(width)
}
let strokeOpacity = fromJSObject["strokeOpacity"] as? Double
if let hexColor = fromJSObject["strokeColor"] as? String {
strokeColor = UIColor(hex: hexColor) ?? UIColor.blue
}
strokeColor = strokeColor.withAlphaComponent(strokeOpacity ?? 1.0)
let fillOpacity = fromJSObject["fillOpacity"] as? Double
if let hexColor = fromJSObject["fillColor"] as? String {
fillColor = UIColor(hex: hexColor) ?? UIColor.blue
}
fillColor = fillColor.withAlphaComponent(fillOpacity ?? 1.0)
guard let shapeJSArray = fromJSObject["paths"] as? JSArray else {
throw GoogleMapErrors.invalidArguments("Polygon object is missing the required 'paths' property")
}
if let obj = shapeJSArray.first, obj as? JSArray != nil {
try shapeJSArray.forEach({ obj in
if let shapeArr = obj as? JSArray {
try processedShapes.append(Polygon.processShape(shapeArr))
}
})
} else {
// is a single shape
try processedShapes.append(Polygon.processShape(shapeJSArray))
}
self.shapes = processedShapes
self.fillColor = fillColor
self.strokeColor = strokeColor
self.strokeWidth = strokeWidth
self.tag = fromJSObject["tag"] as? String
self.tappable = fromJSObject["clickable"] as? Bool
self.title = fromJSObject["title"] as? String
self.geodesic = fromJSObject["geodesic"] as? Bool
self.zIndex = Int32((fromJSObject["zIndex"] as? Int) ?? 0)
}
private static func processShape(_ shapeArr: JSArray) throws -> [LatLng] {
var shape: [LatLng] = []
try shapeArr.forEach { obj in
guard let jsCoord = obj as? JSObject else {
throw GoogleMapErrors.invalidArguments("LatLng object is missing the required 'lat' and/or 'lng' property")
}
guard let lat = jsCoord["lat"] as? Double, let lng = jsCoord["lng"] as? Double else {
throw GoogleMapErrors.invalidArguments("LatLng object is missing the required 'lat' and/or 'lng' property")
}
shape.append(LatLng(lat: lat, lng: lng))
}
return shape
}
}

View File

@@ -0,0 +1,75 @@
import Foundation
import Capacitor
public struct StyleSpan {
let color: UIColor
let segments: Double?
}
public struct Polyline {
let path: [LatLng]
let strokeWidth: CGFloat
let strokeColor: UIColor
let title: String?
let tappable: Bool?
let geodesic: Bool?
let zIndex: Int32
let tag: String?
let styleSpans: [StyleSpan]
init(fromJSObject: JSObject) throws {
var strokeColor = UIColor.blue
var strokeWidth: CGFloat = 1.0
var path: [LatLng] = []
var styleSpans: [StyleSpan] = []
if let width = fromJSObject["strokeWeight"] as? Float {
strokeWidth = CGFloat(width)
}
let strokeOpacity = fromJSObject["strokeOpacity"] as? Double
if let hexColor = fromJSObject["strokeColor"] as? String {
strokeColor = UIColor(hex: hexColor) ?? UIColor.blue
}
strokeColor = strokeColor.withAlphaComponent(strokeOpacity ?? 1.0)
guard let pathJSArray = fromJSObject["path"] as? JSArray else {
throw GoogleMapErrors.invalidArguments("Polyline object is missing the required 'path' property")
}
try pathJSArray.forEach { obj in
guard let jsCoord = obj as? JSObject else {
throw GoogleMapErrors.invalidArguments("LatLng object is missing the required 'lat' and/or 'lng' property")
}
guard let lat = jsCoord["lat"] as? Double, let lng = jsCoord["lng"] as? Double else {
throw GoogleMapErrors.invalidArguments("LatLng object is missing the required 'lat' and/or 'lng' property")
}
path.append(LatLng(lat: lat, lng: lng))
}
if let styleSpanJSArray = fromJSObject["styleSpans"] as? JSArray {
styleSpanJSArray.forEach({ obj in
if let styleSpanObj = obj as? JSObject,
let hexColor = styleSpanObj["color"] as? String,
let color = UIColor(hex: hexColor) {
let segments = styleSpanObj["segments"] as? Double
styleSpans.append(StyleSpan(color: color, segments: segments))
}
})
}
self.strokeColor = strokeColor
self.strokeWidth = strokeWidth
self.tag = fromJSObject["tag"] as? String
self.title = fromJSObject["title"] as? String
self.tappable = fromJSObject["clickable"] as? Bool
self.geodesic = fromJSObject["geodesic"] as? Bool
self.zIndex = Int32((fromJSObject["zIndex"] as? Int) ?? 0)
self.path = path
self.styleSpans = styleSpans
}
}

View File

@@ -0,0 +1,18 @@
import Capacitor
public struct TileOverlay: Codable {
let url: String
let opacity: Float?
let visible: Bool?
let zIndex: Int32
init(fromJSObject: JSObject) throws {
guard let url = fromJSObject["url"] as? String else {
throw GoogleMapErrors.invalidArguments("TileOverlay object is missing the required 'url' property")
}
self.url = url
self.opacity = fromJSObject["opacity"] as? Float
self.visible = fromJSObject["isFlat"] as? Bool
self.zIndex = Int32((fromJSObject["zIndex"] as? Int) ?? 0)
}
}

View File

@@ -0,0 +1,25 @@
import XCTest
@testable import Plugin
class CapacitorGoogleMapsTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testEcho() {
// This is an example of a functional test case for a plugin.
// Use XCTAssert and related functions to verify your tests produce the correct results.
let implementation = CapacitorGoogleMaps()
let value = "Hello, World!"
let result = implementation.echo(value)
XCTAssertEqual(value, result)
}
}

99
node_modules/@capacitor/google-maps/package.json generated vendored Normal file
View File

@@ -0,0 +1,99 @@
{
"name": "@capacitor/google-maps",
"version": "7.2.0",
"description": "Google maps on Capacitor",
"main": "dist/plugin.cjs.js",
"module": "dist/esm/index.js",
"typings": "dist/typings/index.d.ts",
"typesVersions": {
"<4.1": {
"dist/typings/index.d.ts": [
"dist/typings/ts_old/index.d.ts"
]
}
},
"unpkg": "dist/plugin.js",
"files": [
"android/src/main/",
"android/build.gradle",
"dist/",
"CapacitorGoogleMaps.podspec",
"ios/Sources",
"ios/Tests",
"Package.swift"
],
"author": "Ionic <hi@ionicframework.com>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/ionic-team/capacitor-google-maps.git"
},
"bugs": {
"url": "https://github.com/ionic-team/capacitor-google-maps/issues"
},
"keywords": [
"capacitor",
"plugin",
"native",
"google-maps"
],
"scripts": {
"verify": "pnpm run verify:ios && pnpm run verify:android && pnpm run verify:web",
"verify:ios": "xcodebuild build -scheme CapacitorGoogleMaps -destination generic/platform=iOS",
"verify:android": "cd android && ./gradlew clean build test && cd ..",
"verify:web": "pnpm run build",
"lint": "pnpm eslint . --ext ts && pnpm prettier \"./**/*.{css,html,ts,js,java}\" --check && pnpm node-swiftlint lint",
"fmt": "pnpm eslint . --ext ts --fix && pnpm prettier \"./**/*.{css,html,ts,js,java}\" --write && pnpm node-swiftlint --fix --format",
"docgen": "node ../scripts/docgen_updates.js",
"build": "pnpm run clean && pnpm run docgen && tsc && rollup -c rollup.config.js && pnpm run downleveldts",
"clean": "rimraf ./dist",
"watch": "tsc --watch",
"prepublishOnly": "pnpm run build",
"publish:cocoapod": "pod trunk push ./CapacitorGoogleMaps.podspec --allow-warnings",
"downleveldts": "pnpm downlevel-dts dist/typings dist/typings/ts_old --to=3.5",
"pack-local": "pnpm run build && pnpm pack && find . -name 'capacitor-google-maps-*tgz' -exec bash -c 'mv $0 capacitor-google-maps.tgz' {} \\; ",
"unittest:ios": "xcodebuild test -project ./unit-tests/ios/GoogleMapsPlugin/GoogleMapsPlugin.xcodeproj -scheme TestApp -destination 'platform=iOS Simulator,name=iPhone 12,OS=15.2' | xcpretty && exit ${PIPESTATUS[0]}",
"unittest:android": "cd ./unit-tests/android && ./gradlew testDebugUnitTest"
},
"devDependencies": {
"@capacitor/android": ">=7.0.0",
"@capacitor/core": ">=7.0.0",
"@capacitor/docgen": "0.3.0",
"@capacitor/ios": ">=7.0.0",
"@ionic/prettier-config": "^1.0.1",
"@types/resize-observer-browser": "^0.1.7",
"@types/supercluster": "^7.1.0",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2",
"downlevel-dts": "^0.7.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-import": "^2.25.4",
"prettier": "^2.8.8",
"prettier-plugin-java": "~2.1.0",
"rimraf": "^3.0.2",
"rollup": "^2.78.1",
"swiftlint": "^1.0.2",
"typescript": "^5.4.2"
},
"peerDependencies": {
"@capacitor/core": ">=7.0.0"
},
"capacitor": {
"ios": {
"src": "ios"
},
"android": {
"src": "android"
}
},
"publishConfig": {
"access": "public"
},
"dependencies": {
"@googlemaps/js-api-loader": "~1.16.8",
"@googlemaps/markerclusterer": "~2.5.3",
"@types/google.maps": "~3.58.1"
},
"gitHead": "583b0e5d9c7b018558347750ac9834d78d2939bc"
}