import * as Cesium from 'cesium'; import data2 from '@/assets/images/home/homeRight/data2.png'; import data1 from '@/assets/images/home/homeRight/data1.png'; import jiangxishi from '@/assets/geojson/jiangxishi.json'; import jiangxi from '@/assets/geojson/jiangxi.json'; import zg from '@/assets/geojson/zg.json'; import MapPopUpBox from '@/views/Home/MapPopUpBox.vue'; import { render } from 'vue'; /** * 机巢聚合功能 */ export const useAggregation = () => { const scalingJudgment = [ { name: '县', value: [0, 48651], gJson: null }, { name: '市', value: [48651, 314863], gJson: jiangxishi }, { name: '省', value: [314863, 1169651], gJson: jiangxi }, { name: '国', value: [1169651, 37962800], gJson: zg }, ]; let viewer = null; const active = ref(''); let handler = null; let labelDiv = null; let positionC3 = null; const init = () => { determineScaling(); viewer.camera.moveEnd.addEventListener(() => { determineScaling(); }); }; // 确定缩放比例 const determineScaling = () => { let height = viewer.camera.positionCartographic.height; // 根据高度展示对应的 gJson for (let item of scalingJudgment) { if (height > item.value[0] && height <= item.value[1]) { if (active.value !== item.name) { removeEntities(); removeLabel(); active.value = item.name; item.gJson ? aggregation(item) : splashed(); } break; } } }; //散点机巢 function splashed() { for (let i = 0; i < 50; i++) { viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees( 115.89 + Math.random() * 0.2, 28.68 + Math.random() * 0.2 ), label: { // 随机整数 text: Math.floor(Math.random() * 100) + '号机巢', font: '14pt monospace', fillColor: Cesium.Color.WHITE, outlineColor: Cesium.Color.BLACK, outlineWidth: 2, style: Cesium.LabelStyle.FILL_AND_OUTLINE, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(0, -9), }, billboard: { image: new Cesium.ConstantProperty(data1), width: 24, height: 24, }, }); } } // 聚合机巢 const aggregation = item => { const featuresList = item.gJson.features.map(item => ({ name: item.properties.name, position: item.properties.center, })); // 遍历特征并添加实体 featuresList.forEach(feature => { if (!feature.position) return; const position = Cesium.Cartesian3.fromDegrees(feature.position[0], feature.position[1]); viewer.entities.add({ id: feature.id, position: position, label: { // 随机整数 text: feature.name + Math.floor(Math.random() * 100), font: '14pt monospace', fillColor: Cesium.Color.WHITE, outlineColor: Cesium.Color.BLACK, outlineWidth: 2, style: Cesium.LabelStyle.FILL_AND_OUTLINE, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(0, -9), }, billboard: { image: new Cesium.ConstantProperty(data2), width: 24, height: 24, }, properties: { id: feature.id, customData: { name: feature.name, }, }, }); }); // 加载新的 GeoJSON 数据 Cesium.GeoJsonDataSource.load(item.gJson).then(dataSource => { viewer.dataSources.add(dataSource); item.dataSource = dataSource; // 保存数据源以便后续删除 // 获取数据源中的实体 const entities = dataSource.entities.values; entities.forEach(entity => { entity.polygon.material = new Cesium.ColorMaterialProperty( Cesium.Color.YELLOW.withAlpha(0) // 透明填充 ); entity.polygon.outline = new Cesium.ConstantProperty(true); // 显示边框 entity.polygon.outlineColor = new Cesium.ConstantProperty(Cesium.Color.YELLOW); // 黑色边框 }); }); }; const getLabelDom = () => { const vNode = h(MapPopUpBox, { data: '参数',removeLabel }); const tooltipContainer = document.createElement('div'); tooltipContainer.style.position = 'absolute'; tooltipContainer.style.transform = 'translateY(-50%)'; tooltipContainer.style.pointerEvents = 'none'; document.querySelector('.page-index').append(tooltipContainer); render(vNode, tooltipContainer); return tooltipContainer; }; const labelBox = () => { if (!labelDiv) { labelDiv = getLabelDom(); } const screenPosition = viewer.scene.cartesianToCanvasCoordinates(positionC3); if (screenPosition) { labelDiv.style.left = `${screenPosition.x}px`; labelDiv.style.top = `${screenPosition.y}px`; } }; const clickFun = click => { const pickedObject = viewer.scene.pick(click.position); if (Cesium.defined(pickedObject) && pickedObject.id) { const entity = pickedObject.id; positionC3 = entity.position._value; viewer.scene.postRender.addEventListener(labelBox); } }; const removeEntities = () => { viewer.dataSources.removeAll(true); viewer.entities.removeAll(); }; const removeLabel = () => { viewer.scene.postRender.removeEventListener(labelBox); if (labelDiv && labelDiv.parentNode) { labelDiv.parentNode.removeChild(labelDiv); labelDiv = null; } }; onUnmounted(() => { removeEntities(); removeLabel(); handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); }); onMounted(() => { nextTick(() => { viewer = window.$viewer; handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction(clickFun, Cesium.ScreenSpaceEventType.LEFT_CLICK); init(); }); }); };