2025-05-22 13:56:20 +08:00
|
|
|
|
<template>
|
|
|
|
|
<div id="map-container" class="map-container">
|
|
|
|
|
<slot></slot>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import * as Cesium from 'cesium';
|
2025-05-22 14:10:41 +08:00
|
|
|
|
import { CustomBaiduImageryProvider } from "./CustomBaiduImageryProvider.js";
|
2025-05-22 13:56:20 +08:00
|
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
options: {
|
|
|
|
|
type: Object,
|
|
|
|
|
default: () => {
|
|
|
|
|
return {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
let viewer = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
initMap();
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 初始化地图
|
|
|
|
|
const initMap = async () => {
|
2025-05-22 16:42:40 +08:00
|
|
|
|
let terrainProvider = await Cesium.createWorldTerrainAsync()
|
|
|
|
|
|
2025-05-22 13:56:20 +08:00
|
|
|
|
const oldOptions = {
|
|
|
|
|
// 动画仪表盘
|
|
|
|
|
animation: false,
|
|
|
|
|
// 基础图层选择按钮
|
|
|
|
|
baseLayerPicker: false,
|
|
|
|
|
// 全屏按钮
|
|
|
|
|
fullscreenButton: false,
|
|
|
|
|
vrButton: false,
|
|
|
|
|
// 地名地址查询框
|
|
|
|
|
geocoder: false,
|
|
|
|
|
// 返回地球视角按钮
|
|
|
|
|
homeButton: false,
|
|
|
|
|
// 属性框(显示拾取要素的属性)
|
|
|
|
|
infoBox: false,
|
|
|
|
|
// 场景模式切换按钮(三维地球、2.5维场景、二维地图)
|
|
|
|
|
sceneModePicker: false,
|
|
|
|
|
// 拾取要素识别(显示个框,但不明确选中内容)???
|
|
|
|
|
selectionIndicator: false,
|
|
|
|
|
// 时间轴
|
|
|
|
|
timeline: false,
|
|
|
|
|
// 操作提示按钮
|
|
|
|
|
navigationHelpButton: false,
|
|
|
|
|
// 超采样开4倍,如果显示困难再降低
|
|
|
|
|
msaaSamples: 2,
|
|
|
|
|
scene3DOnly: true,
|
|
|
|
|
shouldAnimate: true,
|
|
|
|
|
contextOptions: {
|
|
|
|
|
webgl: {
|
|
|
|
|
// 允许截图
|
|
|
|
|
preserveDrawingBuffer: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
// 添加cesium的token(目前使用zq发布的)
|
|
|
|
|
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiZjljMTU0MC03OGY5LTRjMzQtYWJkYS02MzI2OTI2OGUyNTgiLCJpZCI6MzE3NTgsImlhdCI6MTc0MTA1MjY3OH0.uvbT5jSUFS-wU41MvzAuY33yfYnUiOWQCWad2KSX28o'
|
|
|
|
|
console.log(props.options.configJson)
|
|
|
|
|
let configJson = props.options.configJson;
|
|
|
|
|
try {
|
|
|
|
|
configJson = JSON.parse(configJson)
|
|
|
|
|
} catch (e) {
|
|
|
|
|
configJson = {}
|
|
|
|
|
}
|
|
|
|
|
if (props.options.isTerrainProvider) {
|
2025-05-22 16:42:40 +08:00
|
|
|
|
// 是否使用自定义地形
|
|
|
|
|
if(props.options.cesiumTerrainProviderUrl) {
|
|
|
|
|
const customTerrainProvider = await Cesium.CesiumTerrainProvider.fromUrl(props.options.cesiumTerrainProviderUrl);
|
|
|
|
|
if(customTerrainProvider) {
|
|
|
|
|
terrainProvider = customTerrainProvider;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-22 13:56:20 +08:00
|
|
|
|
oldOptions.terrainProvider = terrainProvider;
|
|
|
|
|
}
|
|
|
|
|
let options = Object.assign(oldOptions, configJson)
|
|
|
|
|
viewer = new Cesium.Viewer('map-container', options)
|
|
|
|
|
|
|
|
|
|
// 启用深度测试
|
|
|
|
|
// viewer.scene.globe.depthTestAgainstTerrain = true;
|
|
|
|
|
// 隐藏logo
|
|
|
|
|
viewer.cesiumWidget.creditContainer.style.display = 'none'
|
|
|
|
|
|
|
|
|
|
setInitConfig();
|
|
|
|
|
|
|
|
|
|
// 取消左键双击
|
|
|
|
|
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置初始值
|
|
|
|
|
const setInitConfig = () => {
|
|
|
|
|
let options = props.options;
|
|
|
|
|
mapSetView(options);
|
|
|
|
|
// 地形夸张
|
|
|
|
|
if (options.terrainExaggeration) {
|
|
|
|
|
viewer.scene.globe.terrainExaggeration = options.terrainExaggeration;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setMapImg(options);
|
2025-05-22 16:42:40 +08:00
|
|
|
|
setModel(options);
|
2025-05-22 13:56:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置地图
|
|
|
|
|
const setMapImg = (options) => {
|
|
|
|
|
if (!options.ditu) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.ditu === 'amap') {
|
|
|
|
|
const gaodeVector = new Cesium.UrlTemplateImageryProvider({
|
|
|
|
|
url: "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
|
|
|
|
|
name: "高德矢量地图",
|
|
|
|
|
});
|
|
|
|
|
viewer.imageryLayers.addImageryProvider(gaodeVector);
|
|
|
|
|
} else if (options.ditu === 'tencent') {
|
|
|
|
|
const tencentVector = new Cesium.UrlTemplateImageryProvider({
|
|
|
|
|
url: "https://rt3.map.gtimg.com/tile?z={z}&x={x}&y={reverseY}&styleid=1&version=297",
|
|
|
|
|
customTags: {
|
|
|
|
|
sx: function (imageryProvider, x, y, level) {
|
|
|
|
|
return x >> 4;
|
|
|
|
|
},
|
|
|
|
|
sy: function (imageryProvider, x, y, level) {
|
|
|
|
|
return ((1 << level) - y) >> 4;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
name: "腾讯矢量地图",
|
|
|
|
|
});
|
|
|
|
|
viewer.imageryLayers.addImageryProvider(tencentVector);
|
|
|
|
|
} else if (options.ditu === 'baidu') {
|
2025-05-22 14:10:41 +08:00
|
|
|
|
const baiduVector = new CustomBaiduImageryProvider({
|
2025-05-22 13:56:20 +08:00
|
|
|
|
url: "http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1",
|
|
|
|
|
});
|
|
|
|
|
viewer.imageryLayers.addImageryProvider(baiduVector);
|
|
|
|
|
} else if (options.ditu === 'tianditu') {
|
|
|
|
|
const tiandituImage = new Cesium.WebMapTileServiceImageryProvider({
|
|
|
|
|
url: "http://t0.tianditu.gov.cn/img_w/wmts?tk=25129831bd91c81af49d3ecf578f6b3c",
|
|
|
|
|
layer: "img",
|
|
|
|
|
style: "default",
|
|
|
|
|
format: "tiles",
|
|
|
|
|
tileMatrixSetID: "w",
|
|
|
|
|
maximumLevel: 18,
|
|
|
|
|
credit: new Cesium.Credit("© Tianditu", "http://www.tianditu.gov.cn/"),
|
|
|
|
|
name: "天地图影像地图",
|
|
|
|
|
});
|
|
|
|
|
viewer.imageryLayers.addImageryProvider(tiandituImage);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 地图设置视角
|
|
|
|
|
const mapSetView = (options) => {
|
|
|
|
|
let destination = Cesium.Cartesian3.fromDegrees(options.setView.x, options.setView.y, options.setView.z);
|
|
|
|
|
let orientation = {
|
|
|
|
|
heading: Cesium.Math.toRadians(options.setView.heading),
|
|
|
|
|
pitch: Cesium.Math.toRadians(options.setView.pitch),
|
|
|
|
|
roll: Cesium.Math.toRadians(options.setView.roll)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.setView.duration === '默认') {
|
|
|
|
|
viewer.camera.flyTo({
|
|
|
|
|
destination,
|
|
|
|
|
orientation
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
viewer.camera.flyTo({
|
|
|
|
|
destination,
|
|
|
|
|
orientation,
|
|
|
|
|
duration: options.setView.duration
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-22 16:42:40 +08:00
|
|
|
|
// 设置模型
|
|
|
|
|
const setModel = async (options) => {
|
|
|
|
|
// 3d模型参数
|
|
|
|
|
const tilesetOption = {
|
|
|
|
|
maximumScreenSpaceError: 1, // 应对大疆一键生成的模型问题;如模型能正常显示但文件加载太过频繁,可增大数值
|
|
|
|
|
skipLevelOfDetail: true,
|
|
|
|
|
// baseScreenSpaceError: 1024,
|
|
|
|
|
// skipScreenSpaceErrorFactor: 16,
|
|
|
|
|
skipLevels: 5,
|
|
|
|
|
// immediatelyLoadDesiredLevelOfDetail: false,
|
|
|
|
|
// loadSiblings: false,
|
|
|
|
|
// cullWithChildrenBounds: true
|
|
|
|
|
};
|
|
|
|
|
for (const url of options.modelList) {
|
|
|
|
|
const primitive = await Cesium.Cesium3DTileset.fromUrl(url, tilesetOption);
|
|
|
|
|
if(primitive) {
|
|
|
|
|
viewer.scene.primitives.add(primitive);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-22 13:56:20 +08:00
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
if (viewer) {
|
|
|
|
|
viewer.entities.removeAll()
|
|
|
|
|
viewer.imageryLayers.removeAll()
|
|
|
|
|
for (let index = 0; index < viewer.dataSources.length; index++) {
|
|
|
|
|
const datasource = viewer.dataSources.get(index);
|
|
|
|
|
datasource.entities.removeAll()
|
|
|
|
|
}
|
|
|
|
|
viewer.dataSources.removeAll(true)
|
|
|
|
|
// viewer.scene.primitives.removeAll();
|
|
|
|
|
viewer.destroy()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
.map-container {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
</style>
|