@exterio/react-native-yamap-lite 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +510 -0
- package/YamapLite.podspec +21 -0
- package/android/build.gradle +101 -0
- package/android/gradle.properties +14 -0
- package/android/settings.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/yamaplite/ClusteredYamapLiteViewManager.kt +181 -0
- package/android/src/main/java/com/yamaplite/Components/ClusteredYamapLiteView.kt +169 -0
- package/android/src/main/java/com/yamaplite/Components/YamapLiteCircleView.kt +145 -0
- package/android/src/main/java/com/yamaplite/Components/YamapLiteMarkerView.kt +214 -0
- package/android/src/main/java/com/yamaplite/Components/YamapLitePolygon.kt +149 -0
- package/android/src/main/java/com/yamaplite/Components/YamapLitePolyline.kt +171 -0
- package/android/src/main/java/com/yamaplite/Components/YamapLiteView.kt +678 -0
- package/android/src/main/java/com/yamaplite/Events/CameraPositionChangeEvent.kt +38 -0
- package/android/src/main/java/com/yamaplite/Events/MapLoadEvent.kt +34 -0
- package/android/src/main/java/com/yamaplite/Events/PressEvent.kt +24 -0
- package/android/src/main/java/com/yamaplite/Utils/ImageCache.kt +45 -0
- package/android/src/main/java/com/yamaplite/Utils/PointParser.kt +39 -0
- package/android/src/main/java/com/yamaplite/Utils/ResolveImageHelper.kt +122 -0
- package/android/src/main/java/com/yamaplite/Utils/YamapUtils.kt +169 -0
- package/android/src/main/java/com/yamaplite/YamapLiteCircleViewManager.kt +67 -0
- package/android/src/main/java/com/yamaplite/YamapLiteMarkerViewManager.kt +82 -0
- package/android/src/main/java/com/yamaplite/YamapLitePackage.kt +41 -0
- package/android/src/main/java/com/yamaplite/YamapLitePolygonViewManager.kt +61 -0
- package/android/src/main/java/com/yamaplite/YamapLitePolylineViewManager.kt +75 -0
- package/android/src/main/java/com/yamaplite/YamapLiteViewManager.kt +176 -0
- package/ios/ClusteredYamapLiteView.h +15 -0
- package/ios/ClusteredYamapLiteView.mm +325 -0
- package/ios/ClusteredYamapLiteViewManager.mm +17 -0
- package/ios/Components/Circle.swift +108 -0
- package/ios/Components/ClusteredYamap.swift +190 -0
- package/ios/Components/Marker.swift +187 -0
- package/ios/Components/Polygon.swift +108 -0
- package/ios/Components/Polyline.swift +125 -0
- package/ios/Components/Yamap.swift +585 -0
- package/ios/Listeners/CameraListener.swift +54 -0
- package/ios/Listeners/ClusterListener.swift +38 -0
- package/ios/Listeners/MapInputListener.swift +35 -0
- package/ios/Listeners/MapLoadListener.swift +35 -0
- package/ios/Listeners/MapObjectTap.swift +12 -0
- package/ios/Listeners/UserLocationObjectListener.swift +29 -0
- package/ios/Models/YamapModels.swift +77 -0
- package/ios/Utils/ImageCache.swift +20 -0
- package/ios/Utils/PointsEqual.h +45 -0
- package/ios/Utils/ResolveImageHelper.swift +142 -0
- package/ios/YamapLiteCircleView.h +15 -0
- package/ios/YamapLiteCircleView.mm +102 -0
- package/ios/YamapLiteMarkerView.h +15 -0
- package/ios/YamapLiteMarkerView.mm +102 -0
- package/ios/YamapLitePolygonView.h +15 -0
- package/ios/YamapLitePolygonView.mm +120 -0
- package/ios/YamapLitePolylineView.h +15 -0
- package/ios/YamapLitePolylineView.mm +115 -0
- package/ios/YamapLiteView.h +15 -0
- package/ios/YamapLiteView.mm +361 -0
- package/ios/YamapLiteViewManager.mm +17 -0
- package/ios/YamapUtils.h +5 -0
- package/ios/YamapUtils.mm +205 -0
- package/lib/module/@types/index.js +8 -0
- package/lib/module/@types/index.js.map +1 -0
- package/lib/module/ClusteredYamapLiteViewNativeComponent.ts +98 -0
- package/lib/module/Components/Circle.js +20 -0
- package/lib/module/Components/Circle.js.map +1 -0
- package/lib/module/Components/ClusteredYamap.js +133 -0
- package/lib/module/Components/ClusteredYamap.js.map +1 -0
- package/lib/module/Components/Marker.js +40 -0
- package/lib/module/Components/Marker.js.map +1 -0
- package/lib/module/Components/Polygon.js +25 -0
- package/lib/module/Components/Polygon.js.map +1 -0
- package/lib/module/Components/Polyline.js +25 -0
- package/lib/module/Components/Polyline.js.map +1 -0
- package/lib/module/Components/Yamap.js +124 -0
- package/lib/module/Components/Yamap.js.map +1 -0
- package/lib/module/Components/index.js +9 -0
- package/lib/module/Components/index.js.map +1 -0
- package/lib/module/NativeYamapUtils.js +5 -0
- package/lib/module/NativeYamapUtils.js.map +1 -0
- package/lib/module/Utils/YamapUtils.js +14 -0
- package/lib/module/Utils/YamapUtils.js.map +1 -0
- package/lib/module/YamapCircleViewNativeComponent.ts +28 -0
- package/lib/module/YamapLiteViewNativeComponent.ts +93 -0
- package/lib/module/YamapMarkerViewNativeComponent.ts +32 -0
- package/lib/module/YamapPolygonViewNativeComponent.ts +28 -0
- package/lib/module/YamapPolylineViewNativeComponent.ts +31 -0
- package/lib/module/index.js +7 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/@types/index.d.ts +257 -0
- package/lib/typescript/src/@types/index.d.ts.map +1 -0
- package/lib/typescript/src/ClusteredYamapLiteViewNativeComponent.d.ts +82 -0
- package/lib/typescript/src/ClusteredYamapLiteViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/Components/Circle.d.ts +4 -0
- package/lib/typescript/src/Components/Circle.d.ts.map +1 -0
- package/lib/typescript/src/Components/ClusteredYamap.d.ts +3 -0
- package/lib/typescript/src/Components/ClusteredYamap.d.ts.map +1 -0
- package/lib/typescript/src/Components/Marker.d.ts +3 -0
- package/lib/typescript/src/Components/Marker.d.ts.map +1 -0
- package/lib/typescript/src/Components/Polygon.d.ts +4 -0
- package/lib/typescript/src/Components/Polygon.d.ts.map +1 -0
- package/lib/typescript/src/Components/Polyline.d.ts +4 -0
- package/lib/typescript/src/Components/Polyline.d.ts.map +1 -0
- package/lib/typescript/src/Components/Yamap.d.ts +3 -0
- package/lib/typescript/src/Components/Yamap.d.ts.map +1 -0
- package/lib/typescript/src/Components/index.d.ts +7 -0
- package/lib/typescript/src/Components/index.d.ts.map +1 -0
- package/lib/typescript/src/NativeYamapUtils.d.ts +30 -0
- package/lib/typescript/src/NativeYamapUtils.d.ts.map +1 -0
- package/lib/typescript/src/Utils/YamapUtils.d.ts +27 -0
- package/lib/typescript/src/Utils/YamapUtils.d.ts.map +1 -0
- package/lib/typescript/src/YamapCircleViewNativeComponent.d.ts +20 -0
- package/lib/typescript/src/YamapCircleViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/YamapLiteViewNativeComponent.d.ts +80 -0
- package/lib/typescript/src/YamapLiteViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/YamapMarkerViewNativeComponent.d.ts +25 -0
- package/lib/typescript/src/YamapMarkerViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/YamapPolygonViewNativeComponent.d.ts +20 -0
- package/lib/typescript/src/YamapPolygonViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/YamapPolylineViewNativeComponent.d.ts +23 -0
- package/lib/typescript/src/YamapPolylineViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +189 -0
- package/src/@types/index.ts +314 -0
- package/src/ClusteredYamapLiteViewNativeComponent.ts +98 -0
- package/src/Components/Circle.tsx +22 -0
- package/src/Components/ClusteredYamap.tsx +194 -0
- package/src/Components/Marker.tsx +50 -0
- package/src/Components/Polygon.tsx +27 -0
- package/src/Components/Polyline.tsx +27 -0
- package/src/Components/Yamap.tsx +176 -0
- package/src/Components/index.ts +6 -0
- package/src/NativeYamapUtils.ts +47 -0
- package/src/Utils/YamapUtils.ts +63 -0
- package/src/YamapCircleViewNativeComponent.ts +28 -0
- package/src/YamapLiteViewNativeComponent.ts +93 -0
- package/src/YamapMarkerViewNativeComponent.ts +32 -0
- package/src/YamapPolygonViewNativeComponent.ts +28 -0
- package/src/YamapPolylineViewNativeComponent.ts +31 -0
- package/src/index.tsx +5 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import YandexMapsMobile
|
|
4
|
+
|
|
5
|
+
@objc(YamapLiteCircleComponentDelegate)
|
|
6
|
+
public protocol YamapLiteCircleComponentDelegate {
|
|
7
|
+
func onCirclePress(point: [String: Double])
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@objc(YamapLiteCircle)
|
|
11
|
+
public class YamapLiteCircle: UIView, MapObjectTapHandler {
|
|
12
|
+
@objc public weak var delegate: YamapLiteCircleComponentDelegate? = nil
|
|
13
|
+
public var mapObject: YMKMapObject?
|
|
14
|
+
@objc public var radius: Float = 100 {
|
|
15
|
+
didSet {
|
|
16
|
+
updateGeometry()
|
|
17
|
+
updateCircle()
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@objc public var fillColor: UIColor = .black {
|
|
22
|
+
didSet {
|
|
23
|
+
updateCircle()
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@objc public var strokeColor: UIColor = .black {
|
|
28
|
+
didSet {
|
|
29
|
+
updateCircle()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@objc public var strokeWidth: Float = 1 {
|
|
34
|
+
didSet {
|
|
35
|
+
updateCircle()
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@objc public var zIndex: Float = 1 {
|
|
40
|
+
didSet {
|
|
41
|
+
updateCircle()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@objc public var circleCenter = YMKPoint(latitude: 55.951244, longitude: 38.718423) {
|
|
46
|
+
didSet {
|
|
47
|
+
updateGeometry()
|
|
48
|
+
updateCircle()
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@objc public var handled = true
|
|
53
|
+
@objc public var circle: YMKCircle
|
|
54
|
+
@objc var listener: MarkerTapListener?
|
|
55
|
+
override init(frame: CGRect) {
|
|
56
|
+
circleCenter = YMKPoint(latitude: 0, longitude: 0)
|
|
57
|
+
radius = 0.0
|
|
58
|
+
fillColor = UIColor.black
|
|
59
|
+
strokeColor = UIColor.black
|
|
60
|
+
zIndex = 1
|
|
61
|
+
strokeWidth = 1
|
|
62
|
+
handled = true
|
|
63
|
+
circle = YMKCircle(center: circleCenter, radius: radius)
|
|
64
|
+
super.init(frame: frame)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@available(*, unavailable)
|
|
68
|
+
required init?(coder _: NSCoder) {
|
|
69
|
+
fatalError("init(coder:) is not implemented.")
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@objc public func updateGeometry() {
|
|
73
|
+
guard circleCenter.latitude.isFinite, circleCenter.longitude.isFinite, radius.isFinite
|
|
74
|
+
else { return }
|
|
75
|
+
circle = YMKCircle(center: circleCenter, radius: radius)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public func onMapObjectTap(point _: YMKPoint) {
|
|
79
|
+
delegate?.onCirclePress(point: [
|
|
80
|
+
"lat": circleCenter.latitude,
|
|
81
|
+
"lon": circleCenter.longitude,
|
|
82
|
+
])
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@objc public func setMapObject(object: YMKMapObject) {
|
|
86
|
+
if let polygonObject = object as? YMKCircleMapObject {
|
|
87
|
+
mapObject = polygonObject
|
|
88
|
+
mapObject?.userData = self
|
|
89
|
+
listener = MarkerTapListener()
|
|
90
|
+
mapObject?.addTapListener(with: listener!)
|
|
91
|
+
updateCircle()
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@objc public func setCircleCenter(latitude: Double, longitude: Double) {
|
|
96
|
+
circleCenter = YMKPoint(latitude: latitude, longitude: longitude)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@objc public func updateCircle() {
|
|
100
|
+
if let circleObject = mapObject as? YMKCircleMapObject, circleObject.isValid {
|
|
101
|
+
circleObject.geometry = circle
|
|
102
|
+
circleObject.zIndex = zIndex
|
|
103
|
+
circleObject.fillColor = fillColor
|
|
104
|
+
circleObject.strokeColor = strokeColor
|
|
105
|
+
circleObject.strokeWidth = strokeWidth
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import UIKit
|
|
4
|
+
import YandexMapsMobile
|
|
5
|
+
import os.log
|
|
6
|
+
|
|
7
|
+
private let clusterLogger = OSLog(subsystem: "com.yamaplite", category: "ClusteredYamapView")
|
|
8
|
+
|
|
9
|
+
@objc(ClusteredYamapView)
|
|
10
|
+
public class ClusteredYamapView: YamapView {
|
|
11
|
+
@objc public var placemarks: [YMKPlacemarkMapObject] = []
|
|
12
|
+
@objc public var clusterCollection: YMKClusterizedPlacemarkCollection?
|
|
13
|
+
@objc public var clusterColor: UIColor = .red
|
|
14
|
+
private var clusterListener: ClusterListener?
|
|
15
|
+
|
|
16
|
+
private let FONT_SIZE: CGFloat = 45
|
|
17
|
+
private let MARGIN_SIZE: CGFloat = 9
|
|
18
|
+
private let STROKE_SIZE: CGFloat = 9
|
|
19
|
+
|
|
20
|
+
override init(frame: CGRect) {
|
|
21
|
+
super.init(frame: frame)
|
|
22
|
+
clusterListener = ClusterListener(callback: nil, delegate: delegate)
|
|
23
|
+
clusterListener?.setClusteredView(self)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@available(*, unavailable)
|
|
27
|
+
required init?(coder _: NSCoder) {
|
|
28
|
+
fatalError("init(coder:) has not been implemented")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private func initializeClusterCollection() {
|
|
32
|
+
guard clusterCollection == nil else { return }
|
|
33
|
+
guard let map = mapView?.mapWindow?.map else {
|
|
34
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
|
|
35
|
+
self?.initializeClusterCollection()
|
|
36
|
+
}
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if clusterListener == nil {
|
|
41
|
+
clusterListener = ClusterListener(callback: nil, delegate: delegate)
|
|
42
|
+
}
|
|
43
|
+
clusterListener?.setClusteredView(self)
|
|
44
|
+
clusterCollection = map.mapObjects.addClusterizedPlacemarkCollection(with: clusterListener!)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@objc override public func insertReactSubview(_ subview: UIView!, at atIndex: Int) {
|
|
48
|
+
let isMarker =
|
|
49
|
+
!(subview is YMKMapView) && subview.responds(to: Selector(("contentView")))
|
|
50
|
+
&& (subview.value(forKey: "contentView") as? YamapLiteMarker) != nil
|
|
51
|
+
|
|
52
|
+
let isCircle =
|
|
53
|
+
!(subview is YMKMapView) && subview.responds(to: Selector(("contentView")))
|
|
54
|
+
&& (subview.value(forKey: "contentView") as? YamapLiteCircle) != nil
|
|
55
|
+
|
|
56
|
+
if isMarker {
|
|
57
|
+
let safeIndex = min(atIndex, subviews.count)
|
|
58
|
+
insertSubview(subview, at: safeIndex)
|
|
59
|
+
|
|
60
|
+
if let markerView = subview.value(forKey: "contentView") as? YamapLiteMarker {
|
|
61
|
+
if atIndex < placemarks.count {
|
|
62
|
+
markerView.setClusterMapObject(placemarks[atIndex])
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} else if isCircle {
|
|
66
|
+
let safeIndex = min(atIndex, subviews.count)
|
|
67
|
+
super.insertReactSubview(subview, at: safeIndex)
|
|
68
|
+
} else {
|
|
69
|
+
let safeIndex = min(atIndex, subviews.count)
|
|
70
|
+
super.insertReactSubview(subview, at: safeIndex)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@objc public func setupClusteredMarkers(markers: [YMKPoint]?) {
|
|
75
|
+
guard let unwrappedMarkers = markers else { return }
|
|
76
|
+
placemarks.removeAll()
|
|
77
|
+
|
|
78
|
+
guard let map = mapView?.mapWindow?.map else {
|
|
79
|
+
os_log("mapView.mapWindow.map is nil, cannot setup clustered markers", log: clusterLogger, type: .error)
|
|
80
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
|
|
81
|
+
self?.setupClusteredMarkers(markers: unwrappedMarkers)
|
|
82
|
+
}
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if clusterCollection == nil {
|
|
87
|
+
if clusterListener == nil {
|
|
88
|
+
clusterListener = ClusterListener(callback: nil, delegate: delegate)
|
|
89
|
+
}
|
|
90
|
+
clusterListener?.setClusteredView(self)
|
|
91
|
+
clusterCollection = map.mapObjects.addClusterizedPlacemarkCollection(with: clusterListener!)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
guard let collection = clusterCollection else {
|
|
95
|
+
os_log("clusterCollection is nil after initialization attempt", log: clusterLogger, type: .error)
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
collection.clear()
|
|
100
|
+
|
|
101
|
+
let newPlacemarks: [YMKPlacemarkMapObject] = collection.addEmptyPlacemarks(
|
|
102
|
+
with: unwrappedMarkers)
|
|
103
|
+
placemarks.append(contentsOf: newPlacemarks)
|
|
104
|
+
|
|
105
|
+
let markerSubviews = subviews.filter { subview in
|
|
106
|
+
!(subview is YMKMapView) && subview.responds(to: Selector(("contentView")))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for i in 0..<min(placemarks.count, markerSubviews.count) {
|
|
110
|
+
let subview = markerSubviews[i]
|
|
111
|
+
if let markerView = subview.value(forKey: "contentView") as? YamapLiteMarker {
|
|
112
|
+
markerView.setClusterMapObject(placemarks[i])
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
collection.clusterPlacemarks(withClusterRadius: 50, minZoom: 12)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@objc override public func removeReactSubview(_ subview: UIView!) {
|
|
120
|
+
guard let contentView = subview.value(forKey: "contentView") as? UIView else {
|
|
121
|
+
super.removeReactSubview(subview)
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if contentView is YamapLiteMarker {
|
|
126
|
+
// setupClusteredMarkers owns the placemarks lifecycle (collection.clear + rebuild).
|
|
127
|
+
// Removing individual placemarks here races with that rebuild, so we only
|
|
128
|
+
// detach the UIView — the next setupClusteredMarkers call cleans the map object.
|
|
129
|
+
subview.removeFromSuperview()
|
|
130
|
+
} else {
|
|
131
|
+
super.removeReactSubview(subview)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@objc override public func fitAllMarkers() {
|
|
136
|
+
var markerPoints: [YMKPoint] = []
|
|
137
|
+
|
|
138
|
+
for placemark in placemarks {
|
|
139
|
+
if placemark.isValid {
|
|
140
|
+
markerPoints.append(placemark.geometry)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if markerPoints.isEmpty {
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
fitMakers(markerPoints)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@objc public func clusterImage(clusterSize: Int) -> UIImage? {
|
|
152
|
+
let text = NSString(string: String(clusterSize))
|
|
153
|
+
let font = UIFont.systemFont(ofSize: FONT_SIZE)
|
|
154
|
+
let attributes: [NSAttributedString.Key: Any] = [.font: font]
|
|
155
|
+
let size = text.size(withAttributes: attributes)
|
|
156
|
+
|
|
157
|
+
let textRadius = sqrt(size.height * size.height + size.width * size.width) / 2
|
|
158
|
+
let internalRadius = textRadius + MARGIN_SIZE
|
|
159
|
+
let externalRadius = internalRadius + STROKE_SIZE
|
|
160
|
+
let imageSize = CGSize(width: externalRadius * 2, height: externalRadius * 2)
|
|
161
|
+
|
|
162
|
+
let renderer = UIGraphicsImageRenderer(size: imageSize)
|
|
163
|
+
|
|
164
|
+
return renderer.image { context in
|
|
165
|
+
let cgContext = context.cgContext
|
|
166
|
+
|
|
167
|
+
cgContext.setFillColor(clusterColor.cgColor)
|
|
168
|
+
cgContext.fillEllipse(
|
|
169
|
+
in: CGRect(x: 0, y: 0, width: externalRadius * 2, height: externalRadius * 2))
|
|
170
|
+
|
|
171
|
+
cgContext.setFillColor(UIColor.white.cgColor)
|
|
172
|
+
cgContext.fillEllipse(
|
|
173
|
+
in: CGRect(
|
|
174
|
+
x: STROKE_SIZE, y: STROKE_SIZE, width: internalRadius * 2, height: internalRadius * 2))
|
|
175
|
+
|
|
176
|
+
let textRect = CGRect(
|
|
177
|
+
x: externalRadius - size.width / 2,
|
|
178
|
+
y: externalRadius - size.height / 2,
|
|
179
|
+
width: size.width,
|
|
180
|
+
height: size.height
|
|
181
|
+
)
|
|
182
|
+
text.draw(
|
|
183
|
+
in: textRect,
|
|
184
|
+
withAttributes: [
|
|
185
|
+
.font: font,
|
|
186
|
+
.foregroundColor: UIColor.black,
|
|
187
|
+
])
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import YandexMapsMobile
|
|
4
|
+
|
|
5
|
+
@objc(YamapLiteMarkerComponentDelegate)
|
|
6
|
+
public protocol YamapLiteMarkerComponentDelegate {
|
|
7
|
+
func onMarkerPress(point: [String: Double])
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@objc(YamapLiteMarker)
|
|
11
|
+
public class YamapLiteMarker: UIView, MapObjectTapHandler {
|
|
12
|
+
////////////////////////
|
|
13
|
+
///////PROPERTIES///////
|
|
14
|
+
////////////////////////
|
|
15
|
+
|
|
16
|
+
private var listener: MarkerTapListener?
|
|
17
|
+
private weak var listenedObject: YMKMapObject?
|
|
18
|
+
|
|
19
|
+
var point: Point? {
|
|
20
|
+
didSet {
|
|
21
|
+
updateMarker()
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@objc public weak var delegate: YamapLiteMarkerComponentDelegate? = nil
|
|
26
|
+
|
|
27
|
+
@objc public var scale: Double = 1.0 {
|
|
28
|
+
didSet {
|
|
29
|
+
if scale < 0.1 {
|
|
30
|
+
scale = 0.1
|
|
31
|
+
}
|
|
32
|
+
updateMarker()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private var originalIcon: UIImage?
|
|
37
|
+
|
|
38
|
+
@objc public var icon: UIImage? {
|
|
39
|
+
get {
|
|
40
|
+
return originalIcon
|
|
41
|
+
}
|
|
42
|
+
set {
|
|
43
|
+
originalIcon = newValue
|
|
44
|
+
updateMarker()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@objc public var onPress: RCTBubblingEventBlock? = nil
|
|
49
|
+
var anchor: Anchor?
|
|
50
|
+
@objc public var zIndex: Float = 0 {
|
|
51
|
+
didSet {
|
|
52
|
+
updateMarker()
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@objc public var visible: Bool = true {
|
|
57
|
+
didSet {
|
|
58
|
+
updateMarker()
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@objc public var handled: Bool = true
|
|
63
|
+
@objc public var mapObject: YMKMapObject? = nil
|
|
64
|
+
@objc public var rotated: Int = 1 {
|
|
65
|
+
didSet {
|
|
66
|
+
updateMarker()
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@objc public var size: Int = 25 {
|
|
71
|
+
didSet {
|
|
72
|
+
updateMarker()
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@objc public var onPressHandler: RCTBubblingEventBlock? = nil
|
|
77
|
+
|
|
78
|
+
override init(frame: CGRect) {
|
|
79
|
+
super.init(frame: frame)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@available(*, unavailable)
|
|
83
|
+
required init?(coder _: NSCoder) {
|
|
84
|
+
fatalError("init(coder:) is not implemented.")
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
////////////////////////
|
|
88
|
+
////////METHODS/////////
|
|
89
|
+
////////////////////////
|
|
90
|
+
|
|
91
|
+
@objc public func onMapObjectTap(point: YMKPoint) {
|
|
92
|
+
delegate?.onMarkerPress(point: [
|
|
93
|
+
"lat": point.latitude,
|
|
94
|
+
"lon": point.longitude,
|
|
95
|
+
])
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@objc public func setPoint(lat: Double, lon: Double) {
|
|
99
|
+
point = Point(lat: lat, lon: lon)
|
|
100
|
+
updateMarker()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@objc public func setAnchor(x: Double, y: Double) {
|
|
104
|
+
anchor = Anchor(x: x, y: y)
|
|
105
|
+
updateMarker()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@objc public func setIcon(uri: String) {
|
|
109
|
+
let image = ResolveImageHelper.shared.resolveUIImage(uri: uri as NSString) {
|
|
110
|
+
[weak self] loadedImage in
|
|
111
|
+
guard let self = self else {
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
guard let loadedImage = loadedImage else {
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
self.originalIcon = loadedImage
|
|
118
|
+
self.updateMarker()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if let image = image {
|
|
122
|
+
originalIcon = image
|
|
123
|
+
updateMarker()
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@objc public func setMapObject(object: YMKMapObject) {
|
|
128
|
+
guard let placemark = object as? YMKPlacemarkMapObject else { return }
|
|
129
|
+
mapObject = placemark
|
|
130
|
+
mapObject!.userData = self
|
|
131
|
+
if listener == nil {
|
|
132
|
+
listener = MarkerTapListener()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if listenedObject !== placemark {
|
|
136
|
+
placemark.addTapListener(with: listener!)
|
|
137
|
+
listenedObject = placemark
|
|
138
|
+
}
|
|
139
|
+
updateMarker()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@objc public func updateMarker() {
|
|
143
|
+
DispatchQueue.main.async { [self] in
|
|
144
|
+
guard let obj = mapObject as? YMKPlacemarkMapObject, obj.isValid else { return }
|
|
145
|
+
let lat = self.point?.lat ?? 0.0
|
|
146
|
+
let lon = self.point?.lon ?? 0.0
|
|
147
|
+
guard lat.isFinite, lon.isFinite else { return }
|
|
148
|
+
obj.geometry = YMKPoint(latitude: lat, longitude: lon)
|
|
149
|
+
|
|
150
|
+
obj.zIndex = Float(zIndex)
|
|
151
|
+
|
|
152
|
+
let iconStyle = YMKIconStyle()
|
|
153
|
+
iconStyle.scale = NSNumber(value: scale)
|
|
154
|
+
iconStyle.visible = NSNumber(value: visible)
|
|
155
|
+
let anchorX = anchor?.x ?? 0.5
|
|
156
|
+
let anchorY = anchor?.y ?? 0.5
|
|
157
|
+
iconStyle.anchor = NSValue(cgPoint: CGPoint(x: CGFloat(anchorX), y: CGFloat(anchorY)))
|
|
158
|
+
|
|
159
|
+
iconStyle.rotationType = NSNumber(
|
|
160
|
+
value: rotated != 0
|
|
161
|
+
? YMKRotationType.rotate.rawValue
|
|
162
|
+
: YMKRotationType.noRotation.rawValue)
|
|
163
|
+
|
|
164
|
+
if let icon = originalIcon {
|
|
165
|
+
let resizedIcon = ResolveImageHelper.shared.resizeImage(
|
|
166
|
+
icon, toWidth: CGFloat(size))
|
|
167
|
+
obj.setIconWith(resizedIcon ?? icon)
|
|
168
|
+
obj.setIconStyleWith(iconStyle)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
extension YamapLiteMarker {
|
|
175
|
+
@objc public func setClusterMapObject(_ placemark: YMKPlacemarkMapObject) {
|
|
176
|
+
mapObject = placemark
|
|
177
|
+
mapObject?.userData = self
|
|
178
|
+
if listener == nil {
|
|
179
|
+
listener = MarkerTapListener()
|
|
180
|
+
}
|
|
181
|
+
if listenedObject !== placemark {
|
|
182
|
+
placemark.addTapListener(with: listener!)
|
|
183
|
+
listenedObject = placemark
|
|
184
|
+
}
|
|
185
|
+
updateMarker()
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import YandexMapsMobile
|
|
4
|
+
|
|
5
|
+
@objc(YamapLitePolygonComponentDelegate)
|
|
6
|
+
public protocol YamapLitePolygonComponentDelegate {
|
|
7
|
+
func onPolygonPress(point: [String: Double])
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@objc(YamapLitePolygon)
|
|
11
|
+
public class YamapLitePolygon: UIView, MapObjectTapHandler {
|
|
12
|
+
@objc public weak var delegate: YamapLitePolygonComponentDelegate? = nil
|
|
13
|
+
public var mapObject: YMKMapObject?
|
|
14
|
+
@objc var listener: MarkerTapListener?
|
|
15
|
+
|
|
16
|
+
override init(frame: CGRect) {
|
|
17
|
+
super.init(frame: frame)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@available(*, unavailable)
|
|
21
|
+
required init?(coder _: NSCoder) {
|
|
22
|
+
fatalError("init(coder:) is not implemented.")
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@objc public var fillColor: UIColor = .black {
|
|
26
|
+
didSet {
|
|
27
|
+
updatePolygon()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@objc public var strokeColor: UIColor = .black {
|
|
33
|
+
didSet {
|
|
34
|
+
updatePolygon()
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@objc public var strokeWidth: Float = 1 {
|
|
39
|
+
didSet {
|
|
40
|
+
updatePolygon()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@objc public var zIndex: Float = 1 {
|
|
45
|
+
didSet {
|
|
46
|
+
updatePolygon()
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@objc public var points: [YMKPoint]? = [] {
|
|
51
|
+
didSet {
|
|
52
|
+
updateGeometry()
|
|
53
|
+
updatePolygon()
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@objc public var innerRings: [[YMKPoint]]? = [] {
|
|
58
|
+
didSet {
|
|
59
|
+
updateGeometry()
|
|
60
|
+
updatePolygon()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@objc public var handled: Bool = true
|
|
65
|
+
|
|
66
|
+
@objc public var polygon: YMKPolygon = YMKPolygon(
|
|
67
|
+
outerRing: YMKLinearRing(points: []),
|
|
68
|
+
innerRings: []
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@objc public func updatePolygon() {
|
|
72
|
+
if let polygonObject = mapObject as? YMKPolygonMapObject, polygonObject.isValid {
|
|
73
|
+
polygonObject.geometry = polygon
|
|
74
|
+
polygonObject.zIndex = zIndex
|
|
75
|
+
polygonObject.fillColor = fillColor
|
|
76
|
+
polygonObject.strokeColor = strokeColor
|
|
77
|
+
polygonObject.strokeWidth = strokeWidth
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@objc public func updateGeometry() {
|
|
82
|
+
let isFinitePoint: (YMKPoint) -> Bool = { $0.latitude.isFinite && $0.longitude.isFinite }
|
|
83
|
+
if let points = points, points.count >= 3, points.allSatisfy(isFinitePoint) {
|
|
84
|
+
let ring = YMKLinearRing(points: points)
|
|
85
|
+
let unwrappedInnerRings = (innerRings ?? [])
|
|
86
|
+
.filter { $0.count >= 3 && $0.allSatisfy(isFinitePoint) }
|
|
87
|
+
.map { YMKLinearRing(points: $0) }
|
|
88
|
+
polygon = YMKPolygon(outerRing: ring, innerRings: unwrappedInnerRings)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public func onMapObjectTap(point: YMKPoint) {
|
|
93
|
+
delegate?.onPolygonPress(point: [
|
|
94
|
+
"lat": point.latitude,
|
|
95
|
+
"lon": point.longitude,
|
|
96
|
+
])
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@objc public func setMapObject(object: YMKMapObject) {
|
|
100
|
+
if let polygonObject = object as? YMKPolygonMapObject {
|
|
101
|
+
mapObject = polygonObject
|
|
102
|
+
mapObject?.userData = self
|
|
103
|
+
listener = MarkerTapListener()
|
|
104
|
+
mapObject?.addTapListener(with: listener!)
|
|
105
|
+
updatePolygon()
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import YandexMapsMobile
|
|
4
|
+
|
|
5
|
+
@objc(YamapLitePolylineComponentDelegate)
|
|
6
|
+
public protocol YamapLitePolylineComponentDelegate {
|
|
7
|
+
func onPolylinePress(point: [String: Double])
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@objc(YamapLitePolyline)
|
|
11
|
+
public final class YamapLitePolyline: UIView, MapObjectTapHandler {
|
|
12
|
+
@objc public weak var delegate: YamapLitePolylineComponentDelegate? = nil
|
|
13
|
+
public var mapObject: YMKMapObject?
|
|
14
|
+
@objc var listener: MarkerTapListener?
|
|
15
|
+
|
|
16
|
+
@objc public var strokeColor: UIColor = .black {
|
|
17
|
+
didSet {
|
|
18
|
+
updatePolyline()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@objc public var strokeWidth: Float = 1 {
|
|
23
|
+
didSet {
|
|
24
|
+
updatePolyline()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@objc public var outlineColor: UIColor = .black {
|
|
29
|
+
didSet {
|
|
30
|
+
updatePolyline()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@objc public var zIndex: Float = 1 {
|
|
35
|
+
didSet {
|
|
36
|
+
updatePolyline()
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@objc public var dashLength: Float = 1 {
|
|
41
|
+
didSet {
|
|
42
|
+
updatePolyline()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@objc public var gapLength: Float = 0 {
|
|
47
|
+
didSet {
|
|
48
|
+
updatePolyline()
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@objc public var outlineWidth: Float = 0 {
|
|
53
|
+
didSet {
|
|
54
|
+
updatePolyline()
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@objc public var dashOffset: Float = 0 {
|
|
59
|
+
didSet {
|
|
60
|
+
updatePolyline()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@objc public var points: [YMKPoint] = [] {
|
|
65
|
+
didSet {
|
|
66
|
+
updateGeometry()
|
|
67
|
+
updatePolyline()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@objc public var handled = true
|
|
72
|
+
|
|
73
|
+
@objc public var polyline: YMKPolyline
|
|
74
|
+
|
|
75
|
+
override init(frame: CGRect) {
|
|
76
|
+
polyline = YMKPolyline(points: points)
|
|
77
|
+
super.init(frame: frame)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@available(*, unavailable)
|
|
81
|
+
required init?(coder _: NSCoder) {
|
|
82
|
+
fatalError("init(coder:) is not implemented.")
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@objc public func updatePolyline() {
|
|
86
|
+
if let polylineObject = mapObject as? YMKPolylineMapObject, polylineObject.isValid {
|
|
87
|
+
polylineObject.geometry = polyline
|
|
88
|
+
polylineObject.zIndex = zIndex
|
|
89
|
+
polylineObject.setStrokeColorWith(strokeColor)
|
|
90
|
+
polylineObject.strokeWidth = strokeWidth
|
|
91
|
+
polylineObject.dashLength = dashLength
|
|
92
|
+
polylineObject.gapLength = gapLength
|
|
93
|
+
polylineObject.dashOffset = dashOffset
|
|
94
|
+
polylineObject.outlineWidth = outlineWidth
|
|
95
|
+
if outlineWidth > 0 {
|
|
96
|
+
polylineObject.outlineColor = outlineColor
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@objc public func updateGeometry() {
|
|
102
|
+
if points.count >= 2,
|
|
103
|
+
points.allSatisfy({ $0.latitude.isFinite && $0.longitude.isFinite })
|
|
104
|
+
{
|
|
105
|
+
polyline = YMKPolyline(points: points)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@objc public func setMapObject(object: YMKMapObject) {
|
|
110
|
+
if let polylineObject = object as? YMKPolylineMapObject {
|
|
111
|
+
mapObject = polylineObject
|
|
112
|
+
mapObject?.userData = self
|
|
113
|
+
listener = MarkerTapListener()
|
|
114
|
+
mapObject?.addTapListener(with: listener!)
|
|
115
|
+
updatePolyline()
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public func onMapObjectTap(point: YMKPoint) {
|
|
120
|
+
delegate?.onPolylinePress(point: [
|
|
121
|
+
"lat": point.latitude,
|
|
122
|
+
"lon": point.longitude,
|
|
123
|
+
])
|
|
124
|
+
}
|
|
125
|
+
}
|