init
This commit is contained in:
1281
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/CapacitorGoogleMapsPlugin.swift
generated
vendored
Normal file
1281
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/CapacitorGoogleMapsPlugin.swift
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
62
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/Circle.swift
generated
vendored
Normal file
62
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/Circle.swift
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
||||
29
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/GoogleMapCameraConfig.swift
generated
vendored
Normal file
29
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/GoogleMapCameraConfig.swift
generated
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
157
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/GoogleMapConfig.swift
generated
vendored
Normal file
157
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/GoogleMapConfig.swift
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
||||
50
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/GoogleMapErrors.swift
generated
vendored
Normal file
50
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/GoogleMapErrors.swift
generated
vendored
Normal 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)")
|
||||
}
|
||||
}
|
||||
16
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/GoogleMapPadding.swift
generated
vendored
Normal file
16
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/GoogleMapPadding.swift
generated
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
807
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/Map.swift
generated
vendored
Normal file
807
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/Map.swift
generated
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
80
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/Marker.swift
generated
vendored
Normal file
80
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/Marker.swift
generated
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
84
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/Polygon.swift
generated
vendored
Normal file
84
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/Polygon.swift
generated
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
75
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/Polyline.swift
generated
vendored
Normal file
75
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/Polyline.swift
generated
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
18
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/TileOverlay.swift
generated
vendored
Normal file
18
node_modules/@capacitor/google-maps/ios/Sources/CapacitorGoogleMapsPlugin/TileOverlay.swift
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user