1.前言
其实我的需求很简单,就是加载一个geojson图层,然后实现能选中,但是我遇到了很多问题。下面是我添加 geojson 图层的代码,本身其实没有什么问题的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| async addGeoJson(geojson, name, options?) { if (geojson.crs.properties.name == undefined) { geojson.crs.properties.name = 'EPSG:4490'; } const dataSource = new GeoJsonDataSource(name || new Date().getTime()); const data = await dataSource.load(geojson, { clampToGround: true, fill: options && options.color ? Color.fromCssColorString(options.color).withAlpha(0.4) : Color.fromCssColorString('rgba(239,108,0,0.4)'), }); if (options && options.zIndex) { data.entities.values.forEach((entity: any) => { entity.zIndex = options.zIndex || 10000; entity.layerName = name; if (entity.position) { entity.billboard = { scale: 1.0, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, image: Cesium.buildModuleUrl(marker2Img), }; entity.point = undefined; } }); } this.dataSourceManager.add(data); return data; }
|
2.ellipse无法使用zIndex
第一个问题就是我加了一个圆,我把geojson图层加载进了这个大圆里面,导致我始终无法选中geojson添加的图层。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| this.airPortEntity['circle'] = this.viewer.entities.add({ position: position, ellipse: { semiMinorAxis: 6000, semiMajorAxis: 6000, height: 0, zIndex: -1, material: Cesium.Color.WHITE.withAlpha(0.2), }, });
this.airPortEntity['outlineCircle'] = this.viewer.entities.add({ position: position, ellipse: { semiMinorAxis: 6000.0, semiMajorAxis: 6000.0, fill: false, outline: true, outlineColor: Cesium.Color.BLUE, outlineWidth: 10, material: new Cesium.PolylineDashMaterialProperty({ color: Cesium.Color.BLUE, dashLength: 16.0, }), zIndex: -1, }, });
|
【解决方案】
解决方案,就是使用多变形,代替绘制的 ellipse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| this.airPortEntity['circle'] = this.viewer.entities.add({ name: '实心圆', position: position, polygon: { hierarchy: new Cesium.PolygonHierarchy( this.createCirclePositions(position, 6000) ), material: Cesium.Color.WHITE.withAlpha(0.2), zIndex: -1, }, });
this.airPortEntity['outlineCircle'] = this.viewer.entities.add({ name: '虚线圆', position: position, polygon: { fill: false, outline: true, outlineColor: Cesium.Color.BLUE, outlineWidth: 2.0, hierarchy: new Cesium.PolygonHierarchy(this.createCirclePositions(position, 6000)), zIndex: -1, }, });
createCirclePositions(centerPosition, radius = 6000, steps = 64) {
if (!centerPosition || typeof centerPosition.x !== 'number' || typeof centerPosition.y !== 'number') { console.error('createCirclePositions: center 不合法', centerPosition); return []; }
const positions = []; for (let i = 0; i <= steps; i++) { const angle = (Math.PI * 2 * i) / steps; const x = centerPosition.x + Math.cos(angle) * radius; const y = centerPosition.y + Math.sin(angle) * radius; positions.push(new Cesium.Cartesian3(x, y, centerPosition.z || 0)); } return positions; }
|
3.绘制的图形无法选中
我加载了 geojson 面之后,使用 @cesium-extends/drawer 工具,在面上用鼠标画了一个面,想着能选中这个面。但是出现的问题是,我能选中面的顶点,但是无法选中面,点击面之后,就直接选中了位于下方的geojson图层了。我用达模型查了很多遍,对比了很多,花了很多时间,就是无法知道原因,一会说层级顺序,一会说Entity,就是没有一个方法可以的。还尝试过自定义选中策略,这也是大模型给的建议,一点用都没有。
即便是我画一个更大的面,包裹了这个geojson,但是在geojson内部点击的时候,还是选中的geojson,在geojson外部点击的时候,就选中了绘制的图形。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| this.viewer.screenSpaceEventHandler.setInputAction((click) => { const picked = this.viewer.scene.pick(click.position); if (picked && Cesium.defined(picked.id)) { console.log(picked); const entity = picked.id;
if (entity.layerName === 'draw') { this.viewer.selectedEntity = entity; } else { this.viewer.selectedEntity = entity; } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
但是我知道的是,加载的geojson和绘制的图形,在点击被选中的时候,都是输出的 GroundPrimitive 这个类型,选中点的时候,输出的类型是 Billboard。
当我打印 viewer.dataSource, 发现这个绘制的图层的 dataSource,竟然在 geojson 图层之前添加了,估计是这里的问题。
【解决方案】
最后解决方案,就是利用 raiseToTop 方法,将绘制的图层,至于加载的 geojson图层之上。
1 2 3
| this.viewer.dataSources.raiseToTop(this.entityCollectionPoints); this.viewer.dataSources.raiseToTop(this.entityCollection);
|