@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,359 @@
1
+
2
+ import { Polyline } from "../basic/Polyline";
3
+ import { ChainNode, PolylineEditor } from "../utils/PolylineEditor";
4
+ import { MineMap } from './MineMap';
5
+ import iconPoint from '../assets/point.png'
6
+ import iconAdd from '../assets/add.png'
7
+
8
+
9
+ function createImgNode(
10
+ onPointerDown: () => void,
11
+ onPointerUp: () => void,
12
+ onDbClick: () => void,
13
+ ) {
14
+ const img = document.createElement('img')
15
+ img.src = iconPoint
16
+ img.width = 16
17
+ img.height = 16
18
+ img.style.cursor = 'move'
19
+ img.addEventListener('pointerdown', onPointerDown)
20
+ img.addEventListener('pointerup', onPointerUp)
21
+ img.addEventListener('dblclick', onDbClick)
22
+ const marker = new minemap.Marker({
23
+ draggable: false,
24
+ element: img,
25
+ offset: [-8, -8],
26
+ })
27
+ return marker
28
+ }
29
+
30
+ function createImgVirtul(onPointerDown: () => void) {
31
+ const img = document.createElement('img')
32
+ img.src = iconAdd
33
+ img.width = 16
34
+ img.height = 16
35
+ img.style.cursor = 'pointer'
36
+ img.addEventListener('pointerdown', onPointerDown)
37
+ const marker = new minemap.Marker({
38
+ draggable: false,
39
+ element: img,
40
+ offset: [-8, -8],
41
+ })
42
+ return marker
43
+ }
44
+
45
+
46
+ function getLayerOption(polyline: Polyline<unknown>) {
47
+ return {
48
+ id: polyline.name,
49
+ source: polyline.name,
50
+ type: "line",
51
+ translation: [0, 0, 1000],
52
+ "depth-test": false,
53
+ layout: {
54
+ visibility: polyline.show ? "visible" : 'none',
55
+ },
56
+ paint: polyline.dash ? {
57
+ "line-dasharray": [10, 10],
58
+ "line-color": polyline.stroke,
59
+ "line-width": polyline.lineWidth
60
+ } : {
61
+ "line-color": polyline.stroke,
62
+ "line-width": polyline.lineWidth
63
+ },
64
+ }
65
+ }
66
+
67
+
68
+ function main(map: MineMap, polyline: Polyline<unknown>) {
69
+ const { viewer } = map
70
+ const data = {
71
+ type: "FeatureCollection",
72
+ features: [],
73
+ }
74
+ viewer.addSource(polyline.name, {
75
+ type: "geojson",
76
+ data
77
+ });
78
+
79
+ const cource = viewer.getSource(polyline.name)
80
+
81
+ viewer.addLayer(getLayerOption(polyline));
82
+
83
+ let status = 0
84
+ let skip = 0
85
+ const editor = new PolylineEditor<any, any>()
86
+ let activeNode: ChainNode<any, any>
87
+ editor.on('create-node', (n) => {
88
+ if (n.type == 'node') {
89
+ const maker = createImgNode(() => {
90
+ status = 4
91
+ activeNode = n
92
+ map.moveable = false
93
+ }, () => {
94
+ if (status == 4) {
95
+ status = 3
96
+ map.moveable = true
97
+ activeNode = undefined
98
+ }
99
+ }, () => {
100
+ n.destroy()
101
+ updateCoordinate(editor.getCoordinates())
102
+ })
103
+ maker.setLngLat(n.position).addTo(viewer)
104
+
105
+ n.shape = maker
106
+ } else {
107
+ const maker = createImgVirtul(() => {
108
+ status = 4
109
+ activeNode = n.insert()
110
+ map.moveable = false
111
+ })
112
+ maker.setLngLat(n.position).addTo(viewer)
113
+ viewer.addMarker(maker)
114
+ n.shape = maker
115
+ }
116
+ })
117
+
118
+ editor.on('update-node', (n) => {
119
+ n.shape.setLngLat(n.position)
120
+ })
121
+ editor.on('remove-node', (n) => {
122
+ viewer.removeMarker(n.shape)
123
+ })
124
+ editor.on('empty', () => {
125
+ // source.removeFeature(feature)
126
+ status = 0
127
+ })
128
+
129
+ const updateCoordinate = (coordinates) => {
130
+ if (coordinates) {
131
+ data.features[0] = {
132
+ type: "Feature",
133
+ geometry: {
134
+ type: "LineString",
135
+ coordinates: coordinates,
136
+ },
137
+ properties: {
138
+ id: polyline.name,
139
+ },
140
+ }
141
+ } else {
142
+ data.features = []
143
+ }
144
+ cource.setData(data)
145
+ }
146
+
147
+
148
+
149
+
150
+
151
+ if (polyline.coordinates) {
152
+ status = 2
153
+ updateCoordinate(polyline.coordinates)
154
+ }
155
+ const onUpdate = (e: Set<string>) => {
156
+ if (skip) {
157
+ skip--
158
+ return
159
+ }
160
+
161
+ const keys = new Set()
162
+
163
+ e.forEach(key => {
164
+ switch (key) {
165
+ case 'show':
166
+ keys.add('layer')
167
+ break;
168
+ case 'editable':
169
+ break;
170
+ case 'coordinates':
171
+ updateCoordinate(polyline.coordinates)
172
+ if (polyline.coordinates) {
173
+ status = 2
174
+ } else {
175
+ status = 0
176
+ }
177
+ break;
178
+ case 'lineWidth':
179
+ keys.add('layer')
180
+ break;
181
+ case 'stroke':
182
+ keys.add('layer')
183
+ break;
184
+ case 'dash':
185
+ keys.add('layer')
186
+ break;
187
+ default:
188
+ throw new Error(`${key} 还不支持修改`)
189
+ }
190
+ })
191
+
192
+ keys.forEach(e => {
193
+ switch (e) {
194
+ case 'layer':
195
+ viewer.removeLayer(polyline.name)
196
+ viewer.addLayer(getLayerOption(polyline));
197
+ break;
198
+ }
199
+ })
200
+ }
201
+
202
+ const onPointerIn = () => {
203
+ map.cursor = polyline.cursor
204
+ if (status == 2) {
205
+
206
+ polyline.event.trigger('pointer-in')
207
+ }
208
+
209
+ }
210
+
211
+ const onPointerOut = () => {
212
+ map.cursor = 'default'
213
+ if (status == 2) {
214
+
215
+ polyline.event.trigger('pointer-out')
216
+ }
217
+ }
218
+
219
+ let cache = []
220
+
221
+ const onClick = (e: any) => {
222
+ switch (status) {
223
+ case 0:
224
+ status = 1
225
+ cache = [[e.lngLat.lng, e.lngLat.lat], [e.lngLat.lng, e.lngLat.lat]]
226
+ break;
227
+ case 1:
228
+ cache.push(cache[cache.length - 1])
229
+ break;
230
+ }
231
+ }
232
+
233
+ const onPointerMove = (e: any) => {
234
+ switch (status) {
235
+ case 1:
236
+ cache.pop()
237
+ cache.push([e.lngLat.lng, e.lngLat.lat])
238
+ updateCoordinate(cache)
239
+ break;
240
+ case 4:
241
+ activeNode.update([e.lngLat.lng, e.lngLat.lat])
242
+ updateCoordinate(editor.getCoordinates())
243
+ break;
244
+ }
245
+ }
246
+
247
+ const onDbClick = (e) => {
248
+ switch (status) {
249
+ case 1:
250
+ status = 2
251
+ skip++
252
+ cache.pop()
253
+ cache.pop()
254
+ polyline.coordinates = cache
255
+ polyline.event.trigger('pointer-in')
256
+ break;
257
+ case 3:
258
+ if (!skip) {
259
+ polyline.event.trigger('stop-edit')
260
+ } else {
261
+ skip = 0
262
+ }
263
+
264
+ break;
265
+ }
266
+ }
267
+
268
+ const onLineDbClick = () => {
269
+ switch (status) {
270
+ case 2:
271
+
272
+
273
+ polyline.event.trigger('start-edit')
274
+
275
+ break;
276
+ }
277
+ }
278
+
279
+ const onLineClick = () => {
280
+ switch (status) {
281
+ case 2:
282
+ polyline.event.trigger('left-click')
283
+ break;
284
+ }
285
+ }
286
+ const onLineRClick = () => {
287
+ if (polyline.menu) {
288
+ map.menu.show(polyline.menu);
289
+ }
290
+ switch (status) {
291
+ case 2:
292
+ polyline.event.trigger('right-click')
293
+ break;
294
+ }
295
+ }
296
+
297
+ const onStartEdit = () => {
298
+ if (status == 2) {
299
+ status = 3
300
+ map.cursor = 'default'
301
+ editor.setCoordinates(polyline.coordinates)
302
+ skip = 1
303
+ }
304
+ }
305
+
306
+ const onStopEdit = () => {
307
+ if (status == 3) {
308
+ status = 2
309
+ skip++
310
+ polyline.coordinates = editor.getCoordinates()
311
+ editor.setCoordinates([])
312
+ }
313
+ }
314
+
315
+
316
+ const onDestroy = () => {
317
+ viewer.removeLayer(polyline.name)
318
+ viewer.removeSource(polyline.name)
319
+ viewer.off('mouseover', polyline.name, onPointerIn)
320
+ viewer.off('mouseout', polyline.name, onPointerOut)
321
+ viewer.off('dblclick', polyline.name, onLineDbClick)
322
+ viewer.off('click', polyline.name, onLineClick)
323
+ viewer.off('contextmenu', polyline.name, onLineRClick)
324
+ viewer.off('click', onClick)
325
+ viewer.off('mousemove', onPointerMove)
326
+ viewer.off('dblclick', onDbClick)
327
+
328
+ polyline.event.off('update', onUpdate)
329
+ polyline.event.off('destroy', onDestroy)
330
+ polyline.event.off('start-edit', onStartEdit)
331
+ polyline.event.off('stop-edit', onStopEdit)
332
+ }
333
+
334
+ viewer.on('mouseover', polyline.name, onPointerIn)
335
+ viewer.on('mouseout', polyline.name, onPointerOut)
336
+ viewer.on('dblclick', polyline.name, onLineDbClick)
337
+ viewer.on('click', polyline.name, onLineClick)
338
+ viewer.on('contextmenu', polyline.name, onLineRClick)
339
+ viewer.on('click', onClick)
340
+ viewer.on('mousemove', onPointerMove)
341
+ viewer.on('dblclick', onDbClick)
342
+
343
+ polyline.event.on('update', onUpdate)
344
+ polyline.event.on('destroy', onDestroy)
345
+ polyline.event.on('start-edit', onStartEdit)
346
+ polyline.event.on('stop-edit', onStopEdit)
347
+ }
348
+
349
+
350
+ export function drawPolyline(map: MineMap, polyline: Polyline<unknown>) {
351
+ const { viewer } = map
352
+ if (viewer.loaded()) {
353
+ main(map, polyline)
354
+ } else {
355
+ viewer.once('load', () => {
356
+ main(map, polyline)
357
+ })
358
+ }
359
+ }
@@ -0,0 +1,32 @@
1
+ import { Tile3D } from "../basic/Tile3D";
2
+ import { MineMap } from "./MineMap";
3
+
4
+
5
+ function main(map: MineMap, tile3d: Tile3D) {
6
+ const { viewer } = map
7
+
8
+ viewer.addSource(tile3d.name, {
9
+ type: "3d-tiles",
10
+ url: tile3d.src,
11
+ });
12
+
13
+ viewer.addLayer({
14
+ type: "3d-tiles",
15
+ id: tile3d.name,
16
+ source: tile3d.name,
17
+ });
18
+ }
19
+
20
+
21
+ export function drawTile3D(map: MineMap, tile3d: Tile3D) {
22
+
23
+ const { viewer } = map
24
+ if (viewer.loaded()) {
25
+ main(map, tile3d)
26
+ } else {
27
+ viewer.once('load', () => {
28
+ main(map, tile3d)
29
+ })
30
+ }
31
+
32
+ }
@@ -0,0 +1,75 @@
1
+ import { OpenlayerMap } from "./OpenlayerMap";
2
+
3
+ export function bindEvent(map: OpenlayerMap) {
4
+ const { event, viewer, container } = map;
5
+ let target: any;
6
+ let moving = false
7
+
8
+ viewer.on("pointermove", (e) => {
9
+ event.canvas = e.pixel;
10
+ event.geography = map.canvasTgeography(event.canvas);
11
+ let _target: any
12
+ if (moving) {
13
+ event.trigger('pointer-move')
14
+ return
15
+ }
16
+ const res = viewer.getFeaturesAtPixel(event.canvas)[0];
17
+ _target = res ? res.get("event") : undefined;
18
+ if (_target?.silent) {
19
+ _target = undefined;
20
+ }
21
+ if (_target !== target) {
22
+ target?.onPointerOut?.();
23
+ _target?.onPointerIn?.();
24
+ target = _target;
25
+ }
26
+ event.trigger('pointer-move')
27
+ })
28
+
29
+ container.addEventListener('mousedown', () => {
30
+ if (target) {
31
+ moving = true;
32
+ target.onPointerDown?.();
33
+ }
34
+ event.trigger('pointer-down')
35
+ })
36
+
37
+ container.addEventListener('mouseup', () => {
38
+ if (target) {
39
+ moving = false;
40
+ target.onPointerUp?.();
41
+ }
42
+ event.trigger('pointer-up')
43
+ })
44
+
45
+ container.addEventListener('contextmenu', (e) => {
46
+ e.preventDefault()
47
+ if (target) {
48
+ target.onRClick?.();
49
+ }
50
+ })
51
+
52
+ viewer.on("click", () => {
53
+ if (target) {
54
+ target.onLClick?.();
55
+ }
56
+ event.trigger('left-click')
57
+ });
58
+
59
+ viewer.on("dblclick", () => {
60
+ if (target) {
61
+ target.onDbClick?.();
62
+ }
63
+ map.event.trigger('double-click')
64
+ })
65
+
66
+ let key = 0
67
+
68
+ viewer.on('precompose', () => {
69
+ const _key = map.center.reduce((a, b) => a + b, map.zoom)
70
+ if (key != _key) {
71
+ key = _key
72
+ event.trigger('view-change')
73
+ }
74
+ })
75
+ }
@@ -0,0 +1,149 @@
1
+ import { MapCombine } from "../basic/MapCombine";
2
+ import { PointOption, Point } from "../basic/Point";
3
+ import Map from "ol/Map.js";
4
+ import DragPan from "ol/interaction/DragPan";
5
+ import { Projection } from "../utils/Projection";
6
+ import VectorSource from "ol/source/Vector";
7
+ import VectorLayer from "ol/layer/Vector";
8
+ import { fromLonLat } from "ol/proj";
9
+ import { bindEvent } from "./OpenlayerEvent";
10
+ import { PolylineOption, Polyline } from "../basic/Polyline";
11
+ import DoubleClickZoom from "ol/interaction/DoubleClickZoom";
12
+ import { PolygonOption, Polygon } from "../basic/Polygon";
13
+
14
+ import { drawPoint } from "./OpenlayerPoint";
15
+ import { drawPolyline } from "./OpenlayerPolyline";
16
+ import { drawPolygon } from "./OpenlayerPolygon";
17
+ import { Tile3DOption, Tile3D } from "../basic/Tile3D";
18
+
19
+ export class OpenlayerMap extends MapCombine {
20
+ viewer: Map;
21
+ container: HTMLDivElement;
22
+ dragPan: DragPan;
23
+ vectors: VectorSource
24
+ offset: number[];
25
+ fov = 0.9272952180016121;
26
+ get cursor(): string {
27
+ return (this.container).style.cursor
28
+ }
29
+ set cursor(val: string) {
30
+ (this.container).style.cursor = val
31
+ }
32
+ get moveable(): boolean {
33
+ return this.dragPan.getActive();
34
+ }
35
+ set moveable(val: boolean) {
36
+ this.dragPan.setActive(val);
37
+ }
38
+ get center(): number[] {
39
+ const center = this.viewer.getView().getCenter()!
40
+ return [Projection.xToLon(center[0]), Projection.yToLat(center[1]), 0]
41
+ }
42
+ set center(val: number[]) {
43
+ const { viewer } = this;
44
+ const view = viewer.getView();
45
+ view.setCenter([Projection.lonToX(val[0]), Projection.latToY(val[1])]);
46
+ }
47
+ get zoom(): number {
48
+ return this.viewer.getView().getZoom()
49
+ }
50
+ set zoom(val: number) {
51
+ this.viewer.getView().setZoom(val);
52
+ }
53
+
54
+ constructor(viewer: Map) {
55
+ super()
56
+ this.viewer = viewer
57
+ this.container = viewer.getViewport() as HTMLDivElement
58
+ this.container.appendChild(this.htmllayer)
59
+ const { center } = this;
60
+ this.offset = fromLonLat(center)
61
+
62
+ this.vectors = new VectorSource();
63
+ this.viewer.addLayer(
64
+ new VectorLayer({
65
+ source: this.vectors,
66
+ }),
67
+ );
68
+
69
+ this.dragPan = viewer
70
+ .getInteractions()
71
+ .getArray()
72
+ .find((interaction) => {
73
+ if (interaction instanceof DoubleClickZoom) {
74
+ interaction.setActive(false)
75
+ }
76
+ return interaction instanceof DragPan;
77
+ }) as DragPan;
78
+
79
+ bindEvent(this)
80
+ }
81
+
82
+ createPoint<K>(option?: Partial<PointOption<K>>): Point<K> {
83
+ const e = new Point(this, option)
84
+ drawPoint(this, e)
85
+ return e
86
+ }
87
+
88
+ createPolyline<K>(option?: Partial<PolylineOption<K>>): Polyline<K> {
89
+ const e = new Polyline(this, option)
90
+ drawPolyline(this, e)
91
+ return e
92
+ }
93
+ createPolygon<K>(option?: Partial<PolygonOption<K>>): Polygon<K> {
94
+ const e = new Polygon(this, option)
95
+ drawPolygon(this, e)
96
+ return e
97
+ }
98
+
99
+ // protected _onFrame(): void {
100
+ // const { viewer, camera, offset } = this;
101
+ // const box = viewer.getView().calculateExtent(viewer.getSize());
102
+
103
+ // const height = box[3] - box[1];
104
+
105
+ // camera.position.set((box[2] + box[0]) / 2 - offset[0], (box[3] + box[1]) / 2 - offset[1], height);
106
+
107
+ // // this.meterPerPixel = height / this.container.offsetHeight;
108
+ // }
109
+
110
+ geographyTspace(p: number[]): number[] {
111
+ const { offset } = this;
112
+ return [Projection.lonToX(p[0]) - offset[0], Projection.latToY(p[1]) - offset[1], p[2] ?? 0];
113
+ }
114
+ geographyTcanvas(p: number[]): number[] {
115
+ const pixel = this.viewer.getPixelFromCoordinate(fromLonLat(p));
116
+ if (pixel) {
117
+ return [pixel[0], pixel[1]];
118
+ } else {
119
+ return [0, 0]
120
+ }
121
+
122
+ }
123
+ spaceTgeography(p: number[]): number[] {
124
+ const { offset } = this;
125
+ return [Projection.xToLon(p[0] + offset[0]), Projection.yToLat(p[1] + offset[1]), p[2] ?? 0];
126
+ }
127
+ spaceTcanvas(p: number[]): number[] {
128
+ const { offset } = this;
129
+ const pixel = this.viewer.getPixelFromCoordinate([p[0] + offset[0], p[1] + offset[1]]);
130
+ return [pixel[0], pixel[1]];
131
+ }
132
+ canvasTspace(p: number[]): number[] {
133
+ const coordinates = this.viewer.getCoordinateFromPixel(p);
134
+ return [coordinates[0] - this.offset[0], coordinates[1] - this.offset[1], 0];
135
+ }
136
+
137
+ createTile3D(option?: Partial<Tile3DOption>): Tile3D {
138
+ throw new Error("Method not implemented.");
139
+ }
140
+
141
+ canvasTgeography(p: number[]): number[] {
142
+ const coordinates = this.viewer.getCoordinateFromPixel(p);
143
+ return [Projection.xToLon(coordinates[0]), Projection.yToLat(coordinates[1]), 0];
144
+ }
145
+
146
+ _onDestroy() {
147
+ this.viewer.dispose()
148
+ }
149
+ }