@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,585 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import UIKit
|
|
4
|
+
import YandexMapsMobile
|
|
5
|
+
import os.log
|
|
6
|
+
|
|
7
|
+
private let yamapLogger = OSLog(subsystem: "com.yamaplite", category: "YamapView")
|
|
8
|
+
|
|
9
|
+
@objc(YamapViewComponentDelegate)
|
|
10
|
+
public protocol YamapViewComponentDelegate {
|
|
11
|
+
func handleOnMapLoaded(result: [String: Any])
|
|
12
|
+
func handleOnCameraPositionChange(coords: [String: Any])
|
|
13
|
+
func handleOnCameraPositionChangeEnd(coords: [String: Any])
|
|
14
|
+
func handleOnMapPress(coords: [String: Any])
|
|
15
|
+
func handleOnMapLongPress(coords: [String: Any])
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@objc(YamapView)
|
|
19
|
+
public class YamapView: UIView {
|
|
20
|
+
@objc public weak var delegate: YamapViewComponentDelegate? = nil {
|
|
21
|
+
didSet {
|
|
22
|
+
if delegate != nil && mapView != nil {
|
|
23
|
+
runOnMainThread {
|
|
24
|
+
self.setupListeners()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@objc private var mapObjects: [YamapLiteMarker] = []
|
|
31
|
+
|
|
32
|
+
// MARK: LISTENERS
|
|
33
|
+
|
|
34
|
+
////////////////////////
|
|
35
|
+
///////LISTENERS////////
|
|
36
|
+
////////////////////////
|
|
37
|
+
|
|
38
|
+
private var cameraListener: CameraListener?
|
|
39
|
+
private var loadListener: MapLoadListener?
|
|
40
|
+
private var mapInputListener: MapInputListener?
|
|
41
|
+
private var userLocationListener: UserLocationObjectListener?
|
|
42
|
+
private var userLocationLayer: YMKUserLocationLayer!
|
|
43
|
+
private var userLocationImage: UIImage?
|
|
44
|
+
|
|
45
|
+
// MARK: CALLBACKS
|
|
46
|
+
|
|
47
|
+
////////////////////////
|
|
48
|
+
///////CALLBACKS////////
|
|
49
|
+
////////////////////////
|
|
50
|
+
|
|
51
|
+
@objc public var onCameraPositionChangeCallback: RCTDirectEventBlock?
|
|
52
|
+
@objc public var onCameraPositionChangeEndCallback: RCTDirectEventBlock?
|
|
53
|
+
@objc public var onStop: RCTDirectEventBlock?
|
|
54
|
+
@objc public var onMapLoaded: RCTBubblingEventBlock?
|
|
55
|
+
|
|
56
|
+
@objc public var mapView: YMKMapView!
|
|
57
|
+
|
|
58
|
+
// MARK: PROPERTIES
|
|
59
|
+
|
|
60
|
+
////////////////////////
|
|
61
|
+
///////PROPERTIES///////
|
|
62
|
+
////////////////////////
|
|
63
|
+
|
|
64
|
+
@objc public var mapType: String = "map" {
|
|
65
|
+
didSet {
|
|
66
|
+
guard let map = mapView?.mapWindow?.map else {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
switch mapType {
|
|
70
|
+
case "satellite":
|
|
71
|
+
map.mapType = .satellite
|
|
72
|
+
case "hybrid":
|
|
73
|
+
map.mapType = .hybrid
|
|
74
|
+
default:
|
|
75
|
+
map.mapType = .map
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@objc public var nightMode: Bool = false
|
|
81
|
+
@objc public var scrollGesturesEnabled: Bool = true
|
|
82
|
+
@objc public var userLocationIconScale: Float = 1.0
|
|
83
|
+
@objc public var showUserPosition = false
|
|
84
|
+
@objc public var userLocationAccuracyFillColor: UIColor = UIColor.green
|
|
85
|
+
@objc public var userLocationAccuracyStrokeColor: UIColor = UIColor.black
|
|
86
|
+
@objc public var userLocationAccuracyStrokeWidth: Float = 2.0
|
|
87
|
+
@objc public var zoomGesturesEnabled: Bool = true
|
|
88
|
+
@objc public var tiltGesturesEnabled: Bool = true
|
|
89
|
+
@objc public var rotateGesturesEnabled: Bool = true
|
|
90
|
+
@objc public var fastTapEnabled: Bool = true
|
|
91
|
+
|
|
92
|
+
@objc public func applyProperties() {
|
|
93
|
+
runOnMainThread {
|
|
94
|
+
self.updateMapProperties()
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private func updateMapProperties() {
|
|
99
|
+
guard let map = mapView?.mapWindow?.map else { return }
|
|
100
|
+
switch mapType {
|
|
101
|
+
case "satellite": map.mapType = .satellite
|
|
102
|
+
case "hybrid": map.mapType = .hybrid
|
|
103
|
+
default: map.mapType = .map
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
map.isNightModeEnabled = nightMode
|
|
107
|
+
map.isScrollGesturesEnabled = scrollGesturesEnabled
|
|
108
|
+
map.isZoomGesturesEnabled = zoomGesturesEnabled
|
|
109
|
+
map.isTiltGesturesEnabled = tiltGesturesEnabled
|
|
110
|
+
map.isRotateGesturesEnabled = rotateGesturesEnabled
|
|
111
|
+
map.isFastTapEnabled = fastTapEnabled
|
|
112
|
+
|
|
113
|
+
self.updateUserIcon()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@objc public func setFollowUser(_ follow: Bool) {
|
|
117
|
+
if userLocationLayer == nil {
|
|
118
|
+
setupListeners()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if follow {
|
|
122
|
+
userLocationLayer.isAutoZoomEnabled = true
|
|
123
|
+
guard let mapView = mapView else { return }
|
|
124
|
+
let width = mapView.bounds.width
|
|
125
|
+
let height = mapView.bounds.height
|
|
126
|
+
userLocationLayer.setAnchorWithAnchorNormal(
|
|
127
|
+
CGPoint(x: 0.5 * width, y: 0.5 * height),
|
|
128
|
+
anchorCourse: CGPoint(x: 0.5 * width, y: 0.83 * height))
|
|
129
|
+
} else {
|
|
130
|
+
userLocationLayer.isAutoZoomEnabled = false
|
|
131
|
+
userLocationLayer.resetAnchor()
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
@objc public var maxFps: Float = 60 {
|
|
135
|
+
didSet {
|
|
136
|
+
if maxFps <= 0 || maxFps > 60 {
|
|
137
|
+
maxFps = 60
|
|
138
|
+
}
|
|
139
|
+
guard let map = mapView?.mapWindow else { return }
|
|
140
|
+
map.setMaxFpsWithFps(maxFps)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
override init(frame: CGRect) {
|
|
145
|
+
super.init(frame: frame)
|
|
146
|
+
initImpl()
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@available(*, unavailable)
|
|
150
|
+
required init?(coder _: NSCoder) {
|
|
151
|
+
fatalError("init(coder:) is not implemented.")
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private func initImpl() {
|
|
155
|
+
runOnMainThread {
|
|
156
|
+
self.initMapView()
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private func initMapView() {
|
|
161
|
+
mapView = YMKMapView(frame: bounds, vulkanPreferred: YamapView.isM1Simulator())
|
|
162
|
+
mapView.mapWindow.map.mapType = .map
|
|
163
|
+
applyProperties()
|
|
164
|
+
insertSubview(mapView, at: 0)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@objc private func setupListeners() {
|
|
168
|
+
guard let delegate = delegate, let map = mapView?.mapWindow?.map else { return }
|
|
169
|
+
|
|
170
|
+
if loadListener == nil {
|
|
171
|
+
loadListener = MapLoadListener(callback: nil, mapDelegate: delegate)
|
|
172
|
+
map.setMapLoadedListenerWith(loadListener!)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if cameraListener == nil {
|
|
176
|
+
let cameraDelegate = CameraListener(callback: nil, delegate: delegate)
|
|
177
|
+
cameraListener = cameraDelegate
|
|
178
|
+
map.addCameraListener(with: cameraDelegate)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if mapInputListener == nil {
|
|
182
|
+
mapInputListener = MapInputListener(delegate: delegate)
|
|
183
|
+
map.addInputListener(with: mapInputListener!)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if userLocationListener == nil {
|
|
187
|
+
userLocationListener = UserLocationObjectListener(callback: updateUserIcon)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if userLocationLayer == nil {
|
|
191
|
+
userLocationLayer = YMKMapKit.sharedInstance().createUserLocationLayer(
|
|
192
|
+
with: mapView.mapWindow)
|
|
193
|
+
userLocationLayer.setObjectListenerWith(userLocationListener)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if userLocationLayer != nil {
|
|
197
|
+
userLocationLayer.setVisibleWithOn(showUserPosition)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
////////////////////////
|
|
202
|
+
///////METHODS//////////
|
|
203
|
+
////////////////////////
|
|
204
|
+
|
|
205
|
+
@objc public func setLogoPosition(position: NSDictionary) {
|
|
206
|
+
guard let map = mapView?.mapWindow?.map else { return }
|
|
207
|
+
let logoPosition = LogoPosition(position: position)
|
|
208
|
+
map.logo.setAlignmentWith(
|
|
209
|
+
YMKLogoAlignment(
|
|
210
|
+
horizontalAlignment: logoPosition.horizontal,
|
|
211
|
+
verticalAlignment: logoPosition.vertical))
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
@objc public func setLogoPadding(vertical: Int, horizontal: Int) {
|
|
215
|
+
guard let map = mapView?.mapWindow?.map else { return }
|
|
216
|
+
map.logo.setPaddingWith(
|
|
217
|
+
YMKLogoPadding(horizontalPadding: UInt(horizontal), verticalPadding: UInt(vertical)))
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@objc public func setMapStyle(style: [String: Any]) {
|
|
221
|
+
guard let map = mapView?.mapWindow?.map else { return }
|
|
222
|
+
guard let data = try? JSONSerialization.data(withJSONObject: style, options: []),
|
|
223
|
+
let styleString = String(data: data, encoding: .utf8)
|
|
224
|
+
else {
|
|
225
|
+
os_log("Failed to serialize style dictionary to JSON", log: yamapLogger, type: .error)
|
|
226
|
+
return
|
|
227
|
+
}
|
|
228
|
+
map.setMapStyleWithStyle(styleString)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@objc func setLocale(_ locale: String) {
|
|
232
|
+
YRTI18nManagerFactory.setLocaleWithLocale(locale)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@objc public func setShowUserPositionState(_ show: Bool) {
|
|
236
|
+
showUserPosition = show
|
|
237
|
+
if userLocationLayer != nil {
|
|
238
|
+
userLocationLayer.setVisibleWithOn(show)
|
|
239
|
+
}
|
|
240
|
+
if show {
|
|
241
|
+
updateUserIcon()
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
@objc public func setUserLocationIcon(path: String) {
|
|
246
|
+
let helper = ResolveImageHelper.shared
|
|
247
|
+
let baseSize: CGFloat = 50.0
|
|
248
|
+
|
|
249
|
+
let image = helper.resolveUIImage(uri: path as NSString) { [weak self] loadedImage in
|
|
250
|
+
guard let self = self, let loadedImage = loadedImage else {
|
|
251
|
+
os_log("Failed to load image from URI: %@", log: yamapLogger, type: .error, path)
|
|
252
|
+
return
|
|
253
|
+
}
|
|
254
|
+
let resizedImage = helper.resizeImage(loadedImage, toWidth: baseSize)
|
|
255
|
+
self.userLocationImage = resizedImage
|
|
256
|
+
self.updateUserIcon()
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if let image = image {
|
|
260
|
+
let resizedImage = helper.resizeImage(image, toWidth: baseSize)
|
|
261
|
+
userLocationImage = resizedImage
|
|
262
|
+
updateUserIcon()
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@objc public func updateUserIcon() {
|
|
267
|
+
DispatchQueue.main.async { [weak self] in
|
|
268
|
+
guard let self = self else { return }
|
|
269
|
+
|
|
270
|
+
let userIconStyle = YMKIconStyle()
|
|
271
|
+
userIconStyle.scale = self.userLocationIconScale as NSNumber
|
|
272
|
+
|
|
273
|
+
if let image = self.userLocationImage {
|
|
274
|
+
self.userLocationListener?.userLocationView?.pin.setIconWith(
|
|
275
|
+
image, style: userIconStyle)
|
|
276
|
+
self.userLocationListener?.userLocationView?.arrow.setIconWith(
|
|
277
|
+
image, style: userIconStyle)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if let circle = self.userLocationListener?.userLocationView?.accuracyCircle {
|
|
281
|
+
circle.fillColor = self.userLocationAccuracyFillColor
|
|
282
|
+
circle.strokeColor = self.userLocationAccuracyStrokeColor
|
|
283
|
+
circle.strokeWidth = self.userLocationAccuracyStrokeWidth
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
@objc func getLocale(_ resolve: RCTPromiseResolveBlock, reject _: RCTPromiseRejectBlock) {
|
|
289
|
+
resolve(YRTI18nManagerFactory.getLocale())
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
@objc func resetLocale(_ resolve: RCTPromiseResolveBlock, reject _: RCTPromiseRejectBlock) {
|
|
293
|
+
YRTI18nManagerFactory.setLocaleWithLocale(nil)
|
|
294
|
+
resolve(nil)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
@objc func fitMakers(_ markers: [YMKPoint]) {
|
|
298
|
+
guard let map = mapView?.mapWindow?.map else { return }
|
|
299
|
+
if markers.isEmpty {
|
|
300
|
+
return
|
|
301
|
+
}
|
|
302
|
+
let latitudes = markers.map { $0.latitude }
|
|
303
|
+
let longitudes = markers.map { $0.longitude }
|
|
304
|
+
if latitudes.isEmpty || longitudes.isEmpty {
|
|
305
|
+
return
|
|
306
|
+
}
|
|
307
|
+
let minLatitude = latitudes.min() ?? 0
|
|
308
|
+
let minLongitude = longitudes.min() ?? 0
|
|
309
|
+
let maxLatitude = latitudes.max() ?? 0
|
|
310
|
+
let maxLongitude = longitudes.max() ?? 0
|
|
311
|
+
let southWest = YMKPoint(latitude: minLatitude, longitude: minLongitude)
|
|
312
|
+
let northEast = YMKPoint(latitude: maxLatitude, longitude: maxLongitude)
|
|
313
|
+
let box = YMKBoundingBox(southWest: southWest, northEast: northEast)
|
|
314
|
+
|
|
315
|
+
let camera = map.cameraPosition(with: YMKGeometry(boundingBox: box))
|
|
316
|
+
let paddingZoom: Float = 0.75
|
|
317
|
+
let adjustedZoom = max(camera.zoom - paddingZoom, 0)
|
|
318
|
+
|
|
319
|
+
let adjustedCamera = YMKCameraPosition(
|
|
320
|
+
target: camera.target,
|
|
321
|
+
zoom: adjustedZoom,
|
|
322
|
+
azimuth: camera.azimuth,
|
|
323
|
+
tilt: camera.tilt
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
let anim = YMKAnimation(type: .smooth, duration: 0.7)
|
|
327
|
+
map.move(with: adjustedCamera, animation: anim)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
@objc public func getCameraPosition() -> [String: Any]? {
|
|
331
|
+
guard let map = mapView?.mapWindow?.map else { return nil }
|
|
332
|
+
let position = map.cameraPosition
|
|
333
|
+
let result: [String: Any] = [
|
|
334
|
+
"lat": position.target.latitude,
|
|
335
|
+
"lon": position.target.longitude,
|
|
336
|
+
"zoom": Double(position.zoom),
|
|
337
|
+
"azimuth": Double(position.azimuth),
|
|
338
|
+
"tilt": Double(position.tilt),
|
|
339
|
+
]
|
|
340
|
+
return result
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
@objc public func getMapObjectCount() -> NSNumber {
|
|
344
|
+
guard let map = mapView?.mapWindow?.map else { return 0 }
|
|
345
|
+
let visitor = MapObjectCountVisitor()
|
|
346
|
+
map.mapObjects.traverse(with: visitor)
|
|
347
|
+
return NSNumber(value: visitor.count)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
@objc public func getVisibleRegion() -> [String: Any]? {
|
|
351
|
+
guard let mapWindow = mapView?.mapWindow else { return nil }
|
|
352
|
+
let region = mapWindow.map.visibleRegion
|
|
353
|
+
return [
|
|
354
|
+
"bottomLeft": ["lat": region.bottomLeft.latitude, "lon": region.bottomLeft.longitude],
|
|
355
|
+
"bottomRight": ["lat": region.bottomRight.latitude, "lon": region.bottomRight.longitude],
|
|
356
|
+
"topLeft": ["lat": region.topLeft.latitude, "lon": region.topLeft.longitude],
|
|
357
|
+
"topRight": ["lat": region.topRight.latitude, "lon": region.topRight.longitude],
|
|
358
|
+
]
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
@objc public func getScreenPoints(_ points: [[String: Double]]) -> [[String: Double]] {
|
|
362
|
+
guard let mapWindow = mapView?.mapWindow else { return [] }
|
|
363
|
+
return points.compactMap { p -> [String: Double]? in
|
|
364
|
+
guard let lat = p["lat"], let lon = p["lon"] else { return nil }
|
|
365
|
+
guard
|
|
366
|
+
let screenPoint = mapWindow.worldToScreen(
|
|
367
|
+
withWorldPoint: YMKPoint(latitude: lat, longitude: lon))
|
|
368
|
+
else { return nil }
|
|
369
|
+
return ["x": Double(screenPoint.x), "y": Double(screenPoint.y)]
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
@objc public func getWorldPoints(_ points: [[String: Double]]) -> [[String: Double]] {
|
|
374
|
+
guard let mapWindow = mapView?.mapWindow else { return [] }
|
|
375
|
+
return points.compactMap { p -> [String: Double]? in
|
|
376
|
+
guard let x = p["x"], let y = p["y"] else { return nil }
|
|
377
|
+
guard
|
|
378
|
+
let worldPoint = mapWindow.screenToWorld(
|
|
379
|
+
with: YMKScreenPoint(x: Float(x), y: Float(y)))
|
|
380
|
+
else { return nil }
|
|
381
|
+
return ["lat": worldPoint.latitude, "lon": worldPoint.longitude]
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
@objc public func move(
|
|
386
|
+
_ latitude: Double, _ longitude: Double, _ zoom: Float, _ azimuth: Float, _ tilt: Float
|
|
387
|
+
) {
|
|
388
|
+
guard latitude.isFinite, longitude.isFinite, zoom.isFinite, azimuth.isFinite, tilt.isFinite
|
|
389
|
+
else { return }
|
|
390
|
+
guard let m = mapView?.mapWindow?.map else { return }
|
|
391
|
+
m.move(
|
|
392
|
+
with: YMKCameraPosition(
|
|
393
|
+
target: YMKPoint(latitude: latitude, longitude: longitude),
|
|
394
|
+
zoom: zoom,
|
|
395
|
+
azimuth: azimuth,
|
|
396
|
+
tilt: tilt
|
|
397
|
+
)
|
|
398
|
+
)
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
static func isM1Simulator() -> Bool {
|
|
402
|
+
#if targetEnvironment(simulator) && arch(arm64)
|
|
403
|
+
return true
|
|
404
|
+
#else
|
|
405
|
+
return false
|
|
406
|
+
#endif
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
@objc public func setCenter(
|
|
410
|
+
latitude: Double,
|
|
411
|
+
longitude: Double,
|
|
412
|
+
zoom: Float,
|
|
413
|
+
azimuth: Float,
|
|
414
|
+
tilt: Float,
|
|
415
|
+
duration: Float,
|
|
416
|
+
animation: String
|
|
417
|
+
) {
|
|
418
|
+
guard latitude.isFinite, longitude.isFinite, zoom.isFinite, azimuth.isFinite, tilt.isFinite
|
|
419
|
+
else { return }
|
|
420
|
+
guard let map = mapView?.mapWindow?.map else { return }
|
|
421
|
+
let animType: YMKAnimationType
|
|
422
|
+
switch animation {
|
|
423
|
+
case "LINEAR":
|
|
424
|
+
animType = .linear
|
|
425
|
+
default:
|
|
426
|
+
animType = .smooth
|
|
427
|
+
}
|
|
428
|
+
let newPosition = YMKCameraPosition(
|
|
429
|
+
target: YMKPoint(latitude: latitude, longitude: longitude), zoom: Float(zoom),
|
|
430
|
+
azimuth: azimuth, tilt: tilt)
|
|
431
|
+
if duration > 0 {
|
|
432
|
+
let anim = YMKAnimation(type: animType, duration: Float(duration) / 1000.0)
|
|
433
|
+
map.move(with: newPosition, animation: anim)
|
|
434
|
+
} else {
|
|
435
|
+
map.move(with: newPosition)
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
@objc(setZoomWithZoom:duration:animation:)
|
|
440
|
+
public func setZoom(
|
|
441
|
+
zoom: Float,
|
|
442
|
+
duration: Float,
|
|
443
|
+
animation: String
|
|
444
|
+
) {
|
|
445
|
+
guard zoom.isFinite else { return }
|
|
446
|
+
guard let map = mapView?.mapWindow?.map else { return }
|
|
447
|
+
let animType: YMKAnimationType
|
|
448
|
+
switch animation {
|
|
449
|
+
case "LINEAR":
|
|
450
|
+
animType = .linear
|
|
451
|
+
default:
|
|
452
|
+
animType = .smooth
|
|
453
|
+
}
|
|
454
|
+
let prevPosition = map.cameraPosition
|
|
455
|
+
let newPosition = YMKCameraPosition(
|
|
456
|
+
target: prevPosition.target, zoom: Float(zoom), azimuth: prevPosition.azimuth,
|
|
457
|
+
tilt: prevPosition.tilt)
|
|
458
|
+
if duration > 0 {
|
|
459
|
+
let anim = YMKAnimation(type: animType, duration: Float(duration) / 1000.0)
|
|
460
|
+
map.move(with: newPosition, animation: anim)
|
|
461
|
+
} else {
|
|
462
|
+
map.move(with: newPosition)
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
@objc public func fitAllMarkers() {
|
|
467
|
+
var markerPoints: [YMKPoint] = []
|
|
468
|
+
|
|
469
|
+
for marker in mapObjects {
|
|
470
|
+
if marker.visible, let point = marker.point, point.lat.isFinite, point.lon.isFinite {
|
|
471
|
+
markerPoints.append(YMKPoint(latitude: point.lat, longitude: point.lon))
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if markerPoints.isEmpty {
|
|
476
|
+
return
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
fitMakers(markerPoints)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
@objc func cleanMap() {
|
|
483
|
+
guard let map = mapView?.mapWindow?.map else { return }
|
|
484
|
+
map.mapObjects.clear()
|
|
485
|
+
mapObjects.removeAll()
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
static func requiresMainQueueSetup() -> Bool {
|
|
489
|
+
return true
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
@objc override public func insertReactSubview(_ subview: UIView!, at atIndex: Int) {
|
|
493
|
+
let safeIndex = min(atIndex, subviews.count)
|
|
494
|
+
insertSubview(subview, at: safeIndex)
|
|
495
|
+
if let markerContainer = subview as? UIView,
|
|
496
|
+
let markerView = markerContainer.value(forKey: "contentView") as? YamapLiteMarker
|
|
497
|
+
{
|
|
498
|
+
let lat = markerView.point?.lat ?? 0.0
|
|
499
|
+
let lon = markerView.point?.lon ?? 0.0
|
|
500
|
+
let viewPlacemark = mapView.mapWindow.map.mapObjects.addPlacemark()
|
|
501
|
+
|
|
502
|
+
if lat.isFinite, lon.isFinite {
|
|
503
|
+
viewPlacemark.geometry = YMKPoint(latitude: lat, longitude: lon)
|
|
504
|
+
}
|
|
505
|
+
markerView.setMapObject(object: viewPlacemark)
|
|
506
|
+
if !mapObjects.contains(where: { $0 === markerView }) {
|
|
507
|
+
mapObjects.append(markerView)
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
else if let circleContainer = subview as? UIView,
|
|
512
|
+
let circleView = circleContainer.value(forKey: "contentView") as? YamapLiteCircle
|
|
513
|
+
{
|
|
514
|
+
if circleView.radius > 0,
|
|
515
|
+
circleView.circleCenter.latitude.isFinite,
|
|
516
|
+
circleView.circleCenter.longitude.isFinite
|
|
517
|
+
{
|
|
518
|
+
let nativeMapObjects = mapView.mapWindow.map.mapObjects
|
|
519
|
+
let circleObject = nativeMapObjects.addCircle(with: circleView.circle)
|
|
520
|
+
circleView.setMapObject(object: circleObject)
|
|
521
|
+
}
|
|
522
|
+
} else if let polygonContainer = subview as? UIView,
|
|
523
|
+
let polygonView = polygonContainer.value(forKey: "contentView") as? YamapLitePolygon
|
|
524
|
+
{
|
|
525
|
+
let nativeMapObjects = mapView.mapWindow.map.mapObjects
|
|
526
|
+
let polygonObject = nativeMapObjects.addPolygon(with: polygonView.polygon)
|
|
527
|
+
polygonView.setMapObject(object: polygonObject)
|
|
528
|
+
} else if let polylineContainer = subview as? UIView,
|
|
529
|
+
let polylineView = polylineContainer.value(forKey: "contentView") as? YamapLitePolyline
|
|
530
|
+
{
|
|
531
|
+
let nativeMapObjects = mapView.mapWindow.map.mapObjects
|
|
532
|
+
let polylineObject = nativeMapObjects.addPolyline(with: polylineView.polyline)
|
|
533
|
+
polylineView.setMapObject(object: polylineObject)
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
@objc override public func removeReactSubview(_ subview: UIView!) {
|
|
538
|
+
subview.removeFromSuperview()
|
|
539
|
+
guard let container = subview as? UIView,
|
|
540
|
+
let contentView = container.value(forKey: "contentView") as? UIView
|
|
541
|
+
else { return }
|
|
542
|
+
|
|
543
|
+
let nativeMapObjects = mapView.mapWindow.map.mapObjects
|
|
544
|
+
|
|
545
|
+
if let markerView = contentView as? YamapLiteMarker {
|
|
546
|
+
if let obj = markerView.mapObject, obj.isValid {
|
|
547
|
+
nativeMapObjects.remove(with: obj)
|
|
548
|
+
}
|
|
549
|
+
mapObjects.removeAll { $0 === markerView }
|
|
550
|
+
} else if let circleView = contentView as? YamapLiteCircle {
|
|
551
|
+
if let obj = circleView.mapObject, obj.isValid {
|
|
552
|
+
nativeMapObjects.remove(with: obj)
|
|
553
|
+
}
|
|
554
|
+
} else if let polygonView = contentView as? YamapLitePolygon {
|
|
555
|
+
if let obj = polygonView.mapObject, obj.isValid {
|
|
556
|
+
nativeMapObjects.remove(with: obj)
|
|
557
|
+
}
|
|
558
|
+
} else if let polylineView = contentView as? YamapLitePolyline {
|
|
559
|
+
if let obj = polylineView.mapObject, obj.isValid {
|
|
560
|
+
nativeMapObjects.remove(with: obj)
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
func runOnMainThread(_ block: @escaping () -> Void) {
|
|
566
|
+
if Thread.isMainThread { block() } else { DispatchQueue.main.async { block() } }
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
private final class MapObjectCountVisitor: NSObject, YMKMapObjectVisitor {
|
|
571
|
+
var count = 0
|
|
572
|
+
|
|
573
|
+
func onPlacemarkVisited(withPlacemark placemark: YMKPlacemarkMapObject) { count += 1 }
|
|
574
|
+
func onPolylineVisited(withPolyline polyline: YMKPolylineMapObject) { count += 1 }
|
|
575
|
+
func onPolygonVisited(withPolygon: YMKPolygonMapObject) { count += 1 }
|
|
576
|
+
func onCircleVisited(withCircle: YMKCircleMapObject) { count += 1 }
|
|
577
|
+
|
|
578
|
+
func onCollectionVisitStart(with collection: YMKMapObjectCollection) -> Bool { true }
|
|
579
|
+
func onCollectionVisitEnd(with collection: YMKMapObjectCollection) {}
|
|
580
|
+
func onClusterizedCollectionVisitStart(with collection: YMKClusterizedPlacemarkCollection) -> Bool
|
|
581
|
+
{
|
|
582
|
+
true
|
|
583
|
+
}
|
|
584
|
+
func onClusterizedCollectionVisitEnd(with collection: YMKClusterizedPlacemarkCollection) {}
|
|
585
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import YandexMapsMobile
|
|
4
|
+
|
|
5
|
+
class CameraListener: NSObject, YMKMapCameraListener {
|
|
6
|
+
private let callback: RCTDirectEventBlock?
|
|
7
|
+
private weak var delegate: YamapViewComponentDelegate?
|
|
8
|
+
|
|
9
|
+
init(callback: RCTDirectEventBlock?, delegate: YamapViewComponentDelegate?) {
|
|
10
|
+
self.callback = callback
|
|
11
|
+
self.delegate = delegate
|
|
12
|
+
super.init()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
func onCameraPositionChanged(with _: YMKMap,
|
|
16
|
+
cameraPosition: YMKCameraPosition,
|
|
17
|
+
cameraUpdateReason : YMKCameraUpdateReason,
|
|
18
|
+
finished: Bool)
|
|
19
|
+
{
|
|
20
|
+
let target = cameraPosition.target
|
|
21
|
+
let reasonString: String
|
|
22
|
+
switch cameraUpdateReason {
|
|
23
|
+
case .gestures:
|
|
24
|
+
reasonString = "GESTURES"
|
|
25
|
+
case .application:
|
|
26
|
+
reasonString = "APPLICATION"
|
|
27
|
+
@unknown default:
|
|
28
|
+
reasonString = "GESTURES"
|
|
29
|
+
}
|
|
30
|
+
let params: [String: Any] = [
|
|
31
|
+
"lat": target.latitude,
|
|
32
|
+
"lon": target.longitude,
|
|
33
|
+
"zoom": Double(cameraPosition.zoom),
|
|
34
|
+
"azimuth": Double(cameraPosition.azimuth),
|
|
35
|
+
"tilt": Double(cameraPosition.tilt),
|
|
36
|
+
"finished": finished,
|
|
37
|
+
"target": 0.0,
|
|
38
|
+
"reason": reasonString
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
DispatchQueue.main.async { [weak self] in
|
|
42
|
+
guard let self = self else { return }
|
|
43
|
+
if let callback = self.callback {
|
|
44
|
+
callback(params)
|
|
45
|
+
return
|
|
46
|
+
} else if let delegate = self.delegate {
|
|
47
|
+
delegate.handleOnCameraPositionChange(coords: params)
|
|
48
|
+
if finished {
|
|
49
|
+
delegate.handleOnCameraPositionChangeEnd(coords: params)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import YandexMapsMobile
|
|
4
|
+
|
|
5
|
+
class ClusterListener: NSObject, YMKClusterListener, YMKClusterTapListener {
|
|
6
|
+
private let callback: RCTDirectEventBlock?
|
|
7
|
+
private weak var delegate: YamapViewComponentDelegate?
|
|
8
|
+
private weak var clusteredView: ClusteredYamapView?
|
|
9
|
+
|
|
10
|
+
init(callback: RCTDirectEventBlock?, delegate: YamapViewComponentDelegate?) {
|
|
11
|
+
self.callback = callback
|
|
12
|
+
self.delegate = delegate
|
|
13
|
+
super.init()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
func setClusteredView(_ view: ClusteredYamapView) {
|
|
17
|
+
self.clusteredView = view
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func onClusterAdded(with cluster: YMKCluster) {
|
|
21
|
+
if let view = clusteredView {
|
|
22
|
+
let clusterSize = cluster.size
|
|
23
|
+
if let image = view.clusterImage(clusterSize: Int(clusterSize)) {
|
|
24
|
+
cluster.appearance.setIconWith(image)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
cluster.addClusterTapListener(with: self)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
func onClusterTap(with cluster: YMKCluster) -> Bool {
|
|
31
|
+
var lastKnownMarkers: [YMKPoint] = []
|
|
32
|
+
for placemark in cluster.placemarks {
|
|
33
|
+
lastKnownMarkers.append(placemark.geometry)
|
|
34
|
+
}
|
|
35
|
+
clusteredView?.fitMakers(lastKnownMarkers)
|
|
36
|
+
return true
|
|
37
|
+
}
|
|
38
|
+
}
|