@hzab/map-combine 0.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +67 -0
  3. package/package.json +56 -0
  4. package/src/assets/Thumbs.db +0 -0
  5. package/src/assets/add.png +0 -0
  6. package/src/assets/point.png +0 -0
  7. package/src/basic/ContextMenu.tsx +49 -0
  8. package/src/basic/MapCombine.ts +67 -0
  9. package/src/basic/MapElement.ts +32 -0
  10. package/src/basic/MapEvent.ts +18 -0
  11. package/src/basic/Point.ts +176 -0
  12. package/src/basic/PointAggregation.tsx +189 -0
  13. package/src/basic/Polygon.ts +180 -0
  14. package/src/basic/Polyline.ts +194 -0
  15. package/src/basic/ReactPoint.tsx +357 -0
  16. package/src/basic/ReactPopup.tsx +34 -0
  17. package/src/basic/Tile3D.ts +99 -0
  18. package/src/cesium/CesiumEvent.ts +86 -0
  19. package/src/cesium/CesiumMap.ts +167 -0
  20. package/src/cesium/CesiumPoint.ts +137 -0
  21. package/src/cesium/CesiumPolygon.ts +368 -0
  22. package/src/cesium/CesiumPolyline.ts +382 -0
  23. package/src/cesium/CesiumTile3D.ts +100 -0
  24. package/src/mine/MineEvent.ts +29 -0
  25. package/src/mine/MineMap.ts +90 -0
  26. package/src/mine/MinePoint.ts +139 -0
  27. package/src/mine/MinePolygon.ts +388 -0
  28. package/src/mine/MinePolyline.ts +359 -0
  29. package/src/mine/MineTile3D.ts +32 -0
  30. package/src/openlayer/OpenlayerEvent.ts +75 -0
  31. package/src/openlayer/OpenlayerMap.ts +149 -0
  32. package/src/openlayer/OpenlayerPoint.ts +177 -0
  33. package/src/openlayer/OpenlayerPolygon.ts +300 -0
  34. package/src/openlayer/OpenlayerPolyline.ts +289 -0
  35. package/src/utils/Image.ts +46 -0
  36. package/src/utils/PolygonEditor.ts +159 -0
  37. package/src/utils/PolylineEditor.ts +149 -0
  38. package/src/utils/Projection.ts +46 -0
  39. package/src/utils/index.ts +131 -0
  40. package/src/utils/static.ts +7 -0
@@ -0,0 +1,180 @@
1
+ import Eventful from "zrender/lib/core/Eventful"
2
+
3
+ import { MapElement, MapElementOption } from "./MapElement"
4
+ import { MapCombine } from "./MapCombine"
5
+ import { ContextMenuItem } from "./ContextMenu"
6
+
7
+ export interface PolygonOption<K> extends MapElementOption {
8
+ show: boolean
9
+ cursor: string
10
+ coordinates?: number[][]
11
+ editable: boolean
12
+ userdata: K
13
+ silent: boolean
14
+ lineWidth: number
15
+ stroke: string
16
+ dash: boolean
17
+ fill: string
18
+ menu?: ContextMenuItem[];
19
+ }
20
+
21
+ export class Polygon<K = undefined> extends MapElement<PolygonOption<K>> {
22
+ type = 'Polygon'
23
+ event = new Eventful<{
24
+ 'data-loaded': () => void
25
+ 'pointer-in': () => void
26
+ 'pointer-out': () => void
27
+ 'left-click': () => void
28
+ 'right-click': () => void
29
+ 'start-edit': () => void
30
+ 'stop-edit': () => void
31
+ 'update': (keys: Set<string>) => void
32
+ 'destroy': () => void
33
+ }>()
34
+
35
+ get userdata() {
36
+ return this._option.userdata
37
+ }
38
+
39
+ get cursor() {
40
+ return this._option.cursor
41
+ }
42
+
43
+ get show() {
44
+ return this._option.show
45
+ }
46
+
47
+ set show(val) {
48
+ if (this._option.show != val) {
49
+ this._option.show = val
50
+ this._update('show')
51
+ }
52
+ }
53
+
54
+ get menu() {
55
+ return this._option.menu
56
+ }
57
+
58
+ set menu(val) {
59
+ this._option.menu = val
60
+ }
61
+
62
+ get silent() {
63
+ return this._option.silent
64
+ }
65
+
66
+ set silent(val) {
67
+ if (this._option.silent != val) {
68
+ this._option.silent = val
69
+ this._update('silent')
70
+ }
71
+ }
72
+
73
+ get editable() {
74
+ return this._option.editable
75
+ }
76
+
77
+ set editable(val) {
78
+ if (this._option.editable != val) {
79
+ this._option.editable = val
80
+ this._update('editable')
81
+ }
82
+ }
83
+
84
+ get coordinates() {
85
+ return this._option.coordinates
86
+ }
87
+
88
+ set coordinates(val) {
89
+ if (this._option.coordinates != val) {
90
+ this._option.coordinates = val
91
+ this._update('coordinates')
92
+ }
93
+ }
94
+
95
+ get lineWidth() {
96
+ return this._option.lineWidth
97
+ }
98
+
99
+ set lineWidth(val) {
100
+ if (this._option.lineWidth != val) {
101
+ this._option.lineWidth = val
102
+ this._update('lineWidth')
103
+ }
104
+ }
105
+
106
+ get stroke() {
107
+ return this._option.stroke
108
+ }
109
+
110
+ set stroke(val) {
111
+ if (this._option.stroke != val) {
112
+ this._option.stroke = val
113
+ this._update('stroke')
114
+ }
115
+ }
116
+ get dash() {
117
+ return this._option.dash
118
+ }
119
+
120
+ set dash(val) {
121
+ if (this._option.dash != val) {
122
+ this._option.dash = val
123
+ this._update('dash')
124
+ }
125
+ }
126
+
127
+ get fill() {
128
+ return this._option.fill
129
+ }
130
+
131
+ set fill(val) {
132
+ if (this._option.fill != val) {
133
+ this._option.fill = val
134
+ this._update('fill')
135
+ }
136
+ }
137
+
138
+
139
+ constructor(map: MapCombine, option: Partial<PolygonOption<K>> = {}) {
140
+ super(map, Object.assign({ ...Polygon.option }, option))
141
+ }
142
+
143
+ static option: PolygonOption<undefined> = {
144
+ name: '线',
145
+ show: true,
146
+ editable: false,
147
+ cursor: 'pointer',
148
+ userdata: undefined,
149
+ silent: false,
150
+ lineWidth: 2,
151
+ stroke: '#FA792A',
152
+ dash: false,
153
+ fill: '#43F65588',
154
+ }
155
+
156
+ private _needUpdate?: Set<string>
157
+ private _update(key: string) {
158
+ if (this._needUpdate) {
159
+ this._needUpdate.add(key)
160
+ } else {
161
+ this._needUpdate = new Set([key])
162
+ setTimeout(() => {
163
+ this.event.trigger('update', this._needUpdate)
164
+ this._needUpdate = undefined
165
+ });
166
+ }
167
+ }
168
+
169
+ protected _onDestroy(): void {
170
+ this.event.trigger('destroy')
171
+ }
172
+
173
+
174
+ startEdit() {
175
+ this.event.trigger('start-edit')
176
+ }
177
+ stopEdit() {
178
+ this.event.trigger('stop-edit')
179
+ }
180
+ }
@@ -0,0 +1,194 @@
1
+ import Eventful from "zrender/lib/core/Eventful"
2
+
3
+ import { MapElement, MapElementOption } from "./MapElement"
4
+ import { MapCombine } from "./MapCombine"
5
+ import { ContextMenuItem } from "./ContextMenu"
6
+
7
+ export interface PolylineOption<K> extends MapElementOption {
8
+ show: boolean
9
+ cursor: string
10
+ coordinates?: number[][]
11
+ editable: boolean
12
+ userdata: K
13
+ silent: boolean
14
+ lineWidth: number
15
+ stroke: string
16
+ dash: boolean
17
+ menu?: ContextMenuItem[];
18
+ icon: string
19
+ flow: boolean
20
+ }
21
+
22
+ export class Polyline<K = undefined> extends MapElement<PolylineOption<K>>{
23
+
24
+
25
+ type = 'Polyline'
26
+ event = new Eventful<{
27
+ 'data-loaded': () => void
28
+ 'pointer-in': () => void
29
+ 'pointer-out': () => void
30
+ 'left-click': () => void
31
+ 'right-click': () => void
32
+ 'start-edit': () => void
33
+ 'stop-edit': () => void
34
+ 'update': (keys: Set<string>) => void
35
+ 'destroy': () => void
36
+ }>()
37
+
38
+ get userdata() {
39
+ return this._option.userdata
40
+ }
41
+
42
+ get cursor() {
43
+ return this._option.cursor
44
+ }
45
+
46
+ get show() {
47
+ return this._option.show
48
+ }
49
+
50
+ set show(val) {
51
+ if (this._option.show != val) {
52
+ this._option.show = val
53
+ this._update('show')
54
+ }
55
+ }
56
+
57
+ get menu() {
58
+ return this._option.menu
59
+ }
60
+
61
+ set menu(val) {
62
+ this._option.menu = val
63
+ }
64
+
65
+ get silent() {
66
+ return this._option.silent
67
+ }
68
+
69
+ set silent(val) {
70
+ if (this._option.silent != val) {
71
+ this._option.silent = val
72
+ this._update('silent')
73
+ }
74
+ }
75
+
76
+ get editable() {
77
+ return this._option.editable
78
+ }
79
+
80
+ set editable(val) {
81
+ if (this._option.editable != val) {
82
+ this._option.editable = val
83
+ this._update('editable')
84
+ }
85
+ }
86
+
87
+ get coordinates() {
88
+ return this._option.coordinates
89
+ }
90
+
91
+ set coordinates(val) {
92
+ if (this._option.coordinates != val) {
93
+ this._option.coordinates = val
94
+ this._update('coordinates')
95
+ }
96
+ }
97
+
98
+ get lineWidth() {
99
+ return this._option.lineWidth
100
+ }
101
+
102
+ set lineWidth(val) {
103
+ if (this._option.lineWidth != val) {
104
+ this._option.lineWidth = val
105
+ this._update('lineWidth')
106
+ }
107
+ }
108
+
109
+ get stroke() {
110
+ return this._option.stroke
111
+ }
112
+
113
+ set stroke(val) {
114
+ if (this._option.stroke != val) {
115
+ this._option.stroke = val
116
+ this._update('stroke')
117
+ }
118
+ }
119
+ get dash() {
120
+ return this._option.dash
121
+ }
122
+
123
+ set dash(val) {
124
+ if (this._option.dash != val) {
125
+ this._option.dash = val
126
+ this._update('dash')
127
+ }
128
+ }
129
+
130
+ get icon() {
131
+ return this._option.icon
132
+ }
133
+
134
+ set icon(val) {
135
+ if (this._option.icon != val) {
136
+ this._option.icon = val
137
+ this._update('icon')
138
+ }
139
+ }
140
+
141
+ get flow() {
142
+ return this._option.flow
143
+ }
144
+
145
+ set flow(val) {
146
+ if (this._option.flow != val) {
147
+ this._option.flow = val
148
+ this._update('flow')
149
+ }
150
+ }
151
+
152
+
153
+ constructor(map: MapCombine, option: Partial<PolylineOption<K>> = {}) {
154
+ super(map, Object.assign({ ...Polyline.option }, option))
155
+ }
156
+
157
+ static option: PolylineOption<undefined> = {
158
+ name: '线',
159
+ show: true,
160
+ editable: false,
161
+ cursor: 'pointer',
162
+ userdata: undefined,
163
+ silent: false,
164
+ lineWidth: 2,
165
+ stroke: '#FA792A',
166
+ dash: false,
167
+ icon: '',
168
+ flow: false,
169
+ }
170
+
171
+ private _needUpdate?: Set<string>
172
+ private _update(key: string) {
173
+ if (this._needUpdate) {
174
+ this._needUpdate.add(key)
175
+ } else {
176
+ this._needUpdate = new Set([key])
177
+ setTimeout(() => {
178
+ this.event.trigger('update', this._needUpdate)
179
+ this._needUpdate = undefined
180
+ });
181
+ }
182
+ }
183
+
184
+ protected _onDestroy(): void {
185
+ this.event.trigger('destroy')
186
+ }
187
+
188
+ startEdit() {
189
+ this.event.trigger('start-edit')
190
+ }
191
+ stopEdit() {
192
+ this.event.trigger('stop-edit')
193
+ }
194
+ }
@@ -0,0 +1,357 @@
1
+ import { ReactElement } from "react";
2
+ import { MapElement, MapElementOption } from "./MapElement";
3
+ import Eventful from "zrender/lib/core/Eventful";
4
+ import { MapCombine } from "./MapCombine";
5
+ import ReactDOM from "react-dom";
6
+ import { ContextMenuItem } from "./ContextMenu";
7
+
8
+ export interface ReactPointOption<K> extends MapElementOption {
9
+ show: boolean;
10
+ coordinates?: number[];
11
+ silent: boolean;
12
+ element: (props: K) => ReactElement;
13
+ center: number[];
14
+ rotation: number;
15
+ editable: boolean;
16
+ props: K;
17
+ menu?: ContextMenuItem[];
18
+ }
19
+
20
+ export class ReactPoint<K = undefined> extends MapElement<ReactPointOption<K>> {
21
+ type: "ReactPoint";
22
+ event = new Eventful<{
23
+ "pointer-in": () => void;
24
+ "pointer-out": () => void;
25
+ "left-click": () => void;
26
+ "right-click": () => void;
27
+ update: (keys: Set<string>) => void;
28
+ destroy: () => void;
29
+ }>();
30
+
31
+ get show() {
32
+ return this._option.show;
33
+ }
34
+
35
+ set show(val) {
36
+ if (this._option.show != val) {
37
+ this._option.show = val;
38
+ this._update("show");
39
+ }
40
+ }
41
+
42
+ get menu() {
43
+ return this._option.menu;
44
+ }
45
+
46
+ set menu(val) {
47
+ this._option.menu = val;
48
+ }
49
+
50
+ get props() {
51
+ return this._option.props;
52
+ }
53
+
54
+ set props(val) {
55
+ if (this._option.props != val) {
56
+ this._option.props = val;
57
+ this._update("props");
58
+ }
59
+ }
60
+
61
+ get silent() {
62
+ return this._option.silent;
63
+ }
64
+
65
+ set silent(val) {
66
+ if (this._option.silent != val) {
67
+ this._option.silent = val;
68
+ this._update("silent");
69
+ }
70
+ }
71
+
72
+ get editable() {
73
+ return this._option.editable;
74
+ }
75
+
76
+ set editable(val) {
77
+ if (this._option.editable != val) {
78
+ this._option.editable = val;
79
+ this._update("editable");
80
+ }
81
+ }
82
+
83
+ get coordinates() {
84
+ return this._option.coordinates;
85
+ }
86
+
87
+ set coordinates(val) {
88
+ if (this._option.coordinates != val) {
89
+ this._option.coordinates = val;
90
+ this._update("coordinates");
91
+ }
92
+ }
93
+
94
+ get center() {
95
+ return this._option.center;
96
+ }
97
+
98
+ set center(val) {
99
+ if (this._option.center != val) {
100
+ this._option.center = val;
101
+ this._update("center");
102
+ }
103
+ }
104
+
105
+ get rotation() {
106
+ return this._option.rotation;
107
+ }
108
+
109
+ set rotation(val) {
110
+ if (this._option.rotation != val) {
111
+ this._option.rotation = val;
112
+ this._update("rotation");
113
+ }
114
+ }
115
+
116
+ get element() {
117
+ return this._option.element;
118
+ }
119
+
120
+ set element(val) {
121
+ if (this._option.element != val) {
122
+ this._option.element = val;
123
+ this._update("element");
124
+ }
125
+ }
126
+
127
+ constructor(map: MapCombine, option: Partial<ReactPointOption<K>> = {}) {
128
+ super(map, Object.assign({ ...ReactPoint.option }, option));
129
+ }
130
+
131
+ static option: ReactPointOption<undefined> = {
132
+ name: "点",
133
+ show: true,
134
+ editable: false,
135
+ center: [0.5, 0.5],
136
+ rotation: 0,
137
+ props: undefined,
138
+ silent: false,
139
+ element: () => (
140
+ <div
141
+ style={{
142
+ backgroundColor: "#43F655",
143
+ width: "16px",
144
+ height: "16px",
145
+ }}
146
+ ></div>
147
+ ),
148
+ };
149
+
150
+ private _needUpdate?: Set<string>;
151
+ private _update(key: string) {
152
+ if (this._needUpdate) {
153
+ this._needUpdate.add(key);
154
+ } else {
155
+ this._needUpdate = new Set([key]);
156
+ setTimeout(() => {
157
+ this.event.trigger("update", this._needUpdate);
158
+ this._needUpdate = undefined;
159
+ });
160
+ }
161
+ }
162
+
163
+ protected _onDestroy(): void {
164
+ this.event.trigger("destroy");
165
+ }
166
+ }
167
+
168
+ export function drawReactPoint(map: MapCombine, point: ReactPoint<unknown>) {
169
+ const { event, htmllayer } = map;
170
+ let status = 0;
171
+ let skip = 0;
172
+
173
+ const root = document.createElement("div");
174
+ root.style.transform = `translate(-${point.center[0] * 100}%,-${point.center[1] * 100}%) rotateZ(${
175
+ point.rotation
176
+ }deg)`;
177
+ root.style.transformOrigin = `${point.center[0] * 100}% ${point.center[1] * 100}%`;
178
+ root.style.position = "absolute";
179
+ root.style.visibility = point.show ? "visible" : "hidden";
180
+ root.style.pointerEvents = point.silent ? "none" : "all";
181
+ root.style.userSelect = "none";
182
+ root.addEventListener("pointerenter", () => {
183
+ status == 2 && point.event.trigger("pointer-in");
184
+ });
185
+ root.addEventListener("pointerleave", () => {
186
+ status == 2 && point.event.trigger("pointer-out");
187
+ });
188
+ root.addEventListener("click", () => {
189
+ status == 2 && point.event.trigger("left-click");
190
+ });
191
+ root.addEventListener("contextmenu", (e) => {
192
+ // e.stopPropagation()
193
+ e.preventDefault();
194
+ if (point.menu) {
195
+ map.menu.show(point.menu);
196
+ }
197
+ status == 2 && point.event.trigger("right-click");
198
+ });
199
+ ReactDOM.render(point.element(point.props), root);
200
+
201
+ let delay = 0;
202
+
203
+ root.addEventListener("pointerdown", () => {
204
+ if (point.editable && status == 2) {
205
+ delay = window.setTimeout(() => {
206
+ delay = 0;
207
+ status = 3;
208
+ map.moveable = false;
209
+ root.style.pointerEvents = "none";
210
+ }, 300);
211
+ }
212
+ });
213
+
214
+ if (point.coordinates) {
215
+ status = 2;
216
+ const p = map.geographyTcanvas(point.coordinates);
217
+ root.style.left = `${p[0]}px`;
218
+ root.style.top = `${p[1]}px`;
219
+ htmllayer.appendChild(root);
220
+ }
221
+
222
+ const onViewChange = () => {
223
+ if (point.coordinates) {
224
+ const p = map.geographyTcanvas(point.coordinates);
225
+ root.style.left = `${p[0]}px`;
226
+ root.style.top = `${p[1]}px`;
227
+ root.style.zIndex = `${point.coordinates[2] ?? ""}`;
228
+ }
229
+ };
230
+
231
+ const onUpdate = (e: Set<string>) => {
232
+ if (skip) {
233
+ skip--;
234
+ return;
235
+ }
236
+ const keys = new Set();
237
+ e.forEach((key) => {
238
+ switch (key) {
239
+ case "show":
240
+ root.style.visibility = point.show ? "visible" : "hidden";
241
+ break;
242
+ case "editable":
243
+ break;
244
+ case "props":
245
+ keys.add("dom");
246
+ break;
247
+ case "element":
248
+ keys.add("dom");
249
+ break;
250
+ case "coordinates":
251
+ if (point.coordinates) {
252
+ const p = map.geographyTcanvas(point.coordinates);
253
+ root.style.left = `${p[0]}px`;
254
+ root.style.top = `${p[1]}px`;
255
+ root.style.zIndex = `${point.coordinates[2] ?? ""}`;
256
+ switch (status) {
257
+ case 0:
258
+ htmllayer.appendChild(root);
259
+ status = 2;
260
+ break;
261
+ case 1:
262
+ status = 2;
263
+ break;
264
+ }
265
+ } else {
266
+ root.remove();
267
+ status = 0;
268
+ }
269
+
270
+ break;
271
+
272
+ case "center":
273
+ keys.add("transform");
274
+ break;
275
+ case "rotation":
276
+ keys.add("transform");
277
+ break;
278
+ default:
279
+ throw new Error(`${key} 还不支持修改`);
280
+ }
281
+ });
282
+
283
+ keys.forEach((e) => {
284
+ switch (e) {
285
+ case "transform":
286
+ root.style.transform = `translate(-${point.center[0] * 100}%,-${point.center[1] * 100}%) rotateZ(${
287
+ point.rotation
288
+ }deg)`;
289
+ root.style.transformOrigin = `${point.center[0] * 100}% ${point.center[1] * 100}%`;
290
+ break;
291
+ case "dom":
292
+ ReactDOM.render(point.element(point.props), root);
293
+ break;
294
+ }
295
+ });
296
+ };
297
+
298
+ const onMouseMove = () => {
299
+ if (delay) {
300
+ clearTimeout(delay);
301
+ delay = 0;
302
+ }
303
+ switch (status) {
304
+ case 0:
305
+ status = 1;
306
+ root.style.left = `${event.canvas[0]}px`;
307
+ root.style.top = `${event.canvas[1]}px`;
308
+ htmllayer.appendChild(root);
309
+ break;
310
+ case 1:
311
+ case 3:
312
+ root.style.left = `${event.canvas[0]}px`;
313
+ root.style.top = `${event.canvas[1]}px`;
314
+ break;
315
+ }
316
+ };
317
+
318
+ const onClick = () => {
319
+ if (status == 1) {
320
+ status = 2;
321
+ skip++;
322
+ point.coordinates = event.geography;
323
+ }
324
+ };
325
+
326
+ const onPointerUp = () => {
327
+ if (delay) {
328
+ clearTimeout(delay);
329
+ delay = 0;
330
+ }
331
+ if (point.editable && status == 3) {
332
+ status = 2;
333
+ map.moveable = true;
334
+ root.style.pointerEvents = point.silent ? "none" : "all";
335
+ skip++;
336
+ point.coordinates = event.geography;
337
+ }
338
+ };
339
+
340
+ const onDestroy = () => {
341
+ root.remove();
342
+ ReactDOM.unmountComponentAtNode(root);
343
+ event.off("view-change", onViewChange);
344
+ event.off("pointer-move", onMouseMove);
345
+ event.off("left-click", onClick);
346
+ event.off("pointer-up", onPointerUp);
347
+ point.event.off("update", onUpdate);
348
+ point.event.off("destroy", onDestroy);
349
+ };
350
+
351
+ event.on("view-change", onViewChange);
352
+ event.on("pointer-move", onMouseMove);
353
+ event.on("left-click", onClick);
354
+ event.on("pointer-up", onPointerUp);
355
+ point.event.on("update", onUpdate);
356
+ point.event.on("destroy", onDestroy);
357
+ }