react-native-map4d-map-dtqg 0.1.1 → 0.1.2

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 (86) hide show
  1. package/README.md +64 -19
  2. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  4. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  5. package/android/.gradle/buildOutputCleanup/cache.properties +1 -1
  6. package/android/src/main/java/com/reactnativemap4dmap/RMFMapViewManager.java +5 -0
  7. package/ios/RMFMapViewManager.m +15 -0
  8. package/lib/commonjs/components/MFBanDoSo.js +109 -0
  9. package/lib/commonjs/components/MFBanDoSo.js.map +1 -0
  10. package/lib/commonjs/components/MFMapView.js +20 -1
  11. package/lib/commonjs/components/MFMapView.js.map +1 -1
  12. package/lib/commonjs/components/extends/AreaFocusManager.js +205 -0
  13. package/lib/commonjs/components/extends/AreaFocusManager.js.map +1 -0
  14. package/lib/commonjs/components/extends/AreaFocuser.js +19 -257
  15. package/lib/commonjs/components/extends/AreaFocuser.js.map +1 -1
  16. package/lib/commonjs/components/extends/BoundHelper.js +36 -0
  17. package/lib/commonjs/components/extends/BoundHelper.js.map +1 -0
  18. package/lib/commonjs/components/extends/area/AreaFocusAreas.js +167 -0
  19. package/lib/commonjs/components/extends/area/AreaFocusAreas.js.map +1 -0
  20. package/lib/commonjs/components/extends/area/AreaFocusGeometryUtils.js +164 -0
  21. package/lib/commonjs/components/extends/area/AreaFocusGeometryUtils.js.map +1 -0
  22. package/lib/commonjs/components/extends/area/AreaFocusSession.js +100 -0
  23. package/lib/commonjs/components/extends/area/AreaFocusSession.js.map +1 -0
  24. package/lib/commonjs/components/extends/area/AreaFocusTypes.js +40 -0
  25. package/lib/commonjs/components/extends/area/AreaFocusTypes.js.map +1 -0
  26. package/lib/commonjs/components/internal/DefaultRoadmapStyle.js +2288 -0
  27. package/lib/commonjs/components/internal/DefaultRoadmapStyle.js.map +1 -0
  28. package/lib/commonjs/components/internal/GeojsonStyleUtils.js +139 -0
  29. package/lib/commonjs/components/internal/GeojsonStyleUtils.js.map +1 -0
  30. package/lib/commonjs/index.js +8 -0
  31. package/lib/commonjs/index.js.map +1 -1
  32. package/lib/module/components/MFBanDoSo.js +92 -0
  33. package/lib/module/components/MFBanDoSo.js.map +1 -0
  34. package/lib/module/components/MFMapView.js +19 -1
  35. package/lib/module/components/MFMapView.js.map +1 -1
  36. package/lib/module/components/extends/AreaFocusManager.js +193 -0
  37. package/lib/module/components/extends/AreaFocusManager.js.map +1 -0
  38. package/lib/module/components/extends/AreaFocuser.js +19 -257
  39. package/lib/module/components/extends/AreaFocuser.js.map +1 -1
  40. package/lib/module/components/extends/BoundHelper.js +29 -0
  41. package/lib/module/components/extends/BoundHelper.js.map +1 -0
  42. package/lib/module/components/extends/area/AreaFocusAreas.js +156 -0
  43. package/lib/module/components/extends/area/AreaFocusAreas.js.map +1 -0
  44. package/lib/module/components/extends/area/AreaFocusGeometryUtils.js +153 -0
  45. package/lib/module/components/extends/area/AreaFocusGeometryUtils.js.map +1 -0
  46. package/lib/module/components/extends/area/AreaFocusSession.js +93 -0
  47. package/lib/module/components/extends/area/AreaFocusSession.js.map +1 -0
  48. package/lib/module/components/extends/area/AreaFocusTypes.js +33 -0
  49. package/lib/module/components/extends/area/AreaFocusTypes.js.map +1 -0
  50. package/lib/module/components/internal/DefaultRoadmapStyle.js +2281 -0
  51. package/lib/module/components/internal/DefaultRoadmapStyle.js.map +1 -0
  52. package/lib/module/components/internal/GeojsonStyleUtils.js +130 -0
  53. package/lib/module/components/internal/GeojsonStyleUtils.js.map +1 -0
  54. package/lib/module/index.js +2 -1
  55. package/lib/module/index.js.map +1 -1
  56. package/package.json +1 -1
  57. package/src/components/MFBanDoSo.js +124 -0
  58. package/src/components/MFMapView.js +19 -2
  59. package/src/components/extends/AreaFocusManager.js +196 -0
  60. package/src/components/extends/AreaFocuser.js +17 -294
  61. package/src/components/extends/BoundHelper.js +32 -0
  62. package/src/components/extends/area/AreaFocusAreas.js +164 -0
  63. package/src/components/extends/area/AreaFocusGeometryUtils.js +164 -0
  64. package/src/components/extends/area/AreaFocusSession.js +100 -0
  65. package/src/components/extends/area/AreaFocusTypes.js +36 -0
  66. package/src/components/internal/DefaultRoadmapStyle.js +3365 -0
  67. package/src/components/internal/GeojsonStyleUtils.js +143 -0
  68. package/src/index.js +2 -0
  69. package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
  70. package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
  71. package/android/.gradle/9.0-milestone-1/checksums/checksums.lock +0 -0
  72. package/android/.gradle/9.0-milestone-1/checksums/md5-checksums.bin +0 -0
  73. package/android/.gradle/9.0-milestone-1/checksums/sha1-checksums.bin +0 -0
  74. package/android/.gradle/9.0-milestone-1/fileChanges/last-build.bin +0 -0
  75. package/android/.gradle/9.0-milestone-1/fileHashes/fileHashes.lock +0 -0
  76. package/android/.gradle/9.0-milestone-1/gc.properties +0 -0
  77. package/android/.gradle/config.properties +0 -2
  78. package/android/.idea/AndroidProjectSystem.xml +0 -6
  79. package/android/.idea/caches/deviceStreaming.xml +0 -1570
  80. package/android/.idea/copilot.data.migration.ask2agent.xml +0 -6
  81. package/android/.idea/gradle.xml +0 -12
  82. package/android/.idea/migrations.xml +0 -10
  83. package/android/.idea/misc.xml +0 -10
  84. package/android/.idea/runConfigurations.xml +0 -17
  85. package/android/.idea/vcs.xml +0 -6
  86. package/android/local.properties +0 -8
@@ -0,0 +1,124 @@
1
+ import PropTypes from 'prop-types';
2
+ import { MFMapView } from './MFMapView';
3
+ import {
4
+ buildGeojsonStyle,
5
+ createCategoryItemsSignature,
6
+ } from './internal/GeojsonStyleUtils';
7
+
8
+ const FilterStylePropType = PropTypes.shape({
9
+ kind: PropTypes.oneOfType([
10
+ PropTypes.string,
11
+ PropTypes.arrayOf(PropTypes.string),
12
+ ]),
13
+ kind_detail: PropTypes.oneOfType([
14
+ PropTypes.string,
15
+ PropTypes.arrayOf(PropTypes.string),
16
+ ]),
17
+ });
18
+
19
+ const DrawLinePropType = PropTypes.shape({
20
+ color: PropTypes.string,
21
+ width: PropTypes.oneOfType([PropTypes.number, PropTypes.array]),
22
+ });
23
+
24
+ const DrawFillPropType = PropTypes.shape({
25
+ color: PropTypes.string,
26
+ });
27
+
28
+ const DrawSymbolPropType = PropTypes.shape({
29
+ icon_image: PropTypes.string,
30
+ icon_index: PropTypes.number,
31
+ icon_color: PropTypes.string,
32
+ use_direct_icon_url: PropTypes.bool,
33
+ });
34
+
35
+ const CategoryStylePropType = PropTypes.shape({
36
+ line: PropTypes.arrayOf(
37
+ PropTypes.shape({
38
+ layer: PropTypes.string,
39
+ filter: FilterStylePropType,
40
+ draw: DrawLinePropType,
41
+ })
42
+ ),
43
+ fill: PropTypes.arrayOf(
44
+ PropTypes.shape({
45
+ layer: PropTypes.string,
46
+ filter: FilterStylePropType,
47
+ draw: DrawFillPropType,
48
+ })
49
+ ),
50
+ symbol: PropTypes.arrayOf(
51
+ PropTypes.shape({
52
+ layer: PropTypes.string,
53
+ filter: FilterStylePropType,
54
+ draw: DrawSymbolPropType,
55
+ })
56
+ ),
57
+ });
58
+
59
+ const CategoryItemPropType = PropTypes.shape({
60
+ key: PropTypes.string,
61
+ title: PropTypes.string,
62
+ group: PropTypes.string,
63
+ order: PropTypes.number,
64
+ checked: PropTypes.bool,
65
+ style: CategoryStylePropType,
66
+ });
67
+
68
+ class MFBanDoSo extends MFMapView {
69
+ constructor(props) {
70
+ super(props);
71
+ this._appliedGeojsonStyle = null;
72
+ }
73
+
74
+ componentDidMount() {
75
+ this._syncGeojsonStyle();
76
+ }
77
+
78
+ componentDidUpdate(prevProps, prevState) {
79
+ const mapReadyChanged = prevState.isReady !== this.state.isReady;
80
+ const mapStyleChanged = prevProps.mapStyle !== this.props.mapStyle;
81
+ const sourceUrlChanged = prevProps.sourceUrl !== this.props.sourceUrl;
82
+ const itemsChanged =
83
+ createCategoryItemsSignature(prevProps.items) !==
84
+ createCategoryItemsSignature(this.props.items);
85
+
86
+ if (
87
+ mapReadyChanged ||
88
+ mapStyleChanged ||
89
+ sourceUrlChanged ||
90
+ itemsChanged
91
+ ) {
92
+ this._syncGeojsonStyle();
93
+ }
94
+ }
95
+
96
+ _syncGeojsonStyle() {
97
+ if (!this.state.isReady) {
98
+ return;
99
+ }
100
+
101
+ const items = this.props.items || [];
102
+
103
+ const geojsonStyle = buildGeojsonStyle(
104
+ this.props.mapStyle,
105
+ this.props.sourceUrl,
106
+ items
107
+ );
108
+
109
+ if (!geojsonStyle || geojsonStyle === this._appliedGeojsonStyle) {
110
+ return;
111
+ }
112
+
113
+ this._appliedGeojsonStyle = geojsonStyle;
114
+ this._runCommand('setMapStyle', [geojsonStyle]);
115
+ }
116
+ }
117
+
118
+ MFBanDoSo.propTypes = {
119
+ ...MFMapView.propTypes,
120
+ items: PropTypes.arrayOf(CategoryItemPropType),
121
+ sourceUrl: PropTypes.string.isRequired,
122
+ };
123
+
124
+ export { MFBanDoSo };
@@ -1,6 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import {ViewPropTypes, ColorPropType} from 'deprecated-react-native-prop-types';
4
+ import {AreaFocusManager} from './extends/AreaFocusManager';
4
5
  import {AreaFocuser} from './extends/AreaFocuser';
5
6
  import {MFPolygon} from './MFPolygon';
6
7
  import {
@@ -144,13 +145,15 @@ const propTypes = {
144
145
  * Callback that is called when user taps on location Button
145
146
  */
146
147
  onMyLocationButtonPress: PropTypes.func,
148
+
147
149
  };
148
150
 
149
151
 
150
152
  class MFMapView extends React.Component {
151
153
  constructor(props) {
152
154
  super(props);
153
- this.areaFocuser = new AreaFocuser(this);
155
+ this.areaFocusManager = new AreaFocusManager(this);
156
+ this.areaFocuser = new AreaFocuser(this.areaFocusManager);
154
157
  this.state = {
155
158
  isReady: Platform.OS === 'ios',
156
159
  managedPolygons: {},
@@ -361,6 +364,21 @@ class MFMapView extends React.Component {
361
364
  return Promise.reject('coordinateForPoint not supported on this platform');
362
365
  }
363
366
 
367
+ focusArea(focusOptions) {
368
+ if (!this.areaFocusManager) {
369
+ return Promise.resolve(null)
370
+ }
371
+
372
+ return this.areaFocusManager.focus(focusOptions)
373
+ }
374
+
375
+ clearFocusedArea() {
376
+ if (!this.areaFocusManager) {
377
+ return
378
+ }
379
+ this.areaFocusManager.clear()
380
+ }
381
+
364
382
  _getHandle() {
365
383
  return findNodeHandle(this.map);
366
384
  }
@@ -399,7 +417,6 @@ class MFMapView extends React.Component {
399
417
  return NativeModules[`RMFMapView`][name];
400
418
  }
401
419
 
402
-
403
420
  render() {
404
421
  let props;
405
422
  const { children, ...restProps } = this.props;
@@ -0,0 +1,196 @@
1
+ import {AreaFocusSession} from './area/AreaFocusSession'
2
+ import {ProvinceArea, IndustrialEconomicArea} from './area/AreaFocusAreas'
3
+ import {IndustrialEconomicType} from './area/AreaFocusTypes'
4
+
5
+ /**
6
+ * @typedef {'normal' | 'highlight'} FocusDisplay
7
+ */
8
+
9
+ /**
10
+ * @typedef {{left?: number, right?: number, top?: number, bottom?: number}} FocusPadding
11
+ */
12
+
13
+ /**
14
+ * @typedef {'province' | 'industrialZone' | 'economicZone' | 'ecoIndustrialZone' | 'freeTradeZone' | 'nonTariffZone' | 'otherZoneModel' | number} FocusType
15
+ */
16
+
17
+ /**
18
+ * @typedef {Object} FocusOptions
19
+ * @property {FocusType} type
20
+ * @property {number=} id
21
+ * @property {string=} name
22
+ * @property {FocusDisplay=} display
23
+ * @property {FocusPadding=} padding
24
+ */
25
+
26
+ const VIETNAM_MAINLAND_BOUNDS = {
27
+ minLat: 8.18,
28
+ minLng: 102.14,
29
+ maxLat: 23.4,
30
+ maxLng: 109.47,
31
+ }
32
+
33
+ const FOCUS_TYPE_TO_INDUSTRIAL_ECONOMIC_TYPE = {
34
+ industrialZone: IndustrialEconomicType.INDUSTRIAL_ZONE,
35
+ economicZone: IndustrialEconomicType.ECONOMIC_ZONE,
36
+ ecoIndustrialZone: IndustrialEconomicType.ECO_INDUSTRIAL_ZONE,
37
+ freeTradeZone: IndustrialEconomicType.FREE_TRADE_ZONE,
38
+ nonTariffZone: IndustrialEconomicType.NON_TARIFF_ZONE,
39
+ otherZoneModel: IndustrialEconomicType.OTHER_ZONE_MODEL,
40
+ }
41
+
42
+ export class AreaFocusManager {
43
+ constructor(mapView) {
44
+ this.mapView = mapView
45
+ this.currentSession = null
46
+ }
47
+
48
+ async _focusArea(area, options) {
49
+ this.clear()
50
+
51
+ if (!area) {
52
+ return null
53
+ }
54
+
55
+ try {
56
+ if (!(await area.load())) {
57
+ return null
58
+ }
59
+
60
+ const focusOptions = {...(options || {})}
61
+ const bounds = area.getBounds() || VIETNAM_MAINLAND_BOUNDS
62
+
63
+ this._fitBounds(bounds, focusOptions)
64
+
65
+ this.currentSession = new AreaFocusSession(this.mapView, area, focusOptions)
66
+ this.currentSession.render()
67
+
68
+ return this.currentSession
69
+ }
70
+ catch (error) {
71
+ console.error('Cannot focus area:', error)
72
+ return null
73
+ }
74
+ }
75
+
76
+ async _focusProvince(options) {
77
+ const provinceId = this._getProvinceId(options)
78
+ const provinceName = this._getProvinceName(options)
79
+
80
+ if (provinceId == null && !provinceName) {
81
+ this.clear()
82
+ return null
83
+ }
84
+
85
+ const area = provinceId != null ? new ProvinceArea(provinceId) : ProvinceArea.fromName(provinceName)
86
+ const display = options && options.display === 'highlight' ? 'highlight' : 'normal'
87
+
88
+ return this._focusArea(area, {
89
+ display,
90
+ padding: options ? options.padding : undefined,
91
+ })
92
+ }
93
+
94
+ /**
95
+ * @param {FocusOptions | null | undefined} focusOptions
96
+ * @returns {Promise<AreaFocusSession | null>}
97
+ */
98
+ async focus(focusOptions) {
99
+ if (focusOptions == null) {
100
+ this.clear()
101
+ return null
102
+ }
103
+
104
+ if (focusOptions.type === 'province') {
105
+ return this._focusProvince(focusOptions)
106
+ }
107
+
108
+ if (focusOptions.id == null) {
109
+ console.warn('Focus options must include an id for non-province types:', focusOptions)
110
+ this.clear()
111
+ return null
112
+ }
113
+
114
+ const industrialEconomicType = this._getIndustrialEconomicType(focusOptions.type)
115
+
116
+ if (industrialEconomicType != null) {
117
+ return this._focusArea(new IndustrialEconomicArea(industrialEconomicType, focusOptions.id), {
118
+ display: focusOptions.display,
119
+ padding: focusOptions.padding,
120
+ })
121
+ }
122
+
123
+ console.warn('Unsupported focus type:', focusOptions.type)
124
+ return null
125
+ }
126
+
127
+ _getIndustrialEconomicType(type) {
128
+ if (typeof type === 'number') {
129
+ const values = Object.values(IndustrialEconomicType)
130
+ return values.includes(type) ? type : null
131
+ }
132
+
133
+ if (typeof type !== 'string') {
134
+ return null
135
+ }
136
+
137
+ return FOCUS_TYPE_TO_INDUSTRIAL_ECONOMIC_TYPE[type] || null
138
+ }
139
+
140
+ clear() {
141
+ if (this.currentSession) {
142
+ this.currentSession.destroy()
143
+ this.currentSession = null
144
+ }
145
+ }
146
+
147
+ _fitBounds(bounds, options) {
148
+ if (!this.mapView || typeof this.mapView.fitBounds !== 'function' || !bounds) {
149
+ return
150
+ }
151
+
152
+ this.mapView.fitBounds({
153
+ bounds: {
154
+ southWest: {
155
+ latitude: bounds.minLat,
156
+ longitude: bounds.minLng,
157
+ },
158
+ northEast: {
159
+ latitude: bounds.maxLat,
160
+ longitude: bounds.maxLng,
161
+ },
162
+ },
163
+ padding: options ? options.padding : undefined,
164
+ })
165
+ }
166
+
167
+ _getProvinceName(options) {
168
+ if (options == null || typeof options !== 'object') {
169
+ return null
170
+ }
171
+
172
+ if (typeof options.name === 'string') {
173
+ const name = options.name.trim()
174
+ return name.length > 0 ? name : null
175
+ }
176
+
177
+ const optionKeys = Object.keys(options)
178
+ const unsupportedKeys = optionKeys.filter((key) => key !== 'type' && key !== 'id' && key !== 'name' && key !== 'display' && key !== 'padding')
179
+
180
+ if (unsupportedKeys.length > 0) {
181
+ console.warn(
182
+ `[AreaFocusManager] focusProvince expects options like { type: 'province', name: 'Ha Noi', display: 'highlight' }. Unsupported keys: ${unsupportedKeys.join(', ')}`
183
+ )
184
+ }
185
+
186
+ return null
187
+ }
188
+
189
+ _getProvinceId(options) {
190
+ if (options == null || typeof options !== 'object') {
191
+ return null
192
+ }
193
+
194
+ return typeof options.id === 'number' ? options.id : null
195
+ }
196
+ }
@@ -1,105 +1,37 @@
1
1
  export class AreaFocuser {
2
2
 
3
- constructor(mapView) {
4
- this.mapView = mapView
5
- this.highlightPaths = []
6
- this.highlightPolygonId = 'area-focuser-highlight-polygon'
3
+ constructor(areaFocusManager) {
4
+ this._areaFocusManager = areaFocusManager
7
5
  }
8
6
 
9
7
  /**
10
8
  * @param {{name?: string, highlight?: boolean}=} options
11
9
  */
12
10
  async focusProvince(options) {
13
- const provinceName = this.getProvinceName(options)
14
- const shouldHighlight = this.shouldHighlight(options)
11
+ const provinceName = this._getProvinceName(options)
12
+ const shouldHighlight = this._shouldHighlight(options)
15
13
 
16
14
  if (!provinceName) {
17
- this.clearHighlightPaths()
18
- this.clearHighlightPolygon()
15
+ this._clear()
19
16
  return
20
17
  }
21
18
 
22
- const url =
23
- `https://api-app-cdtqg.map4d.vn/map/country/geometry?name=${encodeURIComponent(provinceName)}`
24
-
25
- try {
26
- const response = await fetch(url)
27
-
28
- if (!response.ok) {
29
- return
30
- }
31
-
32
- const data = await response.json()
33
-
34
- if (data.code !== 'ok') {
35
- return
36
- }
37
-
38
- const feature =
39
- data.result && data.result.features && data.result.features.length > 0 ? data.result.features[0] : null
40
-
41
- if (!feature) {
42
- return
43
- }
44
-
45
- const geometry = feature.geometry
46
- if (!geometry) {
47
- return
48
- }
49
-
50
- let bounds = null
51
-
52
- const viewbox =
53
- feature.properties && feature.properties.viewbox ? feature.properties.viewbox : null
54
-
55
- if (viewbox != null && viewbox.trim() != '') {
56
- bounds = this.parseViewbox(viewbox)
57
- }
58
-
59
- if (!bounds) {
60
- bounds = this.getViewboxFromGeometry(geometry)
61
- }
62
-
63
- if (!bounds) {
64
- return
65
- }
66
-
67
- this.mapView.fitBounds({
68
- bounds: {
69
- southWest: {
70
- latitude: bounds[0],
71
- longitude: bounds[1],
72
- },
73
- northEast: {
74
- latitude: bounds[2],
75
- longitude: bounds[3],
76
- },
77
- }
19
+ if (this._areaFocusManager) {
20
+ await this._areaFocusManager.focus({
21
+ type: 'province',
22
+ name: provinceName,
23
+ display: shouldHighlight ? 'highlight' : 'normal',
78
24
  })
79
-
80
- this.createHighlightPaths(geometry)
81
-
82
- if (shouldHighlight) {
83
- const polygon = this.getHighlightPolygonProps()
84
-
85
- if (polygon) {
86
- this.mapView._addPolygon({
87
- ...polygon,
88
- id: this.highlightPolygonId,
89
- zIndex: 999,
90
- })
91
- }
92
- }
93
- else {
94
- this.clearHighlightPolygon()
95
- }
96
25
  }
97
- catch (error) {
98
- console.error('Cannot focus province:', error)
26
+ }
27
+
28
+ _clear() {
29
+ if (this._areaFocusManager) {
30
+ this._areaFocusManager.clear()
99
31
  }
100
32
  }
101
33
 
102
- getProvinceName(options) {
34
+ _getProvinceName(options) {
103
35
  if (options == null || typeof options !== 'object') {
104
36
  return null
105
37
  }
@@ -120,220 +52,11 @@ export class AreaFocuser {
120
52
  return null
121
53
  }
122
54
 
123
- shouldHighlight(options) {
55
+ _shouldHighlight(options) {
124
56
  if (options == null || typeof options !== 'object') {
125
57
  return false
126
58
  }
127
59
 
128
60
  return options.highlight === true
129
61
  }
130
-
131
- parseViewbox(viewbox) {
132
- const bounds = viewbox.split(',').map(Number)
133
-
134
- if (bounds.length != 4) {
135
- return null
136
- }
137
-
138
- const [minLat, minLng, maxLat, maxLng] = bounds
139
-
140
- if (
141
- Number.isNaN(minLat) ||
142
- Number.isNaN(minLng) ||
143
- Number.isNaN(maxLat) ||
144
- Number.isNaN(maxLng)
145
- ) {
146
- return null
147
- }
148
-
149
- return [
150
- minLat,
151
- minLng,
152
- maxLat,
153
- maxLng,
154
- ]
155
- }
156
-
157
- getViewboxFromGeometry(geometry) {
158
- const bounds = {
159
- minLat: Infinity,
160
- minLng: Infinity,
161
- maxLat: -Infinity,
162
- maxLng: -Infinity,
163
- }
164
-
165
- const updateBounds = function (coordinate) {
166
- if (coordinate.length < 2) {
167
- return
168
- }
169
-
170
- const lng = coordinate[0]
171
- const lat = coordinate[1]
172
-
173
- if (Number.isNaN(lat) || Number.isNaN(lng)) {
174
- return
175
- }
176
-
177
- bounds.minLat = Math.min(bounds.minLat, lat)
178
- bounds.minLng = Math.min(bounds.minLng, lng)
179
- bounds.maxLat = Math.max(bounds.maxLat, lat)
180
- bounds.maxLng = Math.max(bounds.maxLng, lng)
181
- }
182
-
183
- if (geometry.type === 'Polygon') {
184
- const polygons = geometry.coordinates
185
-
186
- polygons.forEach(function (ring) {
187
- ring.forEach(function (coordinate) {
188
- updateBounds(coordinate)
189
- })
190
- })
191
- }
192
-
193
- if (geometry.type === 'MultiPolygon') {
194
- const multiPolygons = geometry.coordinates
195
-
196
- multiPolygons.forEach(function (polygon) {
197
- polygon.forEach(function (ring) {
198
- ring.forEach(function (coordinate) {
199
- updateBounds(coordinate)
200
- })
201
- })
202
- })
203
- }
204
-
205
- if (
206
- bounds.minLat === Infinity ||
207
- bounds.minLng === Infinity ||
208
- bounds.maxLat === -Infinity ||
209
- bounds.maxLng === -Infinity
210
- ) {
211
- return null
212
- }
213
-
214
- return [
215
- bounds.minLat,
216
- bounds.minLng,
217
- bounds.maxLat,
218
- bounds.maxLng,
219
- ]
220
- }
221
-
222
- createHighlightPaths(geometry) {
223
- this.clearHighlightPaths()
224
-
225
- const paths = this.createWorldMaskPaths(geometry)
226
-
227
- if (paths.length <= 1) {
228
- return
229
- }
230
-
231
- this.highlightPaths = paths
232
- }
233
-
234
- clearHighlightPaths() {
235
- this.highlightPaths = []
236
- }
237
-
238
- clearHighlightPolygon() {
239
- if (!this.mapView) {
240
- return
241
- }
242
-
243
- this.mapView._removePolygon(this.highlightPolygonId)
244
- }
245
-
246
- getHighlightPolygonProps() {
247
- if (!this.highlightPaths || this.highlightPaths.length <= 1) {
248
- return null
249
- }
250
-
251
- const [coordinates, ...holes] = this.highlightPaths
252
-
253
- return {
254
- coordinates,
255
- holes,
256
- fillColor: "#0000001E",
257
- strokeColor: "#FF0000FF",
258
- strokeWidth: 2.0,
259
- }
260
- }
261
-
262
- createWorldMaskPaths(geometry) {
263
- const worldPath = [
264
- { longitude: -180, latitude: -90 },
265
- { longitude: 180, latitude: -90 },
266
- { longitude: 180, latitude: 90 },
267
- { longitude: -180, latitude: 90 },
268
- { longitude: -180, latitude: -90 },
269
- ]
270
-
271
- const paths = [
272
- worldPath,
273
- ]
274
-
275
- const holes = this.getHolePathsFromGeometry(geometry)
276
-
277
- holes.forEach((hole) => {
278
- paths.push(hole)
279
- })
280
-
281
- return paths
282
- }
283
-
284
- getHolePathsFromGeometry(geometry) {
285
- const paths = []
286
-
287
- if (geometry.type == 'Polygon') {
288
- const polygon = geometry.coordinates
289
-
290
- if (polygon.length > 0) {
291
- paths.push(this.convertAndClosePath(polygon[0]))
292
- }
293
- }
294
-
295
- if (geometry.type == 'MultiPolygon') {
296
- const multiPolygon = geometry.coordinates
297
-
298
- multiPolygon.forEach((polygon) => {
299
- if (polygon.length > 0) {
300
- paths.push(this.convertAndClosePath(polygon[0]))
301
- }
302
- })
303
- }
304
-
305
- return paths
306
- }
307
-
308
- convertAndClosePath(path) {
309
- if (path.length == 0) {
310
- return []
311
- }
312
-
313
- const coordinatePath = path
314
- .filter((point) => point.length >= 2)
315
- .map((point) => ({
316
- latitude: point[1],
317
- longitude: point[0],
318
- }))
319
-
320
- if (coordinatePath.length == 0) {
321
- return []
322
- }
323
-
324
- const firstPoint = coordinatePath[0]
325
- const lastPoint = coordinatePath[coordinatePath.length - 1]
326
-
327
- if (
328
- firstPoint.latitude == lastPoint.latitude &&
329
- firstPoint.longitude == lastPoint.longitude
330
- ) {
331
- return coordinatePath
332
- }
333
-
334
- return [
335
- ...coordinatePath,
336
- firstPoint,
337
- ]
338
- }
339
62
  }