@antv/l7-component 2.25.7 → 2.25.10

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 (151) hide show
  1. package/es/assets/iconfont/iconfont.d.ts +21 -0
  2. package/es/assets/iconfont/iconfont.js +61 -0
  3. package/es/constants/index.d.ts +60 -0
  4. package/es/constants/index.js +60 -0
  5. package/es/control/baseControl/buttonControl.d.ts +60 -0
  6. package/es/control/baseControl/buttonControl.js +142 -0
  7. package/es/control/baseControl/control.d.ts +112 -0
  8. package/es/control/baseControl/control.js +256 -0
  9. package/es/control/baseControl/index.d.ts +4 -0
  10. package/es/control/baseControl/index.js +4 -0
  11. package/es/control/baseControl/popperControl.d.ts +28 -0
  12. package/es/control/baseControl/popperControl.js +92 -0
  13. package/es/control/baseControl/selectControl.d.ts +53 -0
  14. package/es/control/baseControl/selectControl.js +173 -0
  15. package/es/control/exportImage.d.ts +19 -0
  16. package/es/control/exportImage.js +73 -0
  17. package/es/control/fullscreen.d.ts +20 -0
  18. package/es/control/fullscreen.js +88 -0
  19. package/es/control/geoLocate.d.ts +17 -0
  20. package/es/control/geoLocate.js +60 -0
  21. package/es/control/layerSwitch.d.ts +27 -0
  22. package/es/control/layerSwitch.js +155 -0
  23. package/es/control/logo.d.ts +14 -0
  24. package/es/control/logo.js +49 -0
  25. package/es/control/mapTheme.d.ts +11 -0
  26. package/es/control/mapTheme.js +69 -0
  27. package/es/control/mouseLocation.d.ts +16 -0
  28. package/es/control/mouseLocation.js +52 -0
  29. package/es/control/scale.d.ts +35 -0
  30. package/es/control/scale.js +121 -0
  31. package/es/control/swipe.d.ts +66 -0
  32. package/es/control/swipe.js +392 -0
  33. package/es/control/zoom.d.ts +39 -0
  34. package/es/control/zoom.js +100 -0
  35. package/es/css/button.less +77 -0
  36. package/es/css/control.less +82 -0
  37. package/es/css/index.css +653 -0
  38. package/es/css/index.less +13 -0
  39. package/es/css/l7.less +69 -0
  40. package/es/css/layerPopup.less +9 -0
  41. package/es/css/logo.less +21 -0
  42. package/es/css/mouseLocation.less +9 -0
  43. package/es/css/popper.less +74 -0
  44. package/es/css/popup.less +176 -0
  45. package/es/css/scale.less +37 -0
  46. package/es/css/select.less +96 -0
  47. package/es/css/swipe.less +80 -0
  48. package/es/css/variables.less +29 -0
  49. package/es/css/zoom.less +34 -0
  50. package/es/images/layers.png +0 -0
  51. package/es/images/layers.svg +1 -0
  52. package/es/images/logo.png +0 -0
  53. package/es/images/quanping.svg +12 -0
  54. package/es/index.d.ts +19 -0
  55. package/es/index.js +717 -0
  56. package/es/interface.d.ts +29 -0
  57. package/es/interface.js +1 -0
  58. package/es/marker-layer.d.ts +46 -0
  59. package/es/marker-layer.js +509 -0
  60. package/es/marker.d.ts +66 -0
  61. package/es/marker.js +495 -0
  62. package/es/popup/layerPopup.d.ts +105 -0
  63. package/es/popup/layerPopup.js +341 -0
  64. package/es/popup/popup.d.ts +147 -0
  65. package/es/popup/popup.js +587 -0
  66. package/es/utils/anchor.d.ts +22 -0
  67. package/es/utils/anchor.js +31 -0
  68. package/es/utils/eventManager.d.ts +42 -0
  69. package/es/utils/eventManager.js +84 -0
  70. package/es/utils/icon.d.ts +1 -0
  71. package/es/utils/icon.js +12 -0
  72. package/es/utils/popper.d.ts +76 -0
  73. package/es/utils/popper.js +257 -0
  74. package/es/utils/screenfull.d.ts +2 -0
  75. package/es/utils/screenfull.js +106 -0
  76. package/lib/assets/iconfont/iconfont.d.ts +21 -0
  77. package/lib/assets/iconfont/iconfont.js +68 -0
  78. package/lib/constants/index.d.ts +60 -0
  79. package/lib/constants/index.js +66 -0
  80. package/lib/control/baseControl/buttonControl.d.ts +60 -0
  81. package/lib/control/baseControl/buttonControl.js +149 -0
  82. package/lib/control/baseControl/control.d.ts +112 -0
  83. package/lib/control/baseControl/control.js +269 -0
  84. package/lib/control/baseControl/index.d.ts +4 -0
  85. package/lib/control/baseControl/index.js +39 -0
  86. package/lib/control/baseControl/popperControl.d.ts +28 -0
  87. package/lib/control/baseControl/popperControl.js +99 -0
  88. package/lib/control/baseControl/selectControl.d.ts +53 -0
  89. package/lib/control/baseControl/selectControl.js +180 -0
  90. package/lib/control/exportImage.d.ts +19 -0
  91. package/lib/control/exportImage.js +80 -0
  92. package/lib/control/fullscreen.d.ts +20 -0
  93. package/lib/control/fullscreen.js +95 -0
  94. package/lib/control/geoLocate.d.ts +17 -0
  95. package/lib/control/geoLocate.js +67 -0
  96. package/lib/control/layerSwitch.d.ts +27 -0
  97. package/lib/control/layerSwitch.js +162 -0
  98. package/lib/control/logo.d.ts +14 -0
  99. package/lib/control/logo.js +55 -0
  100. package/lib/control/mapTheme.d.ts +11 -0
  101. package/lib/control/mapTheme.js +76 -0
  102. package/lib/control/mouseLocation.d.ts +16 -0
  103. package/lib/control/mouseLocation.js +59 -0
  104. package/lib/control/scale.d.ts +35 -0
  105. package/lib/control/scale.js +128 -0
  106. package/lib/control/swipe.d.ts +66 -0
  107. package/lib/control/swipe.js +399 -0
  108. package/lib/control/zoom.d.ts +39 -0
  109. package/lib/control/zoom.js +107 -0
  110. package/lib/css/button.less +77 -0
  111. package/lib/css/control.less +82 -0
  112. package/lib/css/index.css +653 -0
  113. package/lib/css/index.less +13 -0
  114. package/lib/css/l7.less +69 -0
  115. package/lib/css/layerPopup.less +9 -0
  116. package/lib/css/logo.less +21 -0
  117. package/lib/css/mouseLocation.less +9 -0
  118. package/lib/css/popper.less +74 -0
  119. package/lib/css/popup.less +176 -0
  120. package/lib/css/scale.less +37 -0
  121. package/lib/css/select.less +96 -0
  122. package/lib/css/swipe.less +80 -0
  123. package/lib/css/variables.less +29 -0
  124. package/lib/css/zoom.less +34 -0
  125. package/lib/images/layers.png +0 -0
  126. package/lib/images/layers.svg +1 -0
  127. package/lib/images/logo.png +0 -0
  128. package/lib/images/quanping.svg +12 -0
  129. package/lib/index.d.ts +19 -0
  130. package/lib/index.js +844 -0
  131. package/lib/interface.d.ts +29 -0
  132. package/lib/interface.js +5 -0
  133. package/lib/marker-layer.d.ts +46 -0
  134. package/lib/marker-layer.js +518 -0
  135. package/lib/marker.d.ts +66 -0
  136. package/lib/marker.js +502 -0
  137. package/lib/popup/layerPopup.d.ts +105 -0
  138. package/lib/popup/layerPopup.js +348 -0
  139. package/lib/popup/popup.d.ts +147 -0
  140. package/lib/popup/popup.js +594 -0
  141. package/lib/utils/anchor.d.ts +22 -0
  142. package/lib/utils/anchor.js +38 -0
  143. package/lib/utils/eventManager.d.ts +42 -0
  144. package/lib/utils/eventManager.js +92 -0
  145. package/lib/utils/icon.d.ts +1 -0
  146. package/lib/utils/icon.js +19 -0
  147. package/lib/utils/popper.d.ts +76 -0
  148. package/lib/utils/popper.js +264 -0
  149. package/lib/utils/screenfull.d.ts +2 -0
  150. package/lib/utils/screenfull.js +112 -0
  151. package/package.json +5 -5
@@ -0,0 +1,29 @@
1
+ export type ControlEvent = 'show' | 'hide' | 'add' | 'remove' | string;
2
+ export interface IMarkerStyleOption {
3
+ element?: (...args: any[]) => any;
4
+ style: {
5
+ [key: string]: any;
6
+ } | ((...args: any[]) => any);
7
+ className: string;
8
+ field?: string;
9
+ method?: 'sum' | 'max' | 'min' | 'mean';
10
+ radius: number;
11
+ maxZoom: number;
12
+ minZoom: number;
13
+ zoom: number;
14
+ }
15
+ export interface IMarkerLayerOption {
16
+ cluster: boolean;
17
+ clusterOption: Partial<IMarkerStyleOption>;
18
+ /**
19
+ * Default marker options applied to markers added to this layer when not overridden per-marker.
20
+ * Example: { color: '#ff0000', style: { width: '24px', height: '24px' }, className: 'my-marker' }
21
+ */
22
+ markerOption?: Partial<{
23
+ color?: string;
24
+ style?: {
25
+ [key: string]: any;
26
+ };
27
+ className?: string;
28
+ }>;
29
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ import type { IMarker, L7Container } from '@antv/l7-core';
2
+ import { EventEmitter } from 'eventemitter3';
3
+ import type { IMarkerLayerOption } from './interface';
4
+ export default class MarkerLayer extends EventEmitter {
5
+ private markers;
6
+ private markerLayerOption;
7
+ private clusterIndex;
8
+ private points;
9
+ private clusterMarkers;
10
+ private mapsService;
11
+ private scene;
12
+ private zoom;
13
+ private bbox;
14
+ private inited;
15
+ private containerSize;
16
+ constructor(option?: Partial<IMarkerLayerOption>);
17
+ getDefault(): IMarkerLayerOption;
18
+ addTo(scene: L7Container): this;
19
+ private setContainerSize;
20
+ private getContainerSize;
21
+ addMarker(marker: IMarker): void;
22
+ removeMarker(marker: IMarker): void;
23
+ /**
24
+ * 隐藏 marker 在每个 marker 上单独修改属性而不是在 markerContainer 上修改(在 markerContainer 修改会有用户在场景加载完之前调用失败的问题)
25
+ */
26
+ hide(): void;
27
+ /**
28
+ * 显示 marker
29
+ */
30
+ show(): void;
31
+ getMarkers(): IMarker[];
32
+ getOriginMarkers(): IMarker[];
33
+ addMarkers(): void;
34
+ clear(): void;
35
+ destroy(): void;
36
+ private updateMarkers;
37
+ private addPoint;
38
+ private removePoint;
39
+ private initCluster;
40
+ private getClusterMarker;
41
+ private getLeaves;
42
+ private clusterMarker;
43
+ private normalMarker;
44
+ private update;
45
+ private generateElement;
46
+ }
@@ -0,0 +1,509 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
3
+ import { DOM, Satistics, bindAll, boundsContains, lodashUtil, padBounds } from '@antv/l7-utils';
4
+ import { EventEmitter } from 'eventemitter3';
5
+ // @ts-ignore
6
+ // tslint:disable-next-line:no-submodule-imports
7
+ import Supercluster from 'supercluster/dist/supercluster';
8
+ import Marker from "./marker";
9
+ const {
10
+ merge
11
+ } = lodashUtil;
12
+ export default class MarkerLayer extends EventEmitter {
13
+ constructor(option) {
14
+ var _this$markerLayerOpti;
15
+ super();
16
+ _defineProperty(this, "markers", []);
17
+ // 原始的marker列表
18
+ _defineProperty(this, "markerLayerOption", void 0);
19
+ _defineProperty(this, "clusterIndex", void 0);
20
+ _defineProperty(this, "points", []);
21
+ _defineProperty(this, "clusterMarkers", []);
22
+ // 聚合后的marker列表
23
+ _defineProperty(this, "mapsService", void 0);
24
+ _defineProperty(this, "scene", void 0);
25
+ _defineProperty(this, "zoom", void 0);
26
+ _defineProperty(this, "bbox", void 0);
27
+ _defineProperty(this, "inited", void 0);
28
+ _defineProperty(this, "containerSize", void 0);
29
+ this.markerLayerOption = merge(this.getDefault(), option);
30
+ bindAll(['update'], this);
31
+ this.zoom = ((_this$markerLayerOpti = this.markerLayerOption.clusterOption) === null || _this$markerLayerOpti === void 0 ? void 0 : _this$markerLayerOpti.zoom) || -99;
32
+ }
33
+ getDefault() {
34
+ return {
35
+ cluster: false,
36
+ clusterOption: {
37
+ radius: 80,
38
+ maxZoom: 20,
39
+ minZoom: 0,
40
+ zoom: -99,
41
+ style: {},
42
+ className: ''
43
+ }
44
+ };
45
+ }
46
+
47
+ // 执行scene.addMarkerLayer时调用
48
+ addTo(scene) {
49
+ // this.remove();
50
+ this.scene = scene;
51
+ this.mapsService = scene.mapService;
52
+ if (this.markerLayerOption.cluster) {
53
+ this.initCluster();
54
+ this.update();
55
+ // 地图视野变化时,重新计算视野内的聚合点。
56
+ this.mapsService.on('camerachange', this.update); // amap1.x 更新事件
57
+ this.mapsService.on('viewchange', this.update); // amap2.0 更新事件
58
+ }
59
+ // 统一由 layer 管理 marker 的位置更新,避免每个 marker 单独注册地图事件
60
+ this.mapsService.on('camerachange', this.updateMarkers.bind(this));
61
+ this.mapsService.on('viewchange', this.updateMarkers.bind(this));
62
+ this.mapsService.on('camerachange', this.setContainerSize.bind(this)); // amap1.x 更新事件
63
+ this.mapsService.on('viewchange', this.setContainerSize.bind(this)); // amap2.0 更新事件
64
+ this.addMarkers();
65
+ this.inited = true;
66
+ return this;
67
+ }
68
+
69
+ // 设置容器大小
70
+ setContainerSize() {
71
+ if (!this.mapsService) {
72
+ return;
73
+ }
74
+ const container = this.mapsService.getContainer();
75
+ this.containerSize = {
76
+ containerWidth: (container === null || container === void 0 ? void 0 : container.scrollWidth) || 0,
77
+ containerHeight: (container === null || container === void 0 ? void 0 : container.scrollHeight) || 0,
78
+ bounds: this.mapsService.getBounds()
79
+ };
80
+ }
81
+
82
+ // 获取容器尺寸
83
+ getContainerSize() {
84
+ return this.containerSize;
85
+ }
86
+
87
+ // 在图层添加单个marker
88
+ addMarker(marker) {
89
+ const cluster = this.markerLayerOption.cluster;
90
+ marker.getMarkerLayerContainerSize = this.getContainerSize.bind(this);
91
+
92
+ // apply default markerOption if provided by layer
93
+ try {
94
+ const mOpt = this.markerLayerOption.markerOption;
95
+ if (mOpt && marker && typeof marker.getElement === 'function') {
96
+ const el = marker.getElement();
97
+ if (el) {
98
+ // apply className
99
+ if (mOpt.className) {
100
+ // DOM helper available
101
+ try {
102
+ DOM.addClass(el, mOpt.className);
103
+ } catch (e) {
104
+ el.className = `${el.className || ''} ${mOpt.className}`.trim();
105
+ }
106
+ }
107
+ // apply style properties
108
+ if (mOpt.style && typeof mOpt.style === 'object') {
109
+ Object.keys(mOpt.style).forEach(k => {
110
+ try {
111
+ // @ts-ignore
112
+ el.style[k] = mOpt.style[k];
113
+ } catch (e) {
114
+ // ignore invalid styles
115
+ }
116
+ });
117
+ }
118
+ // apply color: try find svg path inside marker element and set fill
119
+ if (mOpt.color) {
120
+ try {
121
+ // querySelector can return SVGPathElement; coerce to any for attribute access
122
+ const svgPath = el.querySelector ? el.querySelector('path') : null;
123
+ if (svgPath && typeof svgPath.setAttribute === 'function') {
124
+ svgPath.setAttribute('fill', mOpt.color);
125
+ } else {
126
+ // fallback: set background color
127
+ el.style.background = mOpt.color;
128
+ }
129
+ } catch (e) {
130
+ // ignore
131
+ }
132
+ }
133
+ }
134
+ }
135
+ } catch (err) {
136
+ // be defensive — don't block marker addition on errors applying defaults
137
+ void err;
138
+ }
139
+ if (cluster) {
140
+ this.addPoint(marker, this.markers.length);
141
+ if (this.mapsService) {
142
+ // 在新增 marker 的时候需要更新聚合信息(哪怕此时的 zoom 没有发生变化)
143
+ const zoom = this.mapsService.getZoom();
144
+ const bbox = this.mapsService.getBounds();
145
+ this.bbox = padBounds(bbox, 0.5);
146
+ this.zoom = Math.floor(zoom);
147
+ this.getClusterMarker(this.bbox, this.zoom);
148
+ }
149
+ }
150
+ this.markers.push(marker);
151
+
152
+ // if layer has been added to a scene, immediately add marker's element into scene
153
+ // this ensures addMarker works both before and after addTo(scene)
154
+ try {
155
+ if (this.inited && this.scene && typeof marker.addTo === 'function') {
156
+ // When cluster mode is enabled, defer actual DOM mounting of original markers
157
+ // to the clustering render pass so that only cluster markers (or the chosen
158
+ // original marker for single-point clusters) are attached. This prevents
159
+ // duplicate DOM nodes / missing event handlers caused by pre-mounting originals.
160
+ if (!this.markerLayerOption.cluster) {
161
+ marker.addTo(this.scene);
162
+ }
163
+ }
164
+ } catch (e) {
165
+ // defensive: do not break on addTo errors
166
+ void e;
167
+ }
168
+ }
169
+ removeMarker(marker) {
170
+ this.markers.indexOf(marker);
171
+ const markerIndex = this.markers.indexOf(marker);
172
+ if (markerIndex > -1) {
173
+ // remove visual element and unbind handlers
174
+ try {
175
+ if (typeof marker.remove === 'function') {
176
+ marker.remove();
177
+ }
178
+ } catch (e) {
179
+ void e;
180
+ }
181
+ this.markers.splice(markerIndex, 1);
182
+ if (this.markerLayerOption.cluster) {
183
+ this.removePoint(markerIndex);
184
+ if (this.mapsService) {
185
+ this.getClusterMarker(this.bbox, this.zoom);
186
+ }
187
+ }
188
+ }
189
+ }
190
+
191
+ /**
192
+ * 隐藏 marker 在每个 marker 上单独修改属性而不是在 markerContainer 上修改(在 markerContainer 修改会有用户在场景加载完之前调用失败的问题)
193
+ */
194
+ hide() {
195
+ this.markers.forEach(m => {
196
+ try {
197
+ if (typeof m.hide === 'function') {
198
+ m.hide();
199
+ } else {
200
+ m.getElement().style.display = 'none';
201
+ }
202
+ } catch (e) {
203
+ void e;
204
+ }
205
+ });
206
+ this.clusterMarkers.forEach(m => {
207
+ try {
208
+ if (typeof m.hide === 'function') {
209
+ m.hide();
210
+ } else {
211
+ m.getElement().style.display = 'none';
212
+ }
213
+ } catch (e) {
214
+ void e;
215
+ }
216
+ });
217
+ }
218
+
219
+ /**
220
+ * 显示 marker
221
+ */
222
+ show() {
223
+ this.markers.forEach(m => {
224
+ try {
225
+ if (typeof m.show === 'function') {
226
+ m.show();
227
+ } else {
228
+ m.getElement().style.display = 'block';
229
+ }
230
+ } catch (e) {
231
+ void e;
232
+ }
233
+ });
234
+ this.clusterMarkers.forEach(m => {
235
+ try {
236
+ if (typeof m.show === 'function') {
237
+ m.show();
238
+ } else {
239
+ m.getElement().style.display = 'block';
240
+ }
241
+ } catch (e) {
242
+ void e;
243
+ }
244
+ });
245
+ }
246
+
247
+ // 返回当下的markers数据,有聚合图时返回聚合的marker列表,否则返回原始maerker列表
248
+ getMarkers() {
249
+ const cluster = this.markerLayerOption.cluster;
250
+ return cluster ? this.clusterMarkers : this.markers;
251
+ }
252
+ getOriginMarkers() {
253
+ return this.markers;
254
+ }
255
+
256
+ // 批量添加marker到scene
257
+ addMarkers() {
258
+ this.getMarkers().forEach(marker => {
259
+ marker.addTo(this.scene);
260
+ });
261
+ }
262
+
263
+ // 清除图层里的marker
264
+ clear() {
265
+ this.markers.forEach(marker => {
266
+ marker.remove();
267
+ });
268
+ this.clusterMarkers.forEach(clusterMarker => {
269
+ clusterMarker.remove();
270
+ });
271
+ this.markers = [];
272
+ this.points = [];
273
+ this.clusterMarkers = [];
274
+ }
275
+ destroy() {
276
+ this.clear();
277
+ this.removeAllListeners();
278
+ this.mapsService.off('camerachange', this.update);
279
+ this.mapsService.off('viewchange', this.update);
280
+ this.mapsService.off('camerachange', this.setContainerSize.bind(this));
281
+ this.mapsService.off('viewchange', this.setContainerSize.bind(this));
282
+ this.mapsService.off('camerachange', this.updateMarkers.bind(this));
283
+ this.mapsService.off('viewchange', this.updateMarkers.bind(this));
284
+ }
285
+ updateMarkers() {
286
+ // update positions for both origin markers and cluster markers
287
+ try {
288
+ this.markers.forEach(m => {
289
+ if (m && typeof m.update === 'function') {
290
+ m.update();
291
+ }
292
+ });
293
+ this.clusterMarkers.forEach(m => {
294
+ if (m && typeof m.update === 'function') {
295
+ m.update();
296
+ }
297
+ });
298
+ } catch (e) {
299
+ void e;
300
+ }
301
+ }
302
+
303
+ // 将marker数据保存在point中
304
+ addPoint(marker, id) {
305
+ const {
306
+ lng,
307
+ lat
308
+ } = marker.getLnglat();
309
+ const feature = {
310
+ geometry: {
311
+ type: 'Point',
312
+ coordinates: [lng, lat]
313
+ },
314
+ properties: _objectSpread(_objectSpread({}, marker.getExtData()), {}, {
315
+ marker_id: id
316
+ })
317
+ };
318
+ this.points.push(feature);
319
+ if (this.clusterIndex) {
320
+ // 在新增点的时候需要更新 cluster 的数据
321
+ this.clusterIndex.load(this.points);
322
+ }
323
+ }
324
+ removePoint(id) {
325
+ const targetIndex = this.points.findIndex(point => point.properties.marker_id === id);
326
+ if (targetIndex > -1) {
327
+ this.points.splice(targetIndex, 1);
328
+ }
329
+ if (this.clusterIndex) {
330
+ // 在删除点的时候需要更新 cluster 的数据
331
+ this.clusterIndex.load(this.points);
332
+ }
333
+ }
334
+ initCluster() {
335
+ if (!this.markerLayerOption.cluster) {
336
+ return;
337
+ }
338
+ const {
339
+ radius,
340
+ minZoom = 0,
341
+ maxZoom
342
+ } = this.markerLayerOption.clusterOption;
343
+ this.clusterIndex = new Supercluster({
344
+ radius,
345
+ minZoom,
346
+ maxZoom
347
+ });
348
+ // @ts-ignore
349
+ this.clusterIndex.load(this.points);
350
+ }
351
+ getClusterMarker(viewBounds, zoom) {
352
+ const viewBBox = viewBounds[0].concat(viewBounds[1]);
353
+ const clusterPoint = this.clusterIndex.getClusters(viewBBox, zoom);
354
+ this.clusterMarkers.forEach(marker => {
355
+ marker.remove();
356
+ });
357
+ this.clusterMarkers = [];
358
+ clusterPoint.forEach(feature => {
359
+ var _feature$properties;
360
+ const {
361
+ field,
362
+ method
363
+ } = this.markerLayerOption.clusterOption;
364
+ // 处理聚合数据
365
+ if ((_feature$properties = feature.properties) !== null && _feature$properties !== void 0 && _feature$properties.cluster_id) {
366
+ var _feature$properties2;
367
+ const clusterData = this.getLeaves((_feature$properties2 = feature.properties) === null || _feature$properties2 === void 0 ? void 0 : _feature$properties2.cluster_id);
368
+ feature.properties.clusterData = clusterData;
369
+ if (field && method) {
370
+ const columnData = clusterData === null || clusterData === void 0 ? void 0 : clusterData.map(item => {
371
+ const data = {
372
+ [field]: item.properties[field]
373
+ };
374
+ return data;
375
+ });
376
+ const column = Satistics.getColumn(columnData, field);
377
+ const stat = Satistics.getSatByColumn(method, column);
378
+ const fieldName = 'point_' + method;
379
+ feature.properties[fieldName] = stat.toFixed(2);
380
+ }
381
+ }
382
+ const marker = this.clusterMarker(feature);
383
+ // attach layer-level re-emission so consumers can listen to cluster marker events
384
+ try {
385
+ // IMarker type may not declare EventEmitter methods; cast to any for runtime attach
386
+ const anyMarker = marker;
387
+ if (anyMarker && typeof anyMarker.on === 'function') {
388
+ anyMarker.on('click', ev => {
389
+ try {
390
+ this.emit('marker:click', {
391
+ marker: anyMarker,
392
+ data: anyMarker.getExtData ? anyMarker.getExtData() : null,
393
+ lngLat: anyMarker.getLnglat ? anyMarker.getLnglat() : null,
394
+ originalEvent: ev
395
+ });
396
+ } catch (e) {
397
+ void e;
398
+ }
399
+ });
400
+ }
401
+ } catch (e) {
402
+ void e;
403
+ }
404
+ this.clusterMarkers.push(marker);
405
+ marker.addTo(this.scene);
406
+ });
407
+ }
408
+ getLeaves(clusterId, limit = Infinity, offset = 0) {
409
+ if (!clusterId) {
410
+ return null;
411
+ }
412
+ return this.clusterIndex.getLeaves(clusterId, limit, offset);
413
+ }
414
+ clusterMarker(feature) {
415
+ var _feature$properties3, _feature$properties4;
416
+ const clusterOption = this.markerLayerOption.clusterOption;
417
+ const {
418
+ element = this.generateElement.bind(this)
419
+ } = clusterOption;
420
+
421
+ // determine cluster count
422
+ let pointCount = (_feature$properties3 = feature.properties) === null || _feature$properties3 === void 0 ? void 0 : _feature$properties3.point_count;
423
+ if (pointCount === undefined && (_feature$properties4 = feature.properties) !== null && _feature$properties4 !== void 0 && _feature$properties4.cluster_id) {
424
+ const leaves = this.getLeaves(feature.properties.cluster_id, Infinity, 0) || [];
425
+ pointCount = leaves.length;
426
+ }
427
+
428
+ // if this cluster effectively contains only one original marker, return the original marker
429
+ if ((pointCount === 1 || pointCount === '1') && feature.properties) {
430
+ // try to get the original marker by marker_id from leaves or properties
431
+ let leaf = null;
432
+ if (feature.properties.cluster_id) {
433
+ const leaves = this.getLeaves(feature.properties.cluster_id, 1, 0);
434
+ leaf = leaves && leaves[0];
435
+ } else if (feature.properties.marker_id !== undefined) {
436
+ leaf = feature;
437
+ }
438
+ if (leaf && leaf.properties && typeof leaf.properties.marker_id === 'number') {
439
+ const origin = this.normalMarker(leaf);
440
+ if (origin) {
441
+ // ensure aggregated properties are available on the original marker
442
+ try {
443
+ if (feature && feature.properties && typeof origin.setExtData === 'function') {
444
+ origin.setExtData(feature.properties);
445
+ }
446
+ } catch (e) {
447
+ void e;
448
+ }
449
+ return origin;
450
+ }
451
+ }
452
+ // fallback: if no marker_id, continue to render cluster element
453
+ }
454
+
455
+ // for real clusters (count > 1) or fallback, create cluster marker element
456
+ let el;
457
+ if (typeof element === 'function') {
458
+ el = element(feature);
459
+ } else {
460
+ // element may be a DOM node already
461
+ el = element;
462
+ }
463
+ const marker = new Marker({
464
+ element: el
465
+ }).setLnglat({
466
+ lng: feature.geometry.coordinates[0],
467
+ lat: feature.geometry.coordinates[1]
468
+ });
469
+ // attach aggregated properties to the cluster marker so getExtData() returns useful info
470
+ if (feature && feature.properties) {
471
+ // @ts-ignore
472
+ marker.setExtData(feature.properties);
473
+ }
474
+ return marker;
475
+ }
476
+ normalMarker(feature) {
477
+ const marker_id = feature.properties.marker_id;
478
+ return this.markers[marker_id];
479
+ }
480
+ update() {
481
+ if (!this.mapsService) {
482
+ return;
483
+ }
484
+ // 当图层中无marker时,无需更新
485
+ if (this.markers.length === 0) {
486
+ return;
487
+ }
488
+ const zoom = this.mapsService.getZoom();
489
+ const bbox = this.mapsService.getBounds();
490
+ if (!this.bbox || Math.abs(zoom - this.zoom) >= 1 || !boundsContains(this.bbox, bbox)) {
491
+ this.bbox = padBounds(bbox, 0.5);
492
+ this.zoom = Math.floor(zoom);
493
+ this.getClusterMarker(this.bbox, this.zoom);
494
+ }
495
+ }
496
+ generateElement(feature) {
497
+ const el = DOM.create('div', 'l7-marker-cluster');
498
+ const label = DOM.create('div', '', el);
499
+ const span = DOM.create('span', '', label);
500
+ const {
501
+ field,
502
+ method
503
+ } = this.markerLayerOption.clusterOption;
504
+ feature.properties.point_count = feature.properties.point_count || 1;
505
+ const text = field && method ? feature.properties['point_' + method] || feature.properties[field] : feature.properties.point_count;
506
+ span.textContent = text;
507
+ return el;
508
+ }
509
+ }
package/es/marker.d.ts ADDED
@@ -0,0 +1,66 @@
1
+ import type { ILngLat, IMarkerContainerAndBounds, IMarkerOption, IPoint, IPopup, L7Container } from '@antv/l7-core';
2
+ import { anchorType } from '@antv/l7-utils';
3
+ import { EventEmitter } from 'eventemitter3';
4
+ export default class Marker extends EventEmitter {
5
+ private markerOption;
6
+ private popup;
7
+ private mapsService;
8
+ private lngLat;
9
+ private scene;
10
+ private added;
11
+ private preLngLat;
12
+ private visible;
13
+ getMarkerLayerContainerSize(): IMarkerContainerAndBounds | void;
14
+ constructor(option?: Partial<IMarkerOption>);
15
+ getDefault(): {
16
+ element: undefined;
17
+ anchor: anchorType;
18
+ offsets: number[];
19
+ color: string;
20
+ draggable: boolean;
21
+ overflowHide: boolean;
22
+ };
23
+ addTo(scene: L7Container): this;
24
+ remove(): this;
25
+ /**
26
+ * Hide the marker visually but keep it in the layer's data structures.
27
+ */
28
+ hide(): this;
29
+ /**
30
+ * Show the marker if it was hidden.
31
+ */
32
+ show(): this;
33
+ setLnglat(lngLat: ILngLat | IPoint): this;
34
+ getLnglat(): ILngLat;
35
+ getElement(): HTMLElement;
36
+ setElement(el: HTMLElement): this;
37
+ openPopup(): this;
38
+ closePopup(): this;
39
+ setPopup(popup: IPopup): this;
40
+ togglePopup(): this;
41
+ getPopup(): IPopup;
42
+ getOffset(): number[];
43
+ setDraggable(draggable: boolean): void;
44
+ getDraggable(): boolean;
45
+ getExtData(): any;
46
+ setExtData(data: any): void;
47
+ update(): void;
48
+ private updatePositionWhenZoom;
49
+ private onMapClick;
50
+ private getCurrentContainerSize;
51
+ private updateDraggable;
52
+ private onMarkerDragStart;
53
+ private onMarkerDragMove;
54
+ private onMarkerDragEnd;
55
+ private updatePosition;
56
+ private init;
57
+ private registerMarkerEvent;
58
+ private unRegisterMarkerEvent;
59
+ private eventHandle;
60
+ /**
61
+ * 高德 2.x 使用了 fastClick.js 避免延迟,导致 IOS 移动端的 click 事件不会正常触发,需要手动触发
62
+ * @param e
63
+ */
64
+ private touchStartTime;
65
+ private polyfillEvent;
66
+ }