@hzab/map-combine 0.4.2-alpha.4 → 0.4.2-alpha.6
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.
- package/CHANGELOG.md +1 -0
- package/package.json +1 -1
- package/src/cesium/CesiumMap.ts +328 -358
- package/src/cesium/CesiumPolyline.ts +183 -47
- package/src/utils/points-viewer.ts +27 -1
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
package/src/cesium/CesiumMap.ts
CHANGED
|
@@ -1,358 +1,328 @@
|
|
|
1
|
-
import { AMapImageryProvider } from "./cesium-tile-covert";
|
|
2
|
-
|
|
3
|
-
import { MapCombine } from "../basic/MapCombine";
|
|
4
|
-
import { PointOption, Point } from "../basic/Point";
|
|
5
|
-
import { PointAggregationOption, PointAggregation } from "../basic/PointAggregation";
|
|
6
|
-
import { PolygonOption, Polygon } from "../basic/Polygon";
|
|
7
|
-
import { PolylineOption, Polyline } from "../basic/Polyline";
|
|
8
|
-
import { Tile3DOption, Tile3D } from "../basic/Tile3D";
|
|
9
|
-
import { type BasicModelOption, type BasicModel } from "../basic/BasicModel";
|
|
10
|
-
|
|
11
|
-
import { bindEvent } from "./CesiumEvent";
|
|
12
|
-
import { drawPoint } from "./CesiumPoint";
|
|
13
|
-
import { drawPolygon } from "./CesiumPolygon";
|
|
14
|
-
import { drawPolyline } from "./CesiumPolyline";
|
|
15
|
-
import { drawTile3D } from "./CesiumTile3D";
|
|
16
|
-
import { CesiumModel } from "./CesiumModel";
|
|
17
|
-
|
|
18
|
-
const $m = 20037508.34278924;
|
|
19
|
-
/**
|
|
20
|
-
* flyToViewer
|
|
21
|
-
*/
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
this.
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Cesium.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const cartographic = Cesium.Cartographic.fromCartesian(this.viewer.camera.position);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const height = this.container.offsetHeight;
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
this.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
map
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
return
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
*
|
|
272
|
-
* @param
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
maxZoom: MAX_ZOOM,
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
//
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* 移动点位到中心点
|
|
332
|
-
* @param point
|
|
333
|
-
*/
|
|
334
|
-
flyTo(point, opt = {}) {
|
|
335
|
-
const height = this.zoomTdistance(this.zoom);
|
|
336
|
-
// 取消任何正在进行的飞行,防止排队
|
|
337
|
-
if (this.viewer.camera.cancelFlight) {
|
|
338
|
-
this.viewer.camera.cancelFlight();
|
|
339
|
-
}
|
|
340
|
-
// 设置相机视角
|
|
341
|
-
this.viewer.camera.flyTo({
|
|
342
|
-
destination: Cesium.Cartesian3.fromDegrees(point[0], point[1], height),
|
|
343
|
-
...opt,
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
function createColorCanvas(color) {
|
|
349
|
-
var width = 1,
|
|
350
|
-
height = 1;
|
|
351
|
-
var canvas = document.createElement("canvas");
|
|
352
|
-
canvas.width = width;
|
|
353
|
-
canvas.height = height;
|
|
354
|
-
var ctx = canvas.getContext("2d");
|
|
355
|
-
ctx.fillStyle = color;
|
|
356
|
-
ctx.fillRect(0, 0, width, height);
|
|
357
|
-
return canvas.toDataURL();
|
|
358
|
-
}
|
|
1
|
+
import { AMapImageryProvider } from "./cesium-tile-covert";
|
|
2
|
+
|
|
3
|
+
import { MapCombine } from "../basic/MapCombine";
|
|
4
|
+
import { PointOption, Point } from "../basic/Point";
|
|
5
|
+
import { PointAggregationOption, PointAggregation } from "../basic/PointAggregation";
|
|
6
|
+
import { PolygonOption, Polygon } from "../basic/Polygon";
|
|
7
|
+
import { PolylineOption, Polyline } from "../basic/Polyline";
|
|
8
|
+
import { Tile3DOption, Tile3D } from "../basic/Tile3D";
|
|
9
|
+
import { type BasicModelOption, type BasicModel } from "../basic/BasicModel";
|
|
10
|
+
|
|
11
|
+
import { bindEvent } from "./CesiumEvent";
|
|
12
|
+
import { drawPoint } from "./CesiumPoint";
|
|
13
|
+
import { drawPolygon } from "./CesiumPolygon";
|
|
14
|
+
import { drawPolyline } from "./CesiumPolyline";
|
|
15
|
+
import { drawTile3D } from "./CesiumTile3D";
|
|
16
|
+
import { CesiumModel } from "./CesiumModel";
|
|
17
|
+
|
|
18
|
+
const $m = 20037508.34278924;
|
|
19
|
+
/**
|
|
20
|
+
* flyToViewer 最大缩放层级
|
|
21
|
+
*/
|
|
22
|
+
const MAX_ZOOM = 18;
|
|
23
|
+
|
|
24
|
+
export class CesiumMap extends MapCombine {
|
|
25
|
+
viewer: any;
|
|
26
|
+
markers: any;
|
|
27
|
+
option;
|
|
28
|
+
|
|
29
|
+
container: HTMLDivElement;
|
|
30
|
+
|
|
31
|
+
get cursor(): string {
|
|
32
|
+
return this.container.style.cursor;
|
|
33
|
+
}
|
|
34
|
+
set cursor(val: string) {
|
|
35
|
+
this.container.style.cursor = val;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get moveable(): boolean {
|
|
39
|
+
return this.viewer.scene.screenSpaceCameraController.enableRotate;
|
|
40
|
+
}
|
|
41
|
+
set moveable(val: boolean) {
|
|
42
|
+
this.viewer.scene.screenSpaceCameraController.enableRotate = val;
|
|
43
|
+
}
|
|
44
|
+
get center(): number[] {
|
|
45
|
+
const { viewer, container } = this;
|
|
46
|
+
const width = container.offsetWidth;
|
|
47
|
+
const height = container.offsetHeight;
|
|
48
|
+
const position = viewer.scene.camera.pickEllipsoid(
|
|
49
|
+
new Cesium.Cartesian2(width / 2, height / 2),
|
|
50
|
+
viewer.scene.globe.ellipsoid,
|
|
51
|
+
);
|
|
52
|
+
const cartographic = Cesium.Cartographic.fromCartesian(position);
|
|
53
|
+
return [Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)];
|
|
54
|
+
}
|
|
55
|
+
set center(val: number[]) {
|
|
56
|
+
const { viewer, container } = this;
|
|
57
|
+
const width = container.offsetWidth;
|
|
58
|
+
const height = container.offsetHeight;
|
|
59
|
+
const position = viewer.scene.camera.pickEllipsoid(
|
|
60
|
+
new Cesium.Cartesian2(width / 2, height / 2),
|
|
61
|
+
viewer.scene.globe.ellipsoid,
|
|
62
|
+
);
|
|
63
|
+
const target = Cesium.Cartesian3.fromDegrees(...val);
|
|
64
|
+
Cesium.Cartesian3.subtract(target, position, target);
|
|
65
|
+
Cesium.Cartesian3.add(this.viewer.camera.position, target, this.viewer.camera.position);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get zoom(): number {
|
|
69
|
+
const cartographic = Cesium.Cartographic.fromCartesian(this.viewer.camera.position);
|
|
70
|
+
return this.distanceTzoom(cartographic.height);
|
|
71
|
+
}
|
|
72
|
+
set zoom(val: number) {
|
|
73
|
+
const cartographic = Cesium.Cartographic.fromCartesian(this.viewer.camera.position);
|
|
74
|
+
cartographic.height = this.zoomTdistance(val);
|
|
75
|
+
this.viewer.camera.position = Cesium.Cartesian3.fromRadians(
|
|
76
|
+
cartographic.longitude,
|
|
77
|
+
cartographic.latitude,
|
|
78
|
+
cartographic.height,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
fov = 0.9695385667699215;
|
|
83
|
+
distanceTzoom(distance: number) {
|
|
84
|
+
const height = this.container.offsetHeight;
|
|
85
|
+
return Math.log2(($m * height) / (256 * Math.tan(this.fov / 2) * distance));
|
|
86
|
+
}
|
|
87
|
+
zoomTdistance(zoom: number): number {
|
|
88
|
+
const height = this.container.offsetHeight;
|
|
89
|
+
return ($m * height) / (256 * Math.tan(this.fov / 2) * Math.pow(2, zoom));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
constructor(viewer?: any) {
|
|
93
|
+
super();
|
|
94
|
+
this._initParamsEvent(viewer);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
init(opt) {
|
|
98
|
+
this.option = opt;
|
|
99
|
+
const { container, center = [120.2288892, 30.2349677, 0], zoom = 13, url } = opt || {};
|
|
100
|
+
const viewer = new Cesium.Viewer(container, {
|
|
101
|
+
vrButton: false,
|
|
102
|
+
// 检索
|
|
103
|
+
geocoder: false,
|
|
104
|
+
// home
|
|
105
|
+
homeButton: false,
|
|
106
|
+
// 切换3d地图
|
|
107
|
+
sceneModePicker: false,
|
|
108
|
+
// 底图切换按钮
|
|
109
|
+
baseLayerPicker: false,
|
|
110
|
+
// 问号
|
|
111
|
+
navigationHelpButton: false,
|
|
112
|
+
// 动画控制
|
|
113
|
+
animation: false,
|
|
114
|
+
// 版权信息
|
|
115
|
+
creditContainer: document.createElement("div"),
|
|
116
|
+
// 时间轴
|
|
117
|
+
timeline: false,
|
|
118
|
+
// 全屏按钮
|
|
119
|
+
fullscreenButton: false,
|
|
120
|
+
selectionIndicator: false,
|
|
121
|
+
// 打开动画
|
|
122
|
+
shouldAnimate: false,
|
|
123
|
+
infoBox: false,
|
|
124
|
+
// 只进行3d渲染,没有2d,2.5d,提高性能
|
|
125
|
+
scene3DOnly: true,
|
|
126
|
+
// 初始设置一个纯色瓦片,避免报错影响后续瓦片加载
|
|
127
|
+
imageryProvider: new Cesium.SingleTileImageryProvider({
|
|
128
|
+
url: createColorCanvas("#333"),
|
|
129
|
+
rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
|
|
130
|
+
}),
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// viewer.cesiumWidget.creditContainer.remove();
|
|
134
|
+
|
|
135
|
+
// viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
|
|
136
|
+
|
|
137
|
+
this._initParamsEvent(viewer);
|
|
138
|
+
|
|
139
|
+
// 处理瓦片
|
|
140
|
+
this._createLayer();
|
|
141
|
+
|
|
142
|
+
const map = this;
|
|
143
|
+
const d = Cesium.Cartesian3.fromDegrees(...center);
|
|
144
|
+
map.setView([d.x, d.y, d.z, 6.283185307179586, -1.5691285980481942, 0]);
|
|
145
|
+
map.center = center;
|
|
146
|
+
map.zoom = zoom;
|
|
147
|
+
|
|
148
|
+
return map;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private _initParamsEvent(viewer) {
|
|
152
|
+
if (!viewer) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.viewer = viewer;
|
|
156
|
+
|
|
157
|
+
this.container = viewer?.container;
|
|
158
|
+
this.container.appendChild(this.htmllayer);
|
|
159
|
+
this.cursor = "default";
|
|
160
|
+
this.markers = this.viewer.scene.primitives.add(new Cesium.BillboardCollection());
|
|
161
|
+
|
|
162
|
+
bindEvent(this);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private _createLayer() {
|
|
166
|
+
const { url, subdomains, proj, minZoomLevel, maxZoomLevel } = this.option;
|
|
167
|
+
let layer: any;
|
|
168
|
+
let options = {
|
|
169
|
+
...this.option,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
switch (proj) {
|
|
173
|
+
case "GCJ02->WGS84":
|
|
174
|
+
options = {
|
|
175
|
+
...options,
|
|
176
|
+
crs: "WGS84", // 使用84坐标系,默认为:GCJ02
|
|
177
|
+
};
|
|
178
|
+
layer = this.viewer.imageryLayers.addImageryProvider(new AMapImageryProvider(options));
|
|
179
|
+
|
|
180
|
+
break;
|
|
181
|
+
default:
|
|
182
|
+
options = {
|
|
183
|
+
...options,
|
|
184
|
+
tilingScheme: new Cesium.WebMercatorTilingScheme(),
|
|
185
|
+
};
|
|
186
|
+
layer = this.viewer.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider(options));
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
this.viewer.imageryLayers.add(layer);
|
|
191
|
+
|
|
192
|
+
return layer;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
getView() {
|
|
196
|
+
const { camera } = this.viewer;
|
|
197
|
+
return [camera.position.x, camera.position.y, camera.position.z, camera.heading, camera.pitch, camera.roll];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
setView(e: number[]) {
|
|
201
|
+
const { camera } = this.viewer;
|
|
202
|
+
camera.setView({
|
|
203
|
+
destination: new Cesium.Cartesian3(e[0], e[1], e[2]),
|
|
204
|
+
orientation: new Cesium.HeadingPitchRoll(e[3], e[4], e[5]),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
createPoint<K>(option?: Partial<PointOption<K>>): Point<K> {
|
|
209
|
+
const e = new Point(this, option);
|
|
210
|
+
drawPoint(this, e);
|
|
211
|
+
return e;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
createPointAggregation(option?: PointAggregationOption): PointAggregation {
|
|
215
|
+
const e = new PointAggregation(this, option);
|
|
216
|
+
return e;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
createPolyline<K>(option?: Partial<PolylineOption<K>>): Polyline<K> {
|
|
220
|
+
const e = new Polyline(this, option);
|
|
221
|
+
drawPolyline(this, e);
|
|
222
|
+
return e;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
createPolygon<K>(option?: Partial<PolygonOption<K>>): Polygon<K> {
|
|
226
|
+
const e = new Polygon(this, option);
|
|
227
|
+
drawPolygon(this, e);
|
|
228
|
+
return e;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
createTile3D(option?: Partial<Tile3DOption>): Tile3D {
|
|
232
|
+
const e = new Tile3D(this, option);
|
|
233
|
+
drawTile3D(this, e);
|
|
234
|
+
return e;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
createModel(option?: Partial<BasicModelOption> | undefined): BasicModel {
|
|
238
|
+
return new CesiumModel(this, option);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
canvasTgeography(p: number[]): number[] {
|
|
242
|
+
const { viewer } = this;
|
|
243
|
+
const cartesian2 = new Cesium.Cartesian2(...p);
|
|
244
|
+
const ray = viewer.camera.getPickRay(cartesian2);
|
|
245
|
+
const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
|
|
246
|
+
|
|
247
|
+
if (cartesian) {
|
|
248
|
+
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
|
|
249
|
+
return [
|
|
250
|
+
Cesium.Math.toDegrees(cartographic.longitude),
|
|
251
|
+
Cesium.Math.toDegrees(cartographic.latitude),
|
|
252
|
+
cartographic.height,
|
|
253
|
+
];
|
|
254
|
+
} else {
|
|
255
|
+
return [0, 0, 0];
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
geographyTcanvas(p: number[]): number[] {
|
|
259
|
+
const res = Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, Cesium.Cartesian3.fromDegrees(...p));
|
|
260
|
+
if (!res) {
|
|
261
|
+
return [-1, -1];
|
|
262
|
+
}
|
|
263
|
+
return [res.x, res.y];
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* 所有点位移动至视口,调整位置及层级
|
|
268
|
+
* @param points
|
|
269
|
+
* @param opt
|
|
270
|
+
* @param {Array<number> = [0,0,0,0]} opt.avoid 距离边框的内边距,顺序:上、下、左、右
|
|
271
|
+
* @param {Array<number> = [0,0,0,0]} opt.minRadius flyToViewer 最小范围(米)
|
|
272
|
+
* @param {Array<number> = [0,0,0,0]} opt.maxZoom flyToViewer 最大缩放层级
|
|
273
|
+
*/
|
|
274
|
+
flyToViewer(
|
|
275
|
+
points,
|
|
276
|
+
opt = {
|
|
277
|
+
avoid: [0, 0, 0, 0],
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* flyToViewer 最大缩放层级
|
|
281
|
+
*/
|
|
282
|
+
maxZoom: MAX_ZOOM,
|
|
283
|
+
},
|
|
284
|
+
) {
|
|
285
|
+
if (points?.length === 0) {
|
|
286
|
+
return this.flyTo(points[0], opt);
|
|
287
|
+
}
|
|
288
|
+
// 创建矩形
|
|
289
|
+
const destination = Cesium.Rectangle.fromDegrees(
|
|
290
|
+
...this.getBounds(points, { canvas: this.viewer.scene.canvas, maxZoom: MAX_ZOOM, ...opt }),
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
// 设置相机视角
|
|
294
|
+
this.viewer.camera.flyTo({
|
|
295
|
+
destination,
|
|
296
|
+
...opt,
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* 移动点位到中心点
|
|
302
|
+
* @param point
|
|
303
|
+
*/
|
|
304
|
+
flyTo(point, opt = {}) {
|
|
305
|
+
const height = this.zoomTdistance(this.zoom);
|
|
306
|
+
// 取消任何正在进行的飞行,防止排队
|
|
307
|
+
if (this.viewer.camera.cancelFlight) {
|
|
308
|
+
this.viewer.camera.cancelFlight();
|
|
309
|
+
}
|
|
310
|
+
// 设置相机视角
|
|
311
|
+
this.viewer.camera.flyTo({
|
|
312
|
+
destination: Cesium.Cartesian3.fromDegrees(point[0], point[1], height),
|
|
313
|
+
...opt,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function createColorCanvas(color) {
|
|
319
|
+
var width = 1,
|
|
320
|
+
height = 1;
|
|
321
|
+
var canvas = document.createElement("canvas");
|
|
322
|
+
canvas.width = width;
|
|
323
|
+
canvas.height = height;
|
|
324
|
+
var ctx = canvas.getContext("2d");
|
|
325
|
+
ctx.fillStyle = color;
|
|
326
|
+
ctx.fillRect(0, 0, width, height);
|
|
327
|
+
return canvas.toDataURL();
|
|
328
|
+
}
|
|
@@ -14,6 +14,7 @@ czm_material czm_getMaterial(czm_materialInput materialInput){
|
|
|
14
14
|
material.alpha = colorImage.a * color.a;
|
|
15
15
|
return material;
|
|
16
16
|
}`;
|
|
17
|
+
|
|
17
18
|
function createLineMaterial(e: Polyline<unknown>) {
|
|
18
19
|
if (e.icon || e.flow) {
|
|
19
20
|
const material = new Cesium.Material({
|
|
@@ -99,25 +100,180 @@ export function drawPolyline(map: CesiumMap, polyline: Polyline<unknown>) {
|
|
|
99
100
|
},
|
|
100
101
|
};
|
|
101
102
|
|
|
102
|
-
let primitive: any;
|
|
103
103
|
let cache: any[];
|
|
104
104
|
let activeNode: ChainNode<any, any>;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
105
|
+
|
|
106
|
+
let geometryInstance = null;
|
|
107
|
+
let primitive = null;
|
|
108
|
+
let currentPositions = [];
|
|
109
|
+
let isFirstRender = true;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 更新或创建线条几何体
|
|
113
|
+
* @param newPositions - 新的顶点数组
|
|
114
|
+
* @param forceRebuild 强制重建
|
|
115
|
+
*/
|
|
116
|
+
function updatePrimitiveGeometry(newPositions, forceRebuild: boolean = false) {
|
|
117
|
+
// 验证数据有效性
|
|
118
|
+
if (!newPositions || newPositions.length < 2) {
|
|
119
|
+
if (primitive) {
|
|
120
|
+
viewer.scene.primitives.remove(primitive);
|
|
121
|
+
primitive = null;
|
|
122
|
+
geometryInstance = null;
|
|
123
|
+
}
|
|
124
|
+
currentPositions = [];
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 强制重建,跳过检查
|
|
129
|
+
if (!forceRebuild && !isFirstRender) {
|
|
130
|
+
if (currentPositions.length === newPositions.length) {
|
|
131
|
+
let same = true;
|
|
132
|
+
for (let i = 0; i < newPositions.length; i++) {
|
|
133
|
+
const p1 = currentPositions[i];
|
|
134
|
+
const p2 = newPositions[i];
|
|
135
|
+
if (
|
|
136
|
+
!p1 ||
|
|
137
|
+
!p2 ||
|
|
138
|
+
Math.abs(p1.x - p2.x) > 1e-10 ||
|
|
139
|
+
Math.abs(p1.y - p2.y) > 1e-10 ||
|
|
140
|
+
Math.abs(p1.z - p2.z) > 1e-10
|
|
141
|
+
) {
|
|
142
|
+
same = false;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (same) return;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// 创建新的几何体数据
|
|
151
|
+
let newGeometry: any = null;
|
|
152
|
+
try {
|
|
153
|
+
newGeometry = Cesium.PolylineGeometry.createGeometry(
|
|
154
|
+
new Cesium.PolylineGeometry({
|
|
155
|
+
positions: newPositions,
|
|
113
156
|
width: polyline.lineWidth,
|
|
114
157
|
vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
|
|
115
158
|
}),
|
|
159
|
+
);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error("创建几何体失败:", error);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (!newGeometry) return;
|
|
166
|
+
|
|
167
|
+
// 复用或创建 Primitive
|
|
168
|
+
if (geometryInstance && primitive && !forceRebuild) {
|
|
169
|
+
// 复用几何体实例
|
|
170
|
+
try {
|
|
171
|
+
geometryInstance.geometry = newGeometry;
|
|
172
|
+
if (primitive._state !== undefined) {
|
|
173
|
+
primitive._state = Cesium.PrimitiveState.NEEDS_REBUILD;
|
|
174
|
+
}
|
|
175
|
+
if (primitive._boundingVolume) {
|
|
176
|
+
primitive._boundingVolume = undefined;
|
|
177
|
+
}
|
|
178
|
+
if (primitive._dirty !== undefined) {
|
|
179
|
+
primitive._dirty = true;
|
|
180
|
+
}
|
|
181
|
+
} catch (error) {
|
|
182
|
+
console.warn("复用 Primitive 失败,降级到重建:", error);
|
|
183
|
+
// 降级:重新创建
|
|
184
|
+
if (primitive) {
|
|
185
|
+
viewer.scene.primitives.remove(primitive);
|
|
186
|
+
primitive = null;
|
|
187
|
+
}
|
|
188
|
+
geometryInstance = new Cesium.GeometryInstance({
|
|
189
|
+
geometry: newGeometry,
|
|
190
|
+
id: _event,
|
|
191
|
+
});
|
|
192
|
+
primitive = new Cesium.Primitive({
|
|
193
|
+
show: polyline.show !== false,
|
|
194
|
+
asynchronous: false,
|
|
195
|
+
geometryInstances: geometryInstance,
|
|
196
|
+
appearance: appearance,
|
|
197
|
+
compressVertices: true,
|
|
198
|
+
releaseGeometryInstances: false,
|
|
199
|
+
});
|
|
200
|
+
viewer.scene.primitives.add(primitive);
|
|
201
|
+
}
|
|
202
|
+
// 复用 Primitive,只更新几何体数据(性能最优)
|
|
203
|
+
try {
|
|
204
|
+
// 直接替换几何体数据
|
|
205
|
+
geometryInstance.geometry = newGeometry;
|
|
206
|
+
|
|
207
|
+
// 关键:标记 Primitive 需要重建
|
|
208
|
+
// 在 Cesium 1.90.1 中,这些内部状态需要手动触发
|
|
209
|
+
if (primitive._state !== undefined) {
|
|
210
|
+
primitive._state = Cesium.PrimitiveState.NEEDS_REBUILD;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 清除缓存的包围盒,强制重新计算
|
|
214
|
+
if (primitive._boundingVolume) {
|
|
215
|
+
primitive._boundingVolume = undefined;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 标记为脏,触发重绘
|
|
219
|
+
if (primitive._dirty !== undefined) {
|
|
220
|
+
primitive._dirty = true;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// 对于某些版本,可能需要重新设置 geometryInstances
|
|
224
|
+
// primitive.geometryInstances = geometryInstance;
|
|
225
|
+
} catch (error) {
|
|
226
|
+
// 如果复用失败,降级到重建方案
|
|
227
|
+
console.warn("复用 Primitive 失败,降级到重建:", error);
|
|
228
|
+
forceRebuild = true;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 强制重建或者首次创建,重新创建 Primitive
|
|
233
|
+
if (forceRebuild || !primitive || !geometryInstance) {
|
|
234
|
+
if (primitive) {
|
|
235
|
+
viewer.scene.primitives.remove(primitive);
|
|
236
|
+
primitive = null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
geometryInstance = new Cesium.GeometryInstance({
|
|
240
|
+
geometry: newGeometry,
|
|
116
241
|
id: _event,
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
primitive = new Cesium.Primitive({
|
|
245
|
+
show: polyline.show !== false,
|
|
246
|
+
asynchronous: false,
|
|
247
|
+
geometryInstances: geometryInstance,
|
|
248
|
+
appearance: appearance,
|
|
249
|
+
compressVertices: true,
|
|
250
|
+
releaseGeometryInstances: false,
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
viewer.scene.primitives.add(primitive);
|
|
254
|
+
isFirstRender = false;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
currentPositions = newPositions.slice();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function cleanupPrimitive() {
|
|
261
|
+
if (primitive) {
|
|
262
|
+
viewer.scene.primitives.remove(primitive);
|
|
263
|
+
primitive = null;
|
|
264
|
+
}
|
|
265
|
+
if (geometryInstance) {
|
|
266
|
+
geometryInstance = null;
|
|
267
|
+
}
|
|
268
|
+
currentPositions = [];
|
|
269
|
+
isFirstRender = true;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// 初始加载
|
|
273
|
+
if (polyline.coordinates) {
|
|
274
|
+
status = 2;
|
|
275
|
+
cache = polyline.coordinates.map(geographyTcartesian3);
|
|
276
|
+
updatePrimitiveGeometry(cache, true); // 强制重建
|
|
121
277
|
}
|
|
122
278
|
|
|
123
279
|
const editor = new PolylineEditor<any, any>();
|
|
@@ -180,8 +336,10 @@ export function drawPolyline(map: CesiumMap, polyline: Polyline<unknown>) {
|
|
|
180
336
|
markers.remove(n.shape);
|
|
181
337
|
});
|
|
182
338
|
editor.on("empty", () => {
|
|
183
|
-
|
|
184
|
-
|
|
339
|
+
if (primitive) {
|
|
340
|
+
viewer.scene.primitives.remove(primitive);
|
|
341
|
+
primitive = null;
|
|
342
|
+
}
|
|
185
343
|
status = 0;
|
|
186
344
|
});
|
|
187
345
|
|
|
@@ -218,7 +376,6 @@ export function drawPolyline(map: CesiumMap, polyline: Polyline<unknown>) {
|
|
|
218
376
|
break;
|
|
219
377
|
case "dash":
|
|
220
378
|
keys.add("Material");
|
|
221
|
-
|
|
222
379
|
break;
|
|
223
380
|
default:
|
|
224
381
|
throw new Error(`${key} 还不支持修改`);
|
|
@@ -229,14 +386,13 @@ export function drawPolyline(map: CesiumMap, polyline: Polyline<unknown>) {
|
|
|
229
386
|
case "Primitive":
|
|
230
387
|
if (polyline.coordinates) {
|
|
231
388
|
cache = polyline.coordinates.map((e) => geographyTcartesian3(e));
|
|
389
|
+
updatePrimitiveGeometry(cache, true); // 强制重建
|
|
232
390
|
} else {
|
|
233
391
|
cache = [];
|
|
234
392
|
markers.removeAll();
|
|
235
393
|
status = 0;
|
|
236
394
|
}
|
|
237
|
-
|
|
238
395
|
initPrimitive();
|
|
239
|
-
|
|
240
396
|
break;
|
|
241
397
|
case "Material":
|
|
242
398
|
material = createLineMaterial(polyline);
|
|
@@ -254,6 +410,7 @@ export function drawPolyline(map: CesiumMap, polyline: Polyline<unknown>) {
|
|
|
254
410
|
break;
|
|
255
411
|
}
|
|
256
412
|
};
|
|
413
|
+
|
|
257
414
|
let temp: any;
|
|
258
415
|
const onMouseMove = () => {
|
|
259
416
|
const e = event.geography;
|
|
@@ -262,13 +419,13 @@ export function drawPolyline(map: CesiumMap, polyline: Polyline<unknown>) {
|
|
|
262
419
|
case 1:
|
|
263
420
|
cache.pop();
|
|
264
421
|
cache.push(geographyTcartesian3(e));
|
|
265
|
-
|
|
422
|
+
updatePrimitiveGeometry(cache); // 普通更新
|
|
266
423
|
break;
|
|
267
424
|
case 4:
|
|
268
425
|
temp = geographyTcartesian3(e);
|
|
269
426
|
activeNode.update([temp.x, temp.y, temp.z]);
|
|
270
427
|
cache = editor.getCoordinates().map((e) => new Cesium.Cartesian3(...e));
|
|
271
|
-
|
|
428
|
+
updatePrimitiveGeometry(cache, true); // 强制重建
|
|
272
429
|
break;
|
|
273
430
|
}
|
|
274
431
|
};
|
|
@@ -284,38 +441,16 @@ export function drawPolyline(map: CesiumMap, polyline: Polyline<unknown>) {
|
|
|
284
441
|
break;
|
|
285
442
|
case 1:
|
|
286
443
|
cache.push(cache[cache.length - 1]);
|
|
287
|
-
// geometry.setCoordinates(cache)
|
|
288
444
|
initPrimitive();
|
|
289
445
|
break;
|
|
290
446
|
}
|
|
291
447
|
};
|
|
292
448
|
|
|
293
449
|
const initPrimitive = () => {
|
|
294
|
-
primitive && viewer.scene.primitives.remove(primitive);
|
|
295
450
|
if (cache.length > 1) {
|
|
296
|
-
|
|
297
|
-
new Cesium.PolylineGeometry({
|
|
298
|
-
positions: cache,
|
|
299
|
-
width: polyline.lineWidth,
|
|
300
|
-
vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
|
|
301
|
-
}),
|
|
302
|
-
);
|
|
303
|
-
if (geometry) {
|
|
304
|
-
primitive = new Cesium.Primitive({
|
|
305
|
-
show: polyline.show,
|
|
306
|
-
asynchronous: false,
|
|
307
|
-
geometryInstances: new Cesium.GeometryInstance({
|
|
308
|
-
geometry,
|
|
309
|
-
id: _event,
|
|
310
|
-
}),
|
|
311
|
-
appearance,
|
|
312
|
-
});
|
|
313
|
-
viewer.scene.primitives.add(primitive);
|
|
314
|
-
} else {
|
|
315
|
-
primitive = undefined;
|
|
316
|
-
}
|
|
451
|
+
updatePrimitiveGeometry(cache, true); // 强制重建
|
|
317
452
|
} else {
|
|
318
|
-
|
|
453
|
+
cleanupPrimitive();
|
|
319
454
|
}
|
|
320
455
|
};
|
|
321
456
|
|
|
@@ -326,7 +461,6 @@ export function drawPolyline(map: CesiumMap, polyline: Polyline<unknown>) {
|
|
|
326
461
|
skip++;
|
|
327
462
|
cache.pop();
|
|
328
463
|
cache.pop();
|
|
329
|
-
// geometry.setCoordinates(cache)
|
|
330
464
|
polyline.coordinates = cache.map((e) => cartesian3Tgeography(e));
|
|
331
465
|
polyline.event.trigger("data-loaded");
|
|
332
466
|
polyline.event.trigger("pointer-in");
|
|
@@ -348,8 +482,10 @@ export function drawPolyline(map: CesiumMap, polyline: Polyline<unknown>) {
|
|
|
348
482
|
};
|
|
349
483
|
|
|
350
484
|
const onDestroy = () => {
|
|
351
|
-
|
|
352
|
-
|
|
485
|
+
cleanupPrimitive();
|
|
486
|
+
if (markers) {
|
|
487
|
+
viewer.scene.primitives.remove(markers);
|
|
488
|
+
}
|
|
353
489
|
event.off("pointer-move", onMouseMove);
|
|
354
490
|
event.off("left-click", onClick);
|
|
355
491
|
event.off("double-click", onDbClick);
|
|
@@ -43,5 +43,31 @@ export const getBounds = function (points, opt) {
|
|
|
43
43
|
minLat -= avoid[1] * latPixelRatio;
|
|
44
44
|
maxLat += avoid[0] * latPixelRatio;
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
// 根据 maxZoom 计算最小矩形范围
|
|
47
|
+
const minRange = getMinRangeFromZoom(opt.maxZoom);
|
|
48
|
+
const centerLon = (minLon + maxLon) / 2;
|
|
49
|
+
const centerLat = (minLat + maxLat) / 2;
|
|
50
|
+
|
|
51
|
+
// 确保矩形范围不小于最小值 解决点位距离过近导致异常缩放问题
|
|
52
|
+
let finalWest = Math.min(minLon, centerLon - minRange / 2);
|
|
53
|
+
let finalEast = Math.max(maxLon, centerLon + minRange / 2);
|
|
54
|
+
let finalSouth = Math.min(minLat, centerLat - minRange / 2);
|
|
55
|
+
let finalNorth = Math.max(maxLat, centerLat + minRange / 2);
|
|
56
|
+
|
|
57
|
+
return [finalWest, finalSouth, finalEast, finalNorth];
|
|
47
58
|
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 根据 maxZoom 计算出一个“最小”的经纬度跨度
|
|
62
|
+
* @param zoom
|
|
63
|
+
* @returns
|
|
64
|
+
*/
|
|
65
|
+
export function getMinRangeFromZoom(zoom) {
|
|
66
|
+
// 每个瓦片覆盖的经度范围
|
|
67
|
+
const lonPerTile = 360 / Math.pow(2, zoom);
|
|
68
|
+
// 每个瓦片覆盖的纬度范围(近似)
|
|
69
|
+
const latPerTile = 180 / Math.pow(2, zoom);
|
|
70
|
+
|
|
71
|
+
// 返回一个足够小的范围,比如一个瓦片范围的一半
|
|
72
|
+
return Math.max(lonPerTile, latPerTile) / 2;
|
|
73
|
+
}
|