import * as Cesium from 'cesium' import AmapMercatorTilingScheme from './cesium/AmapMercatorTilingScheme/index' import store from '@/store' import { Terrain } from 'cesium' import { addBlueFilter } from '@/utils/cesium/common' // 定义全局的viewer变量防止重复生成 let viewer = null let globalBaseMapLayers = [] window.globalCesium = Cesium window.$viewer = null let customEntityDataSources = {} let customMapLayer = {} let handlerEvents = { handler: null, } let TDT_Token = import.meta.env.VITE_APP_TDT_TOKEN export default function cesiumOperation () { // 天地图地图 const TDT_IMG_C = 'https://{s}.tianditu.gov.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0' + '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' + '&style=default&format=tiles&tk=' + TDT_Token // 天地图注记 const TDT_ZJ = 'https://{s}.tianditu.gov.cn/cia_c/wmts?service=wmts&request=GetTile&version=1.0.0' + '&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' + '&style=default&format=tiles&tk=' + TDT_Token // 标准地图注记 const TID_STAND = 'https://{s}.tianditu.gov.cn/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0' + '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' + '&style=default&format=tiles&tk=' + TDT_Token // 天地图图层变量 const imageryProvider_tdt = new Cesium.WebMapTileServiceImageryProvider({ url: TDT_IMG_C, layer: 'tdtImg_c', style: 'default', format: 'tiles', tileMatrixSetID: 'c', subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'], tilingScheme: new Cesium.GeographicTilingScheme(), tileMatrixLabels: [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', ], maximumLevel: 17, }) // 标准地图图层变量 const imageryProvider_stand = new Cesium.UrlTemplateImageryProvider({ url: 'https://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c', subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], // format: 'image/jpeg', // show: true, maximumLevel: 18, credit: 'stand_tc', }) // 标准地图图层注解 const imageryProvider_standZh = new Cesium.UrlTemplateImageryProvider({ url: 'https://t{s}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c', subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], maximumLevel: 18, credit: 'stand_zj', }) // 天地图中文注记加载 const annotation = new Cesium.WebMapTileServiceImageryProvider({ url: TDT_ZJ, layer: 'tdtZwImg_c', style: 'default', format: 'tiles', tileMatrixSetID: 'c', subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'], tilingScheme: new Cesium.GeographicTilingScheme(), tileMatrixLabels: [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', ], maximumLevel: 50, }) // 高德地图图层变量 //高德矢量地图数据图层,自带注记 const imageryProvider_ammapSL = new Cesium.UrlTemplateImageryProvider({ url: 'https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', layer: 'tdtVecBasicLayer', style: 'default', format: 'image/png', tileMatrixSetID: 'GoogleMapsCompatible', subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], maximumLevel: 18, tilingScheme: new AmapMercatorTilingScheme(), credit: 'amap_SL', }) //高德影像地图数据图层,自带注记 const imageryProvider_ammap = new Cesium.UrlTemplateImageryProvider({ url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', layer: 'tdtVecBasicLayer', style: 'default', format: 'image/png', tileMatrixSetID: 'GoogleMapsCompatible', subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], maximumLevel: 18, tilingScheme: new AmapMercatorTilingScheme(), credit: 'amap_stand', }) // 高德影像地图数据图层,注记 const imageryProvider_ammapBz = new Cesium.UrlTemplateImageryProvider({ url: 'https://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8', tilingScheme: new AmapMercatorTilingScheme(), minimumLevel: 3, }) const _init = async id => { Cesium.Camera.DEFAULT_VIEW_FACTOR = -0.45 // 西南东北,默认显示中国 Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(66, 4, 135, 53.55) viewer = new Cesium.Viewer(id, { terrain: Terrain.fromWorldTerrain(), infoBox: false, // 禁用沙箱,解决控制台报错 animation: false, // 左下角的动画仪表盘 baseLayerPicker: false, // 右上角的图层选择按钮 geocoder: false, // 搜索框 homeButton: false, // home按钮 sceneModePicker: false, // 模式切换按钮 timeline: false, // 底部的时间轴 navigationHelpButton: false, // 右上角的帮助按钮, selectionIndicator: false, // 是否显示选择指示器 baseLayer: false, fullscreenButton: false, }) // viewer.scene.globe.depthTestAgainstTerrain = true; viewer.imageryLayers.removeAll() globalBaseMapLayers = [] viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction( Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK ) // 禁用双击 viewer.scene.screenSpaceCameraController.minimumZoomDistance = 100 viewer.scene.screenSpaceCameraController.maximumZoomDistance = 4500000 // viewer.scene.camera.setView({ // destination: Cesium.Cartesian3.fromDegrees(115.856725497,28.624514734, 8000) // }); // // 添加地形数据 // viewer.terrainProvider = new Cesium.CesiumTerrainProvider({ // url: 'https://data.marsgis.cn/terrain', // }); // viewer.terrainProvider = new Cesium.CesiumTerrainProvider({ // url: Cesium.IonResource.fromAssetId(1), // requestWaterMask: false, // requestVertexNormals: true, // }) window.$viewer = viewer loadLAYER() } const loadLAYER = () => { let mapLayers = [] globalBaseMapLayers.length && globalBaseMapLayers.forEach(item => { if (item.mapLayer) item.mapLayer.show = false }) // 高德影像地图数据图层 if (store.state.common.mapSetting.mode === 3) { mapLayers.push( ...[ { key: 'imageryProvider_ammap', layer: imageryProvider_ammap }, { key: 'imageryProvider_ammapBz', layer: imageryProvider_ammapBz }, ] ) } // 高德地图矢量图层加载 if (store.state.common.mapSetting.mode === 2) { mapLayers.push({ key: 'imageryProvider_ammapSL', layer: imageryProvider_ammapSL, }) } // 标准地图加载 if (store.state.common.mapSetting.mode === 0) { mapLayers.push( ...[ { key: 'imageryProvider_standZh', layer: imageryProvider_standZh }, { key: 'imageryProvider_stand', layer: imageryProvider_stand }, ] ) } // 路线图加载 if ( store.state.common.mapSetting.roadLine === true && store.state.common.mapSetting.mode === 1 ) { mapLayers.push({ key: 'annotation', layer: annotation }) } // 天地图图层加载 if (store.state.common.mapSetting.mode === 1) { mapLayers.push({ key: 'imageryProvider_tdt', layer: imageryProvider_tdt, }) } // 创建一个Set来快速查找array2中的id let keyBaseMap = new Set(globalBaseMapLayers.map(item => item.key)) let keyMapLayers = new Set(mapLayers.map(item => item.key)) let keyExistBaseMap = mapLayers.filter(item => !keyBaseMap.has(item.key)) let keyNoExistBaseMap = globalBaseMapLayers.filter(item => keyMapLayers.has(item.key)) keyExistBaseMap.length && keyExistBaseMap.forEach(item => { let curLayer = { key: item.key, mapLayer: viewer?.imageryLayers.addImageryProvider(item.layer), } if (curLayer.key == 'imageryProvider_standZh') { curLayer.mapLayer.brightness = 0.6 // 亮度(默认值) curLayer.mapLayer.contrast = 1.8 // 对比度(负值降低对比度) curLayer.mapLayer.hue = 1 // 色相(弧度值,3.0可能导致紫色) curLayer.mapLayer.saturation = 0 // 增加饱和度强化蓝色 curLayer.mapLayer.gamma = 0.3 // 伽马校正(小于1.0使颜色更鲜艳) curLayer.invertColor = true // 启用反色 } if (curLayer.key == 'imageryProvider_stand') { curLayer.mapLayer.brightness = 0.6 // 亮度(默认值) curLayer.mapLayer.contrast = 1.8 // 对比度(负值降低对比度) curLayer.mapLayer.hue = 1 // 色相(弧度值,3.0可能导致紫色) curLayer.mapLayer.saturation = 0 // 增加饱和度强化蓝色 curLayer.mapLayer.gamma = 0.3 // 伽马校正(小于1.0使颜色更鲜艳) curLayer.invertColor = true // 启用反色 // curLayer.filterRGB = [0, 50, 100] addBlueFilter({ bInvertColor: true, bFilterColor: true, filterColor: '#4e70a6' },viewer) } if (curLayer.mapLayer) curLayer.mapLayer.show = true viewer?.imageryLayers.lowerToBottom(curLayer.mapLayer) globalBaseMapLayers.push(curLayer) }) keyNoExistBaseMap.length && keyNoExistBaseMap.forEach(item => { if (item.mapLayer) item.mapLayer.show = true viewer?.imageryLayers.lowerToBottom(item.mapLayer) }) // 2D/3D切换 switchModel(store.state.common.mapSetting.visual) } const addCustomLayers = (layerName, options) => { if (options.type == 'arcgis') { var imageryProvider = new Cesium.WebMapTileServiceImageryProvider({ url: options.src, layer: options.title, style: 'default', format: 'image/png', tileMatrixSetID: 'default', tilingScheme: new Cesium.GeographicTilingScheme(), tileMatrixLabels: [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', ], }) customMapLayer[layerName] = viewer?.imageryLayers.addImageryProvider(imageryProvider) // const layerProvider = new Cesium.ArcGisMapServerImageryProvider({ // url: options.src, // tilingScheme: new Cesium.GeographicTilingScheme() // }) // customMapLayer[layerName] = viewer?.imageryLayers.addImageryProvider(layerProvider) } } const removeCustomLayers = (layerName = '') => { if (layerName) { if (customMapLayer[layerName]) { viewer?.imageryLayers.remove(customMapLayer[layerName]) delete customMapLayer[layerName] } } else { for (let k in customMapLayer) { viewer?.imageryLayers.remove(customMapLayer[k]) } customMapLayer = {} } } // 切换不同背景图层 const patternMap = () => { const imageryLayers = viewer?.scene.imageryLayers // 切换为标准图层 if (store.state.common.mapSetting.mode === 0) { const tdtImg_c = imageryLayers?._layers.find(v => v.imageryProvider._layer === 'tdtImg_c') const tdtZwImg_c = imageryLayers?._layers.find(v => v.imageryProvider._layer === 'tdtZwImg_c') viewer?.imageryLayers.remove(tdtImg_c) viewer?.imageryLayers.remove(tdtZwImg_c) } else { const tdtStand_c = imageryLayers?._layers.find( v => v.imageryProvider.credit?.html === 'stand_tc' ) const tdtStand_zj = imageryLayers?._layers.find( v => v.imageryProvider.credit?.html === 'stand_zj' ) viewer?.imageryLayers.remove(tdtStand_c) viewer?.imageryLayers.remove(tdtStand_zj) } loadLAYER() } // 生成或删除路网图层 const roadPattern = flag => { if (store.state.common.mapSetting.mode === 0) return const imageryLayers = viewer?.scene.imageryLayers const tdtZwImg_c = imageryLayers?._layers.find(v => v.imageryProvider._layer === 'tdtZwImg_c') if (!flag) { viewer?.imageryLayers.remove(tdtZwImg_c) } else { viewer?.imageryLayers.addImageryProvider(annotation) } } // 二维三维切换 // 切换为二三维模式 const switchModel = type => { switch (type) { case '2D': viewer?.scene.morphTo2D(0) // viewer?.scene.camera.setView({ // orientation: { // pitch: Cesium.Math.toRadians(-60), // heading: Cesium.Math.toRadians(0), // }, // }); break case '3D': viewer?.scene.morphTo3D(0) // viewer?.scene.camera.setView({ // orientation: { // pitch: Cesium.Math.toRadians(-90), // heading: Cesium.Math.toRadians(0), // }, // }); break default: break } } /** * @description: 地图暗黑模式切换 * @param {*} viewer 地图实例 * @param {*} options 配置项 * @return {*} */ const darkMap = (viewer, isDark = false, options) => { const defaultOptions = { brightness: 1, contrast: 1, gamma: 1, hue: 0, saturation: 1, } !isDark && Object.assign(options, defaultOptions) const baseLayer = viewer.imageryLayers.get(0) baseLayer.brightness = options.brightness || 0 baseLayer.contrast = options.contrast || 0 baseLayer.gamma = options.gamma || 2 baseLayer.hue = options.hue || 0 baseLayer.saturation = options.saturation || 0 const baseFragShader = viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources for (let i = 0; i < baseFragShader.length; i++) { const strS = 'color = czm_saturation(color, textureSaturation);\n#endif\n' let strT = 'color = czm_saturation(color, textureSaturation);\n#endif\n' if (options.invertColor) { strT += ` color.r = 1.0 - color.r; color.g = 1.0 - color.g; color.b = 1.0 - color.b; ` } if (options.filterRGB.length > 0) { strT += ` color.r = color.r * ${options.filterRGB[0]}.0/255.0; color.g = color.g * ${options.filterRGB[1]}.0/255.0; color.b = color.b * ${options.filterRGB[2]}.0/255.0; ` } if (!isDark) { //恢复默认 baseFragShader[i] = baseFragShader[i].replace(strT, strS) } else { // 替换为暗黑模式 baseFragShader[i] = baseFragShader[i].replace(strS, strT) } } } const switchDarkModel = () => { const isDark = store.state.common.mapSetting.isDark darkMap(viewer, isDark, { //反色 invertColor: true, //滤色值 [176, 224, 230] filterRGB: [60, 145, 172], }) } //移除DataSource中所有实体 const removeAllDataSource = () => { viewer?.dataSources.removeAll() } // 清除所有标记点 const removeAllPoint = () => { if (viewer) { viewer?.entities?.removeAll() // viewer?.scene?.primitives?.removeAll(); } } // 通过点ID删除 const removeById = id => { viewer?.entities.removeById(id) const pointEntity = viewer?.entities.getById(id) if (pointEntity && pointEntity !== undefined) { viewer?.entities.remove(pointEntity) } } // 通过点ID获取实体 const getEntityById = id => { const pointEntity = viewer?.entities.getById(id) return pointEntity } // 添加标记点 const addPoint = pointOption => { if (!pointOption.longitude && !pointOption.latitude) return const position = Cesium.Cartesian3.fromDegrees( pointOption.longitude, pointOption.latitude, pointOption?.altitude || 0 ) viewer?.entities.add({ position, billboard: pointOption.billboard, point: pointOption.point, label: pointOption.label, id: pointOption.id, }) } const addPolyline = pointOption => { return viewer?.entities.add({ polyline: pointOption.polyline, id: pointOption.id, }) } // 更新图片实体位置 function updateEntityPosition (longitude, latitude, id, params) { const entity = getEntityById(id) const position = Cesium.Cartesian3.fromDegrees(longitude, latitude) const heading = Cesium.Math.toRadians(-params.heading) if (Cesium.defined(entity)) { entity.position = position entity.billboard.rotation = heading } } // 飞行 flyto const flyTo = (pointOption, time = 4, height = 3000, orientation = {}) => { if (!pointOption.longitude && !pointOption.latitude) return const destination = Cesium.Cartesian3.fromDegrees( pointOption.longitude, pointOption.latitude, height ) const duration = time viewer?.camera.flyTo({ destination, duration, orientation, }) } // 鼠标点击事件 const addLeftClickEvent = (sid, cb, eventKey = 'handler') => { if (handlerEvents.handler) removeLeftClickEvent() if (handlerEvents[eventKey]) removeLeftClickEvent(eventKey) handlerEvents[eventKey] = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas) handlerEvents[eventKey].setInputAction(function (click) { const pick = viewer?.scene.pick(click.position) if (pick && pick.primitive && pick.primitive?.customParams?.type == '3DTileset') { return cb(click, pick, viewer, handlerEvents[eventKey]) } if (pick && pick.id && (pick.id._id === sid || pick.id._id.includes(sid))) { cb(click, pick, viewer, handlerEvents[eventKey]) } if (sid === null) { cb(click, pick, viewer, handlerEvents[eventKey]) } }, Cesium.ScreenSpaceEventType.LEFT_CLICK) } // 移除鼠标点击事件 const removeLeftClickEvent = (eventKey = 'handler') => { if (handlerEvents[eventKey] == null) return handlerEvents[eventKey].removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK) handlerEvents[eventKey] = null } // 鼠标左键按下事件 let leftDownClickHandler = { handler: null } const addLeftDownClickEvent = (sid, cb, eventKey = 'handler') => { if (leftDownClickHandler.handler) removeLeftDownClickEvent() if (leftDownClickHandler[eventKey]) removeLeftDownClickEvent(eventKey) leftDownClickHandler[eventKey] = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas) leftDownClickHandler[eventKey].setInputAction(function (click) { const pick = viewer?.scene.pick(click.position) cb(click, pick, viewer) }, Cesium.ScreenSpaceEventType.LEFT_DOWN) } // 移除鼠标左键按下事件 const removeLeftDownClickEvent = (eventKey = 'handler') => { if (leftDownClickHandler[eventKey] == null) return leftDownClickHandler[eventKey].removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN) leftDownClickHandler[eventKey] = null } // 鼠标右击事件 let leftUpClickHandler = { handler: null } const addLeftUpClickEvent = (sid, cb, eventKey = 'handler') => { if (leftUpClickHandler.handler) removeLeftUpClickEvent() if (leftUpClickHandler[eventKey]) removeLeftUpClickEvent(eventKey) leftUpClickHandler[eventKey] = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas) leftUpClickHandler[eventKey].setInputAction(function (click) { const pick = viewer?.scene.pick(click.position) cb(click, pick, viewer) }, Cesium.ScreenSpaceEventType.LEFT_UP) } // 移除鼠标右键事件 const removeLeftUpClickEvent = (eventKey = 'handler') => { if (leftUpClickHandler[eventKey] == null) return leftUpClickHandler[eventKey].removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP) leftUpClickHandler[eventKey] = null } // 鼠标右击事件 let rightClickHandler const addRightClickEvent = (sid, cb) => { if (rightClickHandler) removeRightClickEvent() rightClickHandler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas) rightClickHandler.setInputAction(function (click) { const pick = viewer?.scene.pick(click.position) cb(click, pick, viewer) }, Cesium.ScreenSpaceEventType.RIGHT_CLICK) } // 移除鼠标右键事件 const removeRightClickEvent = () => { if (!rightClickHandler) return rightClickHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK) rightClickHandler = null } // 鼠标移动事件 let LeftMounseHandler const addLeftmounseEvent = (sid, cb) => { if (LeftMounseHandler) removeLeftmounseEvent() LeftMounseHandler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas) LeftMounseHandler.setInputAction(function (event) { const cartesian3 = viewer?.scene.globe.pick( viewer?.camera.getPickRay(event.startPosition), viewer?.scene ) cb(cartesian3, viewer) }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) } // 移除鼠标移动事件 const removeLeftmounseEvent = () => { if (LeftMounseHandler == null) return LeftMounseHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE) LeftMounseHandler = null } let MounseHandler const addMounseHandler = (sid, cb) => { if (MounseHandler == null) removeMounseEvent() MounseHandler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas) MounseHandler.setInputAction(function (movement) { let mouseInfo = _getMouseInfo(movement.endPosition) cb(mouseInfo, viewer) }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) } const _getMouseInfo = position => { let scene = viewer.scene let target = scene.pick(position) let cartesian = undefined let surfaceCartesian = undefined let wgs84Position = undefined let wgs84SurfacePosition = undefined if (scene.pickPositionSupported) { cartesian = scene.pickPosition(position) } if (cartesian) { let c = Cesium.Ellipsoid.WGS84.cartesianToCartographic(cartesian) if (c) { wgs84Position = { lng: Cesium.Math.toDegrees(c.longitude), lat: Cesium.Math.toDegrees(c.latitude), alt: c.height, } } } if ( scene.mode === Cesium.SceneMode.SCENE3D && !(viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider) ) { let ray = scene.camera.getPickRay(position) surfaceCartesian = scene.globe.pick(ray, scene) } else { surfaceCartesian = scene.camera.pickEllipsoid(position, Cesium.Ellipsoid.WGS84) } if (surfaceCartesian) { let c = Cesium.Ellipsoid.WGS84.cartesianToCartographic(surfaceCartesian) if (c) { wgs84SurfacePosition = { lng: Cesium.Math.toDegrees(c.longitude), lat: Cesium.Math.toDegrees(c.latitude), alt: c.height, } } } return { target: target, windowPosition: position, position: cartesian, wgs84Position: wgs84Position, surfacePosition: surfaceCartesian, wgs84SurfacePosition: wgs84SurfacePosition, } } // 移除鼠标移动事件 const removeMounseEvent = () => { if (MounseHandler == null) return MounseHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE) MounseHandler = null } // 视角变化时间 let mapViewHandler = null const addCameraMoveEvent = cb => { if (mapViewHandler) removeCameraMoveEvent() mapViewHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) mapViewHandler.setInputAction(event => { cb(event) }, Cesium.ScreenSpaceEventType.WHEEL) } const removeCameraMoveEvent = () => { if (mapViewHandler == null) return mapViewHandler.removeInputAction(Cesium.ScreenSpaceEventType.WHEEL) mapViewHandler = null } // 添加entity const addCustomEntityDataSource = (sourceName, entities) => { if (!customEntityDataSources[sourceName]) { customEntityDataSources[sourceName] = new Cesium.CustomDataSource() window.$viewer?.dataSources.add(customEntityDataSources[sourceName]) } let entity = customEntityDataSources[sourceName].entities.add(entities) return entity } const clearCustomEntityDataSource = sourceName => { if (customEntityDataSources[sourceName]) { customEntityDataSources[sourceName]?.entities.removeAll() } } const removeAllCustomEntityDataSource = sourceName => { if (customEntityDataSources[sourceName]) { customEntityDataSources[sourceName]?.entities.removeAll() window.$viewer.dataSources.remove(customEntityDataSources[sourceName]) delete customEntityDataSources[sourceName] } } // 添加entity const addCustomImageryProviderDataSource = imageryLayers => { return viewer?.imageryLayers.addImageryProvider(imageryLayers) } const showCustomImageryProviderDataSource = (imageryLayers, show) => { if (imageryLayers) { imageryLayers.show = show } } const removeAllCustomImageryProviderDataSource = imageryLayers => { if (imageryLayers) { viewer?.imageryLayers.remove(imageryLayers) } } // 添加范围的圆 const addEllipse = ({ longitude, latitude, dist = 7000 }) => { if (!longitude && !latitude) return // 定义起点位置 const position = Cesium.Cartesian3.fromDegrees(longitude, latitude) // 画圆 viewer?.entities.add({ position, id: 'rangeEllipse', name: 'rangeEllipse', ellipse: { semiMinorAxis: dist, semiMajorAxis: dist, outline: true, material: Cesium.Color.CORNFLOWERBLUE.withAlpha(0.3), }, }) // 添加距离虚线 // addDistLine({ longitude, latitude, dist }); } const addDistLine = ({ longitude, latitude, dist = 7 }) => { // 定义起点位置 const startPosition = Cesium.Cartesian3.fromDegrees(longitude, latitude) // 计算目标位置(7公里处) const offsetCartesian = Cesium.Cartesian3.fromDegrees( longitude, latitude + Cesium.Math.toDegrees( dist / (Cesium.Ellipsoid.WGS84.maximumRadius * Math.cos(Cesium.Math.toRadians(latitude))) ) // 7公里的偏移 ) // 将目标位置转换为经纬度 // const offsetCartographic = Cesium.Cartographic.fromCartesian(offsetCartesian); // const offsetLongitude = Cesium.Math.toDegrees(offsetCartographic.longitude); // const offsetLatitude = Cesium.Math.toDegrees(offsetCartographic.latitude); addPolyline({ id: 'dist_line', polyline: { width: 5, positions: [startPosition, offsetCartesian], material: new Cesium.PolylineGlowMaterialProperty({ glowPower: 0.2, taperPower: 0.5, color: Cesium.Color.CORNFLOWERBLUE, }), }, }) } // 添加圆 const addCircle = option => { if (!option.longitude && !option.latitude) return // 定义起点位置 const { longitude, latitude } = option const position = Cesium.Cartesian3.fromDegrees(longitude, latitude) viewer.entities.add({ position, id: option.id, ellipse: { semiMinorAxis: option.radius, semiMajorAxis: option.radius, height: option.height || 120, material: Cesium.Color.fromCssColorString(option.color).withAlpha(0.1), outline: true, outlineColor: Cesium.Color.fromCssColorString(option.color), outlineWidth: 3, }, }) } // /** * @description: 添加矩形 * @param {*} option { id: string, color: string, positions: array[ lng,lat,height ] } * @return {*} void 0 */ const addPolygon = option => { if (option.positions.length === 0) return let zIndex = {} if (option.zIndex) { zIndex = { zIndex: option.zIndex, } } // 定义起点位置 viewer.entities.add({ id: option.id, polygon: { hierarchy: Cesium.Cartesian3.fromDegreesArrayHeights(option.positions), material: Cesium.Color.fromCssColorString(option.color).withAlpha(0.1), extrudedHeight: 0, outline: true, outlineColor: Cesium.Color.fromCssColorString(option.color), outlineWidth: 3, }, ...zIndex, }) } // Cesium矢量切片是否加载完成 const isLoadingCompleted = () => { return new Promise((resolve, reject) => { const helper = new Cesium.EventHelper() helper.add(viewer?.scene.globe.tileLoadProgressEvent, function (e) { if (e === 0) { resolve(true) } }) }) } // 获取屏幕四个角经纬度 const getScreenCorner = () => { const camera = viewer.scene.camera const canvas = viewer.canvas // 获取屏幕左下角和右上角的世界坐标 const leftBottom = new Cesium.Cartesian2(0, canvas.clientHeight) const rightTop = new Cesium.Cartesian2(canvas.clientWidth, 0) // 将屏幕坐标转为世界坐标 const leftBottomWorld = camera.pickEllipsoid(leftBottom, viewer.scene.globe.ellipsoid) const rightTopWorld = camera.pickEllipsoid(rightTop, viewer.scene.globe.ellipsoid) // 将世界坐标转为经纬度 const leftBottomCartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(leftBottomWorld) const rightTopCartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(rightTopWorld) // 获取经纬度 const leftBottomLonLat = [ Cesium.Math.toDegrees(leftBottomCartographic.longitude), Cesium.Math.toDegrees(leftBottomCartographic.latitude), ] const rightTopLonLat = [ Cesium.Math.toDegrees(rightTopCartographic.longitude), Cesium.Math.toDegrees(rightTopCartographic.latitude), ] // 返回四个角的经纬度 return { lb: leftBottomLonLat, rb: [rightTopLonLat[0], leftBottomLonLat[1]], // 右下角 rt: rightTopLonLat, lt: [leftBottomLonLat[0], rightTopLonLat[1]], // 左上角 } } // 加载3D建筑模型 let tileset = null function setBuilding3dModel () { try { const resource = Cesium.IonResource.fromAssetId(96188) tileset = new Cesium.Cesium3DTileset({ url: resource, }) tileset.customParams = { type: '3DTileset', } viewer.scene.primitives.add(tileset) } catch (error) { console.log(`Error loading tileset: ${error}`) } } function removeBuilding3dModel () { if (tileset) { viewer.scene.primitives.remove(tileset) } } const viewerDestory = () => { viewer && viewer.destroy() viewer = null window.$viewer = null } let tilesetArr = [] const add3Dtileset = () => { let url = '/3Dtile/kjds/tileset.json' let tileset = new Cesium.Cesium3DTileset({ url: url, }) tileset.customParams = { type: '3DTileset', } tilesetArr.push(tileset) tilesetArr.forEach(i => viewer?.scene.primitives.add(i)) } const remove3Dtileset = () => { if (tilesetArr.length > 0) { tilesetArr.forEach(i => viewer.scene.primitives.remove(i)) } tilesetArr = [] } let pointEditHandler // 航点航线编辑相关事件 const pointInitEvent = (lefet_down, mouse_move, left_up) => { if (!pointEditHandler) { pointEditHandler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas) } const events = { lefet_down, mouse_move, left_up, } pointEditBindEvent(events) pointEditBindEvent(events, Cesium.KeyboardEventModifier.CTRL) pointEditBindEvent(events, Cesium.KeyboardEventModifier.ALT) pointEditBindEvent(events, Cesium.KeyboardEventModifier.SHIFT) pointEditBindEvent(events, Cesium.KeyboardEventModifier.META) } const pointEditBindEvent = (events, e) => { if (pointEditHandler) { pointEditHandler.setInputAction( events.lefet_down(e), Cesium.ScreenSpaceEventType.LEFT_DOWN, e ) pointEditHandler.setInputAction( events.mouse_move(e), Cesium.ScreenSpaceEventType.MOUSE_MOVE, e ) pointEditHandler.setInputAction(events.left_up(e), Cesium.ScreenSpaceEventType.LEFT_UP, e) } } const pointUnInitEvent = () => { pointEditUnBindEvent() pointEditUnBindEvent(Cesium.KeyboardEventModifier.CTRL) pointEditUnBindEvent(Cesium.KeyboardEventModifier.ALT) pointEditUnBindEvent(Cesium.KeyboardEventModifier.SHIFT) pointEditUnBindEvent(Cesium.KeyboardEventModifier.META) pointEditHandler = null } const pointEditUnBindEvent = e => { pointEditHandler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN, e) pointEditHandler?.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE, e) pointEditHandler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP, e) } return { _init, patternMap, loadLAYER, roadPattern, switchModel, switchDarkModel, removeAllDataSource, removeAllPoint, removeById, getEntityById, addPoint, addPolyline, updateEntityPosition, flyTo, addLeftClickEvent, removeLeftClickEvent, addRightClickEvent, removeRightClickEvent, addLeftmounseEvent, removeLeftmounseEvent, addLeftUpClickEvent, removeLeftUpClickEvent, addLeftDownClickEvent, removeLeftDownClickEvent, addMounseHandler, removeMounseEvent, addCameraMoveEvent, removeCameraMoveEvent, addCircle, addPolygon, addEllipse, isLoadingCompleted, getScreenCorner, setBuilding3dModel, removeBuilding3dModel, viewerDestory, globalCesium: window.globalCesium || Cesium, addCustomEntityDataSource, clearCustomEntityDataSource, removeAllCustomEntityDataSource, _getMouseInfo, addCustomImageryProviderDataSource, showCustomImageryProviderDataSource, removeAllCustomImageryProviderDataSource, addCustomLayers, removeCustomLayers, add3Dtileset, remove3Dtileset, // 航线规划---航点航线 pointInitEvent, pointUnInitEvent, } }