@granite-js/naver-map 1.0.0

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.
Files changed (104) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/GraniteNaverMap.podspec +81 -0
  3. package/android/build.gradle +160 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/builtinProvider/java/run/granite/navermap/builtinProvider/BuiltInGraniteNaverMapProvider.kt +549 -0
  6. package/android/src/main/AndroidManifest.xml +3 -0
  7. package/android/src/main/java/run/granite/navermap/GraniteNaverMapEvents.kt +91 -0
  8. package/android/src/main/java/run/granite/navermap/GraniteNaverMapPackage.kt +16 -0
  9. package/android/src/main/java/run/granite/navermap/GraniteNaverMapProvider.kt +242 -0
  10. package/android/src/main/java/run/granite/navermap/GraniteNaverMapRegistry.kt +116 -0
  11. package/android/src/main/java/run/granite/navermap/GraniteNaverMapView.kt +732 -0
  12. package/android/src/newarch/java/run/granite/navermap/GraniteNaverMapViewManager.kt +446 -0
  13. package/android/src/oldarch/java/run/granite/navermap/GraniteNaverMapViewManager.kt +249 -0
  14. package/dist/module/NaverMapView.js +110 -0
  15. package/dist/module/NaverMapView.js.map +1 -0
  16. package/dist/module/index.js +6 -0
  17. package/dist/module/index.js.map +1 -0
  18. package/dist/module/internals/colorUtils.js +624 -0
  19. package/dist/module/internals/colorUtils.js.map +1 -0
  20. package/dist/module/internals/context.js +8 -0
  21. package/dist/module/internals/context.js.map +1 -0
  22. package/dist/module/internals/id.js +10 -0
  23. package/dist/module/internals/id.js.map +1 -0
  24. package/dist/module/internals/useMapOverlay.js +44 -0
  25. package/dist/module/internals/useMapOverlay.js.map +1 -0
  26. package/dist/module/internals/usePreservedReference.js +36 -0
  27. package/dist/module/internals/usePreservedReference.js.map +1 -0
  28. package/dist/module/overlays/ArrowheadPath.js +37 -0
  29. package/dist/module/overlays/ArrowheadPath.js.map +1 -0
  30. package/dist/module/overlays/Circle.js +35 -0
  31. package/dist/module/overlays/Circle.js.map +1 -0
  32. package/dist/module/overlays/GroundOverlay.js +30 -0
  33. package/dist/module/overlays/GroundOverlay.js.map +1 -0
  34. package/dist/module/overlays/InfoWindow.js +32 -0
  35. package/dist/module/overlays/InfoWindow.js.map +1 -0
  36. package/dist/module/overlays/Marker.js +37 -0
  37. package/dist/module/overlays/Marker.js.map +1 -0
  38. package/dist/module/overlays/Path.js +41 -0
  39. package/dist/module/overlays/Path.js.map +1 -0
  40. package/dist/module/overlays/Polygon.js +51 -0
  41. package/dist/module/overlays/Polygon.js.map +1 -0
  42. package/dist/module/overlays/Polyline.js +60 -0
  43. package/dist/module/overlays/Polyline.js.map +1 -0
  44. package/dist/module/overlays/index.js +11 -0
  45. package/dist/module/overlays/index.js.map +1 -0
  46. package/dist/module/package.json +1 -0
  47. package/dist/module/specs/GraniteNaverMapViewNativeComponent.ts +352 -0
  48. package/dist/module/types/Coord.js +2 -0
  49. package/dist/module/types/Coord.js.map +1 -0
  50. package/dist/module/types/index.js +29 -0
  51. package/dist/module/types/index.js.map +1 -0
  52. package/dist/typescript/NaverMapView.d.ts +41 -0
  53. package/dist/typescript/index.d.ts +3 -0
  54. package/dist/typescript/internals/colorUtils.d.ts +10 -0
  55. package/dist/typescript/internals/context.d.ts +8 -0
  56. package/dist/typescript/internals/id.d.ts +1 -0
  57. package/dist/typescript/internals/useMapOverlay.d.ts +15 -0
  58. package/dist/typescript/internals/usePreservedReference.d.ts +6 -0
  59. package/dist/typescript/overlays/ArrowheadPath.d.ts +11 -0
  60. package/dist/typescript/overlays/Circle.d.ts +10 -0
  61. package/dist/typescript/overlays/GroundOverlay.d.ts +11 -0
  62. package/dist/typescript/overlays/InfoWindow.d.ts +14 -0
  63. package/dist/typescript/overlays/Marker.d.ts +16 -0
  64. package/dist/typescript/overlays/Path.d.ts +15 -0
  65. package/dist/typescript/overlays/Polygon.d.ts +10 -0
  66. package/dist/typescript/overlays/Polyline.d.ts +11 -0
  67. package/dist/typescript/overlays/index.d.ts +16 -0
  68. package/dist/typescript/specs/GraniteNaverMapViewNativeComponent.d.ts +92 -0
  69. package/dist/typescript/types/Coord.d.ts +4 -0
  70. package/dist/typescript/types/index.d.ts +55 -0
  71. package/ios/GraniteNaverMap-Bridging-Header.h +20 -0
  72. package/ios/GraniteNaverMapProvider.swift +312 -0
  73. package/ios/GraniteNaverMapRegistry.swift +91 -0
  74. package/ios/GraniteNaverMapView.h +15 -0
  75. package/ios/GraniteNaverMapView.mm +390 -0
  76. package/ios/GraniteNaverMapViewImpl.swift +496 -0
  77. package/ios/GraniteNaverMapViewManager.m +67 -0
  78. package/ios/GraniteNaverMapViewManager.swift +133 -0
  79. package/ios/GraniteNaverMapViewWrapper.swift +215 -0
  80. package/ios/builtinProvider/BuiltInNaverMapProvider.swift +489 -0
  81. package/ios/builtinProvider/GraniteNaverMapMarkerData.swift +66 -0
  82. package/ios/builtinProvider/NMFMarker+Extension.swift +65 -0
  83. package/ios/builtinProvider/RCTConvert+NMFMapView.h +17 -0
  84. package/ios/builtinProvider/RCTConvert+NMFMapView.m +67 -0
  85. package/package.json +103 -0
  86. package/src/NaverMapView.tsx +168 -0
  87. package/src/index.tsx +3 -0
  88. package/src/internals/colorUtils.ts +697 -0
  89. package/src/internals/context.ts +14 -0
  90. package/src/internals/id.ts +9 -0
  91. package/src/internals/useMapOverlay.ts +59 -0
  92. package/src/internals/usePreservedReference.ts +41 -0
  93. package/src/overlays/ArrowheadPath.ts +71 -0
  94. package/src/overlays/Circle.ts +68 -0
  95. package/src/overlays/GroundOverlay.ts +62 -0
  96. package/src/overlays/InfoWindow.ts +68 -0
  97. package/src/overlays/Marker.ts +83 -0
  98. package/src/overlays/Path.ts +87 -0
  99. package/src/overlays/Polygon.ts +83 -0
  100. package/src/overlays/Polyline.ts +93 -0
  101. package/src/overlays/index.ts +23 -0
  102. package/src/specs/GraniteNaverMapViewNativeComponent.ts +352 -0
  103. package/src/types/Coord.ts +4 -0
  104. package/src/types/index.ts +78 -0
@@ -0,0 +1,549 @@
1
+ package run.granite.navermap.builtinProvider
2
+
3
+ import android.content.Context
4
+ import run.granite.navermap.GraniteNaverMapProvider
5
+ import run.granite.navermap.GraniteNaverMapProviderFactory
6
+ import run.granite.navermap.GraniteNaverMapProviderDelegate
7
+ import run.granite.navermap.GraniteNaverMapCameraPosition
8
+ import run.granite.navermap.GraniteNaverMapCoordinate
9
+ import run.granite.navermap.GraniteNaverMapBounds
10
+ import run.granite.navermap.GraniteNaverMapType
11
+ import run.granite.navermap.GraniteNaverMapLocationTrackingMode
12
+ import run.granite.navermap.GraniteNaverMapMarkerData
13
+ import run.granite.navermap.GraniteNaverMapPolylineData
14
+ import run.granite.navermap.GraniteNaverMapPolygonData
15
+ import run.granite.navermap.GraniteNaverMapCircleData
16
+ import run.granite.navermap.GraniteNaverMapPathData
17
+ import android.graphics.BitmapFactory
18
+ import android.view.View
19
+ import android.widget.FrameLayout
20
+ import com.naver.maps.geometry.LatLng
21
+ import com.naver.maps.geometry.LatLngBounds
22
+ import com.naver.maps.map.CameraAnimation
23
+ import com.naver.maps.map.CameraPosition
24
+ import com.naver.maps.map.CameraUpdate
25
+ import com.naver.maps.map.LocationTrackingMode
26
+ import com.naver.maps.map.MapView
27
+ import com.naver.maps.map.NaverMap
28
+ import com.naver.maps.map.NaverMapOptions
29
+ import com.naver.maps.map.overlay.Marker
30
+ import com.naver.maps.map.overlay.OverlayImage
31
+ import com.naver.maps.map.overlay.PolylineOverlay
32
+ import com.naver.maps.map.overlay.PolygonOverlay
33
+ import com.naver.maps.map.overlay.CircleOverlay
34
+ import com.naver.maps.map.overlay.PathOverlay
35
+ import java.net.URL
36
+ import kotlin.concurrent.thread
37
+
38
+ /**
39
+ * Factory for creating BuiltInGraniteNaverMapProvider instances.
40
+ * Each call to createProvider() returns a new instance.
41
+ */
42
+ class BuiltInGraniteNaverMapProviderFactory : GraniteNaverMapProviderFactory {
43
+ override fun createProvider(context: Context): GraniteNaverMapProvider {
44
+ return BuiltInGraniteNaverMapProvider(context)
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Built-in provider using NMapsMap SDK
50
+ */
51
+ class BuiltInGraniteNaverMapProvider(private val context: Context) : GraniteNaverMapProvider {
52
+ private var containerView: FrameLayout? = null
53
+ private var mapView: MapView? = null
54
+ private var naverMap: NaverMap? = null
55
+ private var delegate: GraniteNaverMapProviderDelegate? = null
56
+ private var mapReady = false
57
+ private var mapInitialized = false
58
+
59
+ private val density = context.resources.displayMetrics.density
60
+
61
+ private val markers: MutableMap<String, Marker> = mutableMapOf()
62
+ private val polylines: MutableMap<String, PolylineOverlay> = mutableMapOf()
63
+ private val polygons: MutableMap<String, PolygonOverlay> = mutableMapOf()
64
+ private val circles: MutableMap<String, CircleOverlay> = mutableMapOf()
65
+ private val paths: MutableMap<String, PathOverlay> = mutableMapOf()
66
+
67
+ private fun dpToPx(dp: Int): Int = (dp * density).toInt()
68
+ private fun dpToPx(dp: Float): Int = (dp * density).toInt()
69
+
70
+ override fun createMapView(context: Context): View {
71
+ val container = FrameLayout(context)
72
+ containerView = container
73
+
74
+ val map = MapView(context, NaverMapOptions())
75
+ mapView = map
76
+ container.addView(map, FrameLayout.LayoutParams(
77
+ FrameLayout.LayoutParams.MATCH_PARENT,
78
+ FrameLayout.LayoutParams.MATCH_PARENT
79
+ ))
80
+
81
+ return container
82
+ }
83
+
84
+ override fun setDelegate(delegate: GraniteNaverMapProviderDelegate?) {
85
+ this.delegate = delegate
86
+ }
87
+
88
+ override fun onAttachedToWindow() {
89
+ // Lifecycle is handled in onSizeChanged
90
+ }
91
+
92
+ override fun onDetachedFromWindow() {
93
+ mapView?.onPause()
94
+ mapView?.onStop()
95
+ mapView?.onDestroy()
96
+ }
97
+
98
+ override fun onSizeChanged(width: Int, height: Int) {
99
+ if (!mapInitialized && width > 0 && height > 0) {
100
+ mapInitialized = true
101
+ initializeMap()
102
+ }
103
+ }
104
+
105
+ override fun onHostResume() {
106
+ if (mapReady) {
107
+ mapView?.onResume()
108
+ }
109
+ }
110
+
111
+ override fun onHostPause() {
112
+ if (mapReady) {
113
+ mapView?.onPause()
114
+ }
115
+ }
116
+
117
+ private fun initializeMap() {
118
+ mapView?.onCreate(null)
119
+ mapView?.onStart()
120
+ mapView?.onResume()
121
+
122
+ mapView?.getMapAsync { map ->
123
+ naverMap = map
124
+ mapReady = true
125
+ setupMapListeners(map)
126
+ delegate?.onMapInitialized()
127
+ }
128
+ }
129
+
130
+ private fun setupMapListeners(map: NaverMap) {
131
+ map.addOnCameraIdleListener {
132
+ val position = map.cameraPosition
133
+ val contentBounds = map.contentBounds
134
+ val coveringBounds = map.coveringBounds
135
+
136
+ val cameraPos = GraniteNaverMapCameraPosition(
137
+ target = GraniteNaverMapCoordinate(position.target.latitude, position.target.longitude),
138
+ zoom = position.zoom,
139
+ tilt = position.tilt,
140
+ bearing = position.bearing
141
+ )
142
+
143
+ val contentRegion = listOf(
144
+ GraniteNaverMapCoordinate(contentBounds.southLatitude, contentBounds.westLongitude),
145
+ GraniteNaverMapCoordinate(contentBounds.southLatitude, contentBounds.eastLongitude),
146
+ GraniteNaverMapCoordinate(contentBounds.northLatitude, contentBounds.eastLongitude),
147
+ GraniteNaverMapCoordinate(contentBounds.northLatitude, contentBounds.westLongitude)
148
+ )
149
+
150
+ val coveringRegion = listOf(
151
+ GraniteNaverMapCoordinate(coveringBounds.southLatitude, coveringBounds.westLongitude),
152
+ GraniteNaverMapCoordinate(coveringBounds.southLatitude, coveringBounds.eastLongitude),
153
+ GraniteNaverMapCoordinate(coveringBounds.northLatitude, coveringBounds.eastLongitude),
154
+ GraniteNaverMapCoordinate(coveringBounds.northLatitude, coveringBounds.westLongitude)
155
+ )
156
+
157
+ delegate?.onCameraChange(cameraPos, contentRegion, coveringRegion)
158
+ }
159
+
160
+ map.addOnCameraChangeListener { reason, animated ->
161
+ delegate?.onTouch(reason, animated)
162
+ }
163
+
164
+ map.setOnMapClickListener { point, latLng ->
165
+ delegate?.onClick(point.x.toDouble(), point.y.toDouble(), latLng.latitude, latLng.longitude)
166
+ }
167
+ }
168
+
169
+ // MARK: - Camera
170
+
171
+ override fun moveCamera(position: GraniteNaverMapCameraPosition, animated: Boolean) {
172
+ val cameraPosition = CameraPosition(
173
+ LatLng(position.target.latitude, position.target.longitude),
174
+ position.zoom,
175
+ position.tilt,
176
+ position.bearing
177
+ )
178
+ val update = CameraUpdate.toCameraPosition(cameraPosition)
179
+ if (animated) {
180
+ update.animate(CameraAnimation.Easing)
181
+ }
182
+ naverMap?.moveCamera(update)
183
+ }
184
+
185
+ override fun animateToCoordinate(coordinate: GraniteNaverMapCoordinate) {
186
+ naverMap?.moveCamera(
187
+ CameraUpdate.scrollTo(LatLng(coordinate.latitude, coordinate.longitude))
188
+ .animate(CameraAnimation.Easing)
189
+ )
190
+ }
191
+
192
+ override fun animateToBounds(bounds: GraniteNaverMapBounds, padding: Int) {
193
+ val latLngBounds = LatLngBounds(
194
+ LatLng(bounds.southWest.latitude, bounds.southWest.longitude),
195
+ LatLng(bounds.northEast.latitude, bounds.northEast.longitude)
196
+ )
197
+ naverMap?.moveCamera(
198
+ CameraUpdate.fitBounds(latLngBounds, padding)
199
+ .animate(CameraAnimation.Easing)
200
+ )
201
+ }
202
+
203
+ // MARK: - Map Properties
204
+
205
+ override fun setMapType(type: GraniteNaverMapType) {
206
+ naverMap?.mapType = when (type) {
207
+ GraniteNaverMapType.BASIC -> NaverMap.MapType.Basic
208
+ GraniteNaverMapType.NAVI -> NaverMap.MapType.Navi
209
+ GraniteNaverMapType.SATELLITE -> NaverMap.MapType.Satellite
210
+ GraniteNaverMapType.HYBRID -> NaverMap.MapType.Hybrid
211
+ GraniteNaverMapType.TERRAIN -> NaverMap.MapType.Terrain
212
+ GraniteNaverMapType.NONE -> NaverMap.MapType.None
213
+ }
214
+ }
215
+
216
+ override fun setMapPadding(top: Int, left: Int, bottom: Int, right: Int) {
217
+ naverMap?.setContentPadding(left, top, right, bottom)
218
+ }
219
+
220
+ override fun setCompassEnabled(enabled: Boolean) {
221
+ naverMap?.uiSettings?.isCompassEnabled = enabled
222
+ }
223
+
224
+ override fun setScaleBarEnabled(enabled: Boolean) {
225
+ naverMap?.uiSettings?.isScaleBarEnabled = enabled
226
+ }
227
+
228
+ override fun setZoomControlEnabled(enabled: Boolean) {
229
+ naverMap?.uiSettings?.isZoomControlEnabled = enabled
230
+ }
231
+
232
+ override fun setLocationButtonEnabled(enabled: Boolean) {
233
+ naverMap?.uiSettings?.isLocationButtonEnabled = enabled
234
+ }
235
+
236
+ override fun setBuildingHeight(height: Float) {
237
+ naverMap?.buildingHeight = height
238
+ }
239
+
240
+ override fun setNightModeEnabled(enabled: Boolean) {
241
+ naverMap?.isNightModeEnabled = enabled
242
+ }
243
+
244
+ override fun setMinZoomLevel(level: Double) {
245
+ naverMap?.minZoom = level
246
+ }
247
+
248
+ override fun setMaxZoomLevel(level: Double) {
249
+ naverMap?.maxZoom = level
250
+ }
251
+
252
+ override fun setScrollGesturesEnabled(enabled: Boolean) {
253
+ naverMap?.uiSettings?.isScrollGesturesEnabled = enabled
254
+ }
255
+
256
+ override fun setZoomGesturesEnabled(enabled: Boolean) {
257
+ naverMap?.uiSettings?.isZoomGesturesEnabled = enabled
258
+ }
259
+
260
+ override fun setTiltGesturesEnabled(enabled: Boolean) {
261
+ naverMap?.uiSettings?.isTiltGesturesEnabled = enabled
262
+ }
263
+
264
+ override fun setRotateGesturesEnabled(enabled: Boolean) {
265
+ naverMap?.uiSettings?.isRotateGesturesEnabled = enabled
266
+ }
267
+
268
+ override fun setStopGesturesEnabled(enabled: Boolean) {
269
+ naverMap?.uiSettings?.isStopGesturesEnabled = enabled
270
+ }
271
+
272
+ override fun setLocationTrackingMode(mode: GraniteNaverMapLocationTrackingMode) {
273
+ naverMap?.locationTrackingMode = when (mode) {
274
+ GraniteNaverMapLocationTrackingMode.NONE -> LocationTrackingMode.None
275
+ GraniteNaverMapLocationTrackingMode.NO_FOLLOW -> LocationTrackingMode.NoFollow
276
+ GraniteNaverMapLocationTrackingMode.FOLLOW -> LocationTrackingMode.Follow
277
+ GraniteNaverMapLocationTrackingMode.FACE -> LocationTrackingMode.Face
278
+ }
279
+ }
280
+
281
+ override fun setLayerGroupEnabled(group: String, enabled: Boolean) {
282
+ val layerGroup = when (group) {
283
+ "building" -> NaverMap.LAYER_GROUP_BUILDING
284
+ "ctt" -> NaverMap.LAYER_GROUP_TRAFFIC
285
+ "transit" -> NaverMap.LAYER_GROUP_TRANSIT
286
+ "bike" -> NaverMap.LAYER_GROUP_BICYCLE
287
+ "mountain" -> NaverMap.LAYER_GROUP_MOUNTAIN
288
+ "landparcel" -> NaverMap.LAYER_GROUP_CADASTRAL
289
+ else -> return
290
+ }
291
+ naverMap?.setLayerGroupEnabled(layerGroup, enabled)
292
+ }
293
+
294
+ // MARK: - Markers
295
+
296
+ override fun addMarker(data: GraniteNaverMapMarkerData) {
297
+ val map = naverMap ?: return
298
+
299
+ val marker = Marker().apply {
300
+ position = LatLng(data.coordinate.latitude, data.coordinate.longitude)
301
+ if (data.zIndex != 0) zIndex = data.zIndex
302
+ if (data.rotation != 0f) angle = data.rotation
303
+ isFlat = data.flat
304
+ alpha = data.alpha
305
+
306
+ if (data.pinColor != 0 && (data.pinColor ushr 24) != 0) {
307
+ iconTintColor = data.pinColor
308
+ }
309
+
310
+ if (data.image.isNotEmpty()) {
311
+ loadMarkerImage(this, data.image)
312
+ if (data.width > 0) width = dpToPx(data.width)
313
+ if (data.height > 0) height = dpToPx(data.height)
314
+ }
315
+
316
+ setOnClickListener {
317
+ delegate?.onMarkerClick(data.identifier)
318
+ true
319
+ }
320
+
321
+ this.map = map
322
+ }
323
+
324
+ markers[data.identifier] = marker
325
+ }
326
+
327
+ override fun updateMarker(data: GraniteNaverMapMarkerData) {
328
+ markers[data.identifier]?.apply {
329
+ position = LatLng(data.coordinate.latitude, data.coordinate.longitude)
330
+ if (data.width > 0) width = dpToPx(data.width)
331
+ if (data.height > 0) height = dpToPx(data.height)
332
+ zIndex = data.zIndex
333
+ angle = data.rotation
334
+ isFlat = data.flat
335
+ alpha = data.alpha
336
+ if (data.pinColor != 0) iconTintColor = data.pinColor
337
+ if (data.image.isNotEmpty()) loadMarkerImage(this, data.image)
338
+ }
339
+ }
340
+
341
+ override fun removeMarker(identifier: String) {
342
+ markers[identifier]?.map = null
343
+ markers.remove(identifier)
344
+ }
345
+
346
+ private fun loadMarkerImage(marker: Marker, url: String) {
347
+ thread {
348
+ try {
349
+ val connection = URL(url).openConnection()
350
+ connection.connect()
351
+ val inputStream = connection.getInputStream()
352
+ val bitmap = BitmapFactory.decodeStream(inputStream)
353
+ inputStream.close()
354
+
355
+ containerView?.post {
356
+ marker.icon = OverlayImage.fromBitmap(bitmap)
357
+ }
358
+ } catch (e: Exception) {
359
+ e.printStackTrace()
360
+ }
361
+ }
362
+ }
363
+
364
+ // MARK: - Polylines
365
+
366
+ private fun lineCapType(type: Int): PolylineOverlay.LineCap {
367
+ return when (type) {
368
+ 1 -> PolylineOverlay.LineCap.Round
369
+ 2 -> PolylineOverlay.LineCap.Square
370
+ else -> PolylineOverlay.LineCap.Butt
371
+ }
372
+ }
373
+
374
+ private fun lineJoinType(type: Int): PolylineOverlay.LineJoin {
375
+ return when (type) {
376
+ 1 -> PolylineOverlay.LineJoin.Round
377
+ 2 -> PolylineOverlay.LineJoin.Bevel
378
+ else -> PolylineOverlay.LineJoin.Miter
379
+ }
380
+ }
381
+
382
+ override fun addPolyline(data: GraniteNaverMapPolylineData) {
383
+ val map = naverMap ?: return
384
+ val coords = data.coordinates.map { LatLng(it.latitude, it.longitude) }
385
+ if (coords.size < 2) return
386
+
387
+ val polyline = PolylineOverlay().apply {
388
+ this.coords = coords
389
+ width = dpToPx(data.strokeWidth)
390
+ color = data.strokeColor
391
+ zIndex = data.zIndex
392
+ capType = lineCapType(data.lineCap)
393
+ joinType = lineJoinType(data.lineJoin)
394
+ if (data.pattern.isNotEmpty()) {
395
+ setPattern(*data.pattern.toIntArray())
396
+ }
397
+ this.map = map
398
+ }
399
+
400
+ polylines[data.identifier] = polyline
401
+ }
402
+
403
+ override fun updatePolyline(data: GraniteNaverMapPolylineData) {
404
+ val polyline = polylines[data.identifier] ?: return
405
+ val coords = data.coordinates.map { LatLng(it.latitude, it.longitude) }
406
+ if (coords.size >= 2) {
407
+ polyline.coords = coords
408
+ }
409
+ polyline.width = dpToPx(data.strokeWidth)
410
+ polyline.color = data.strokeColor
411
+ polyline.zIndex = data.zIndex
412
+ polyline.capType = lineCapType(data.lineCap)
413
+ polyline.joinType = lineJoinType(data.lineJoin)
414
+ if (data.pattern.isNotEmpty()) {
415
+ polyline.setPattern(*data.pattern.toIntArray())
416
+ }
417
+ }
418
+
419
+ override fun removePolyline(identifier: String) {
420
+ polylines[identifier]?.map = null
421
+ polylines.remove(identifier)
422
+ }
423
+
424
+ // MARK: - Polygons
425
+
426
+ override fun addPolygon(data: GraniteNaverMapPolygonData) {
427
+ val map = naverMap ?: return
428
+ val coords = data.coordinates.map { LatLng(it.latitude, it.longitude) }
429
+ if (coords.size < 3) return
430
+
431
+ val polygon = PolygonOverlay().apply {
432
+ this.coords = coords
433
+ if (data.holes.isNotEmpty()) {
434
+ this.holes = data.holes.map { hole ->
435
+ hole.map { LatLng(it.latitude, it.longitude) }
436
+ }
437
+ }
438
+ color = data.fillColor
439
+ outlineColor = data.strokeColor
440
+ outlineWidth = dpToPx(data.strokeWidth)
441
+ zIndex = data.zIndex
442
+ this.map = map
443
+ }
444
+
445
+ polygons[data.identifier] = polygon
446
+ }
447
+
448
+ override fun updatePolygon(data: GraniteNaverMapPolygonData) {
449
+ val polygon = polygons[data.identifier] ?: return
450
+ val coords = data.coordinates.map { LatLng(it.latitude, it.longitude) }
451
+ if (coords.size >= 3) {
452
+ polygon.coords = coords
453
+ }
454
+ if (data.holes.isNotEmpty()) {
455
+ polygon.holes = data.holes.map { hole ->
456
+ hole.map { LatLng(it.latitude, it.longitude) }
457
+ }
458
+ }
459
+ polygon.color = data.fillColor
460
+ polygon.outlineColor = data.strokeColor
461
+ polygon.outlineWidth = dpToPx(data.strokeWidth)
462
+ polygon.zIndex = data.zIndex
463
+ }
464
+
465
+ override fun removePolygon(identifier: String) {
466
+ polygons[identifier]?.map = null
467
+ polygons.remove(identifier)
468
+ }
469
+
470
+ // MARK: - Circles
471
+
472
+ override fun addCircle(data: GraniteNaverMapCircleData) {
473
+ val map = naverMap ?: return
474
+
475
+ val circle = CircleOverlay().apply {
476
+ center = LatLng(data.center.latitude, data.center.longitude)
477
+ radius = data.radius
478
+ color = data.fillColor
479
+ outlineColor = data.strokeColor
480
+ outlineWidth = dpToPx(data.strokeWidth)
481
+ zIndex = data.zIndex
482
+ this.map = map
483
+ }
484
+
485
+ circles[data.identifier] = circle
486
+ }
487
+
488
+ override fun updateCircle(data: GraniteNaverMapCircleData) {
489
+ val circle = circles[data.identifier] ?: return
490
+ circle.center = LatLng(data.center.latitude, data.center.longitude)
491
+ circle.radius = data.radius
492
+ circle.color = data.fillColor
493
+ circle.outlineColor = data.strokeColor
494
+ circle.outlineWidth = dpToPx(data.strokeWidth)
495
+ circle.zIndex = data.zIndex
496
+ }
497
+
498
+ override fun removeCircle(identifier: String) {
499
+ circles[identifier]?.map = null
500
+ circles.remove(identifier)
501
+ }
502
+
503
+ // MARK: - Paths
504
+
505
+ override fun addPath(data: GraniteNaverMapPathData) {
506
+ val map = naverMap ?: return
507
+ val coords = data.coordinates.map { LatLng(it.latitude, it.longitude) }
508
+ if (coords.size < 2) return
509
+
510
+ val path = PathOverlay().apply {
511
+ this.coords = coords
512
+ width = dpToPx(data.width)
513
+ outlineWidth = dpToPx(data.outlineWidth)
514
+ color = data.color
515
+ outlineColor = data.outlineColor
516
+ passedColor = data.passedColor
517
+ passedOutlineColor = data.passedOutlineColor
518
+ progress = data.progress.toDouble()
519
+ zIndex = data.zIndex
520
+ if (data.patternInterval > 0) {
521
+ patternInterval = data.patternInterval
522
+ }
523
+ this.map = map
524
+ }
525
+
526
+ paths[data.identifier] = path
527
+ }
528
+
529
+ override fun updatePath(data: GraniteNaverMapPathData) {
530
+ val path = paths[data.identifier] ?: return
531
+ val coords = data.coordinates.map { LatLng(it.latitude, it.longitude) }
532
+ if (coords.size >= 2) {
533
+ path.coords = coords
534
+ }
535
+ path.width = dpToPx(data.width)
536
+ path.outlineWidth = dpToPx(data.outlineWidth)
537
+ path.color = data.color
538
+ path.outlineColor = data.outlineColor
539
+ path.passedColor = data.passedColor
540
+ path.passedOutlineColor = data.passedOutlineColor
541
+ path.progress = data.progress.toDouble()
542
+ path.zIndex = data.zIndex
543
+ }
544
+
545
+ override fun removePath(identifier: String) {
546
+ paths[identifier]?.map = null
547
+ paths.remove(identifier)
548
+ }
549
+ }
@@ -0,0 +1,3 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+ </manifest>
@@ -0,0 +1,91 @@
1
+ package run.granite.navermap
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ class GraniteNaverMapInitializedEvent(
8
+ surfaceId: Int,
9
+ viewId: Int
10
+ ) : Event<GraniteNaverMapInitializedEvent>(surfaceId, viewId) {
11
+ override fun getEventName(): String = "onInitialized"
12
+ override fun getEventData(): WritableMap = Arguments.createMap()
13
+ }
14
+
15
+ class GraniteNaverMapCameraChangeEvent(
16
+ surfaceId: Int,
17
+ viewId: Int,
18
+ private val latitude: Double,
19
+ private val longitude: Double,
20
+ private val zoom: Double,
21
+ private val contentRegion: List<GraniteNaverMapCoordinate>,
22
+ private val coveringRegion: List<GraniteNaverMapCoordinate>
23
+ ) : Event<GraniteNaverMapCameraChangeEvent>(surfaceId, viewId) {
24
+ override fun getEventName(): String = "onCameraChange"
25
+ override fun getEventData(): WritableMap = Arguments.createMap().apply {
26
+ putDouble("latitude", latitude)
27
+ putDouble("longitude", longitude)
28
+ putDouble("zoom", zoom)
29
+
30
+ val contentArray = Arguments.createArray().apply {
31
+ contentRegion.forEach { coord ->
32
+ pushMap(Arguments.createMap().apply {
33
+ putDouble("latitude", coord.latitude)
34
+ putDouble("longitude", coord.longitude)
35
+ })
36
+ }
37
+ }
38
+ putArray("contentRegion", contentArray)
39
+
40
+ val coveringArray = Arguments.createArray().apply {
41
+ coveringRegion.forEach { coord ->
42
+ pushMap(Arguments.createMap().apply {
43
+ putDouble("latitude", coord.latitude)
44
+ putDouble("longitude", coord.longitude)
45
+ })
46
+ }
47
+ }
48
+ putArray("coveringRegion", coveringArray)
49
+ }
50
+ }
51
+
52
+ class GraniteNaverMapTouchEvent(
53
+ surfaceId: Int,
54
+ viewId: Int,
55
+ private val reason: Int,
56
+ private val animated: Boolean
57
+ ) : Event<GraniteNaverMapTouchEvent>(surfaceId, viewId) {
58
+ override fun getEventName(): String = "onTouch"
59
+ override fun getEventData(): WritableMap = Arguments.createMap().apply {
60
+ putInt("reason", reason)
61
+ putBoolean("animated", animated)
62
+ }
63
+ }
64
+
65
+ class GraniteNaverMapClickEvent(
66
+ surfaceId: Int,
67
+ viewId: Int,
68
+ private val x: Double,
69
+ private val y: Double,
70
+ private val latitude: Double,
71
+ private val longitude: Double
72
+ ) : Event<GraniteNaverMapClickEvent>(surfaceId, viewId) {
73
+ override fun getEventName(): String = "onMapClick"
74
+ override fun getEventData(): WritableMap = Arguments.createMap().apply {
75
+ putDouble("x", x)
76
+ putDouble("y", y)
77
+ putDouble("latitude", latitude)
78
+ putDouble("longitude", longitude)
79
+ }
80
+ }
81
+
82
+ class GraniteNaverMapMarkerClickEvent(
83
+ surfaceId: Int,
84
+ viewId: Int,
85
+ private val markerId: String
86
+ ) : Event<GraniteNaverMapMarkerClickEvent>(surfaceId, viewId) {
87
+ override fun getEventName(): String = "onMarkerClick"
88
+ override fun getEventData(): WritableMap = Arguments.createMap().apply {
89
+ putString("id", markerId)
90
+ }
91
+ }
@@ -0,0 +1,16 @@
1
+ package run.granite.navermap
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+ class GraniteNaverMapPackage : ReactPackage {
9
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
10
+ return emptyList()
11
+ }
12
+
13
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
14
+ return listOf(GraniteNaverMapViewManager())
15
+ }
16
+ }