|
@@ -48,136 +48,224 @@ onMounted(async () => {
|
|
|
infoBox: false,
|
|
|
//加载地形效果
|
|
|
terrainProvider: await Cesium.createWorldTerrainAsync({
|
|
|
+ url: 'http://10.8.11.98:9003/terrain/GlobeDEM/layer.json', // 注意修正URL中的locallhost为localhost
|
|
|
requestVertexNormals: true,
|
|
|
- // requestWaterMask: true,
|
|
|
+ // requestWaterMask: true,
|
|
|
})
|
|
|
});
|
|
|
|
|
|
- // 定义距离显示条件和缩放属性(保持不变)
|
|
|
- const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 10000000);
|
|
|
- const pointNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 1000000, 0.3);
|
|
|
- const labelNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 400000, 0);
|
|
|
-
|
|
|
- // 存储实体与数据的映射(保持不变)
|
|
|
- const entityDataMap = new Map();
|
|
|
- JYLData.forEach((item) => {
|
|
|
- const position = Cesium.Cartesian3.fromDegrees(
|
|
|
- parseFloat(item.LGTD),
|
|
|
- parseFloat(item.LTTD)
|
|
|
- );
|
|
|
- const entity = viewer.entities.add({
|
|
|
- position: position,
|
|
|
- billboard: {
|
|
|
- image: '/src/assets/icon/blue.png',
|
|
|
- scale: 0.4,
|
|
|
- color: Cesium.Color.YELLOW,
|
|
|
- horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
- verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
- distanceDisplayCondition: distanceDisplayCondition,
|
|
|
- scaleByDistance: pointNearFarScalar
|
|
|
- },
|
|
|
- label: {
|
|
|
- text: item.STNM || '未知点',
|
|
|
- font: '25px 微软雅黑',
|
|
|
- fillColor: Cesium.Color.WHITE,
|
|
|
- backgroundColor: new Cesium.Color(0.1, 0.1, 0.1, 0.7),
|
|
|
- backgroundPadding: new Cesium.Cartesian2(8, 4),
|
|
|
- showBackground: true,
|
|
|
- cornerRadius: 4,
|
|
|
- outlineColor: Cesium.Color.BLACK,
|
|
|
- outlineWidth: 1,
|
|
|
- horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
- verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
- pixelOffset: new Cesium.Cartesian2(0, -32),
|
|
|
- scale: 1.0,
|
|
|
- disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
|
- distanceDisplayCondition: distanceDisplayCondition,
|
|
|
- scaleByDistance: labelNearFarScalar
|
|
|
- },
|
|
|
- id: `point-${item.STCD || item.LGTD + '-' + item.LTTD}`,
|
|
|
- properties: {
|
|
|
- data: item
|
|
|
+ try {
|
|
|
+ // 1. 请求并解析TMS元数据XML
|
|
|
+ const xmlUrl = 'http://10.8.11.98:9003/image/tms/HTHDOM/tilemapresource.xml';
|
|
|
+ const response = await fetch(xmlUrl);
|
|
|
+ const xmlText = await response.text();
|
|
|
+ const parser = new DOMParser();
|
|
|
+ const xmlDoc = parser.parseFromString(xmlText, 'text/xml');
|
|
|
+
|
|
|
+ // 2. 从XML中提取关键参数
|
|
|
+ const tileFormat = xmlDoc.querySelector('TileFormat').getAttribute('extension'); // 如"png"
|
|
|
+ const maxLevel = xmlDoc.querySelectorAll('TileSet').length - 1; // 最大层级(假设层级从0开始)
|
|
|
+ const srs = xmlDoc.querySelector('SRS').textContent; // 如"EPSG:3857"
|
|
|
+
|
|
|
+ // 3. 加载TMS影像
|
|
|
+ const tmsImagery = new Cesium.UrlTemplateImageryProvider({
|
|
|
+ url: `http://10.8.11.98:9003/image/tms/HTHDOM/{z}/{x}/{y}.${tileFormat}`,
|
|
|
+ tileWidth: 256, // 从XML的TileFormat中获取width
|
|
|
+ tileHeight: 256, // 从XML的TileFormat中获取height
|
|
|
+ maximumLevel: maxLevel,
|
|
|
+ projection: srs === 'EPSG:3857' ? Cesium.WebMercatorProjection : Cesium.GeographicProjection,
|
|
|
+ // 核心:TMS行号反转(解决上下颠倒)
|
|
|
+ urlTemplateFunction: (x, y, level) => {
|
|
|
+ const tmsY = Math.pow(2, level) - 1 - y; // 反转行号
|
|
|
+ return `http://10.8.11.98:9003/image/tms/HTHDOM//${level}/${x}/${tmsY}.${tileFormat}`;
|
|
|
}
|
|
|
});
|
|
|
- entityDataMap.set(entity.id, item);
|
|
|
- });
|
|
|
|
|
|
- // 天地图图层(保持不变)
|
|
|
- const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
|
|
|
- url: `http://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
|
|
|
- layer: "tdt",
|
|
|
- style: "default",
|
|
|
- format: "image/jpeg",
|
|
|
- tileMatrixSetID: "w",
|
|
|
- maximumLevel: 18,
|
|
|
- show: false,
|
|
|
- });
|
|
|
- viewer.imageryLayers.addImageryProvider(tdtLayer);
|
|
|
-
|
|
|
- const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
|
|
|
- url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
|
|
|
- layer: "tdtAnno",
|
|
|
- style: "default",
|
|
|
- format: "image/jpeg",
|
|
|
- tileMatrixSetID: "w",
|
|
|
- maximumLevel: 18,
|
|
|
- show: false,
|
|
|
- });
|
|
|
- viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);
|
|
|
-
|
|
|
- // 初始化视图(保持不变)
|
|
|
- viewer.cesiumWidget.creditContainer.style.display = "none";
|
|
|
- viewer.camera.setView({
|
|
|
- destination: Cesium.Cartesian3.fromDegrees(120.169103, 31.226174, 500000),
|
|
|
- orientation: {
|
|
|
- heading: Cesium.Math.toRadians(0),
|
|
|
- pitch: Cesium.Math.toRadians(-90),
|
|
|
- },
|
|
|
- });
|
|
|
+ viewer.imageryLayers.addImageryProvider(tmsImagery);
|
|
|
+ console.log('TMS影像加载成功');
|
|
|
+
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ console.error('加载TMS影像失败:', error);
|
|
|
+ // 检查XML URL是否正确(可能拼写错误,如localhost是否少写字母)
|
|
|
+ if (error.message.includes('404')) {
|
|
|
+ console.warn('请确认XML路径正确:', xmlUrl);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // 点击事件处理(核心修改)
|
|
|
- handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
|
|
|
- handler.setInputAction((click) => {
|
|
|
- const scaleRatio = getScaleRatio();
|
|
|
- const correctedX = click.position.x / scaleRatio;
|
|
|
- const correctedY = click.position.y / scaleRatio;
|
|
|
- const pickedObject = viewer.scene.pick(new Cesium.Cartesian2(correctedX, correctedY));
|
|
|
-
|
|
|
- if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
|
|
|
- const entityId = pickedObject.id.id;
|
|
|
- const data = entityDataMap.get(entityId) || pickedObject.id.properties?.data?.getValue();
|
|
|
-
|
|
|
- if (data) {
|
|
|
- selectedPoint.value = data;
|
|
|
- // 关键:计算图标屏幕坐标,固定显示在图标上方
|
|
|
- const entityPosition = viewer.scene.cartesianToCanvasCoordinates(pickedObject.id.position._value);
|
|
|
- if (entityPosition) {
|
|
|
- popupPosition.value = {
|
|
|
- // 水平居中对齐图标
|
|
|
- x: (entityPosition.x / scaleRatio) - 100,
|
|
|
- // 固定显示在图标上方(距离图标底部10px)
|
|
|
- y: (entityPosition.y / scaleRatio) - 130 // 130 = 弹框高度 + 间距
|
|
|
- };
|
|
|
- }
|
|
|
- viewer.flyTo(pickedObject.id, {
|
|
|
- offset: new Cesium.HeadingPitchRange(0, -0.5, 1500)
|
|
|
+// 多块倾斜摄影瓦片集的URL列表(根据实际路径修改)
|
|
|
+const tilesetUrls = [
|
|
|
+ "http://localhost:9003/model/TSQ1234/tileset.json",
|
|
|
+ "http://localhost:9003/model/SY123/tileset.json",
|
|
|
+ "http://10.8.11.98:9003/model/tvhy8PnM8/tileset.json",
|
|
|
+ "http://10.8.11.98:9003/model/t9or0ZtaT/tileset.json"
|
|
|
+
|
|
|
+];
|
|
|
+
|
|
|
+// 存储加载成功的瓦片集(可选,用于后续管理)
|
|
|
+const loadedTilesets = [];
|
|
|
+
|
|
|
+
|
|
|
+// 批量加载瓦片集(不调整视角)
|
|
|
+async function loadMultipleTilesets() {
|
|
|
+ try {
|
|
|
+ // 遍历URL列表,并行加载所有瓦片集
|
|
|
+ const promises = tilesetUrls.map(async (url, index) => {
|
|
|
+ try {
|
|
|
+ const tileset = await Cesium.Cesium3DTileset.fromUrl(url, {
|
|
|
+ maximumScreenSpaceError: 32, // 细节层级控制
|
|
|
+ dynamicScreenSpaceError: true,
|
|
|
+ skipLevelOfDetail: true,
|
|
|
+ maximumConcurrentRequests: 5,
|
|
|
+ tileCacheSize: 100
|
|
|
});
|
|
|
+ // 添加到场景
|
|
|
+ viewer.scene.primitives.add(tileset);
|
|
|
+ loadedTilesets.push(tileset);
|
|
|
+ console.log(`第${index + 1}块瓦片集加载完成`);
|
|
|
+ return tileset;
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`第${index + 1}块瓦片集加载失败:`, error);
|
|
|
+ return null; // 单块失败不影响其他块
|
|
|
}
|
|
|
- } else {
|
|
|
- selectedPoint.value = null;
|
|
|
- }
|
|
|
- }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
|
|
+ });
|
|
|
|
|
|
- // 清理函数(移除鼠标移动监听)
|
|
|
- onUnmounted(() => {
|
|
|
- if (handler) {
|
|
|
- handler.destroy();
|
|
|
- handler = null;
|
|
|
- }
|
|
|
- if (viewer && !viewer.isDestroyed()) {
|
|
|
- viewer.destroy();
|
|
|
+ // 等待所有瓦片集加载(无论成功与否)
|
|
|
+ await Promise.all(promises);
|
|
|
+ console.log("所有瓦片集加载操作已完成");
|
|
|
+ } catch (error) {
|
|
|
+ console.error("批量加载逻辑出错:", error);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 执行加载(加载后保持原有视口)
|
|
|
+loadMultipleTilesets();
|
|
|
+
|
|
|
+// 定义距离显示条件和缩放属性(保持不变)
|
|
|
+const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 10000000);
|
|
|
+const pointNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 1000000, 0.3);
|
|
|
+const labelNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 400000, 0);
|
|
|
+
|
|
|
+// 存储实体与数据的映射(保持不变)
|
|
|
+const entityDataMap = new Map();
|
|
|
+JYLData.forEach((item) => {
|
|
|
+ const position = Cesium.Cartesian3.fromDegrees(
|
|
|
+ parseFloat(item.LGTD),
|
|
|
+ parseFloat(item.LTTD)
|
|
|
+ );
|
|
|
+ const entity = viewer.entities.add({
|
|
|
+ position: position,
|
|
|
+ billboard: {
|
|
|
+ image: '/src/assets/icon/blue.png',
|
|
|
+ scale: 0.4,
|
|
|
+ color: Cesium.Color.YELLOW,
|
|
|
+ horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
+ verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
+ distanceDisplayCondition: distanceDisplayCondition,
|
|
|
+ scaleByDistance: pointNearFarScalar
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ text: item.STNM || '未知点',
|
|
|
+ font: '25px 微软雅黑',
|
|
|
+ fillColor: Cesium.Color.WHITE,
|
|
|
+ backgroundColor: new Cesium.Color(0.1, 0.1, 0.1, 0.7),
|
|
|
+ backgroundPadding: new Cesium.Cartesian2(8, 4),
|
|
|
+ showBackground: true,
|
|
|
+ cornerRadius: 4,
|
|
|
+ outlineColor: Cesium.Color.BLACK,
|
|
|
+ outlineWidth: 1,
|
|
|
+ horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
+ verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
+ pixelOffset: new Cesium.Cartesian2(0, -32),
|
|
|
+ scale: 1.0,
|
|
|
+ disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
|
+ distanceDisplayCondition: distanceDisplayCondition,
|
|
|
+ scaleByDistance: labelNearFarScalar
|
|
|
+ },
|
|
|
+ id: `point-${item.STCD || item.LGTD + '-' + item.LTTD}`,
|
|
|
+ properties: {
|
|
|
+ data: item
|
|
|
}
|
|
|
});
|
|
|
+ entityDataMap.set(entity.id, item);
|
|
|
+});
|
|
|
+
|
|
|
+// 天地图图层(保持不变)
|
|
|
+const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
|
|
|
+ url: `https://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
|
|
|
+ layer: "tdt",
|
|
|
+ style: "default",
|
|
|
+ format: "image/jpeg",
|
|
|
+ tileMatrixSetID: "w",
|
|
|
+ maximumLevel: 16,
|
|
|
+ show: true,
|
|
|
+});
|
|
|
+viewer.imageryLayers.addImageryProvider(tdtLayer);
|
|
|
+
|
|
|
+const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
|
|
|
+ url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
|
|
|
+ layer: "tdtAnno",
|
|
|
+ style: "default",
|
|
|
+ format: "image/jpeg",
|
|
|
+ tileMatrixSetID: "w",
|
|
|
+ maximumLevel: 18,
|
|
|
+ show: false,
|
|
|
+});
|
|
|
+viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);
|
|
|
+
|
|
|
+// 初始化视图(保持不变)
|
|
|
+viewer.cesiumWidget.creditContainer.style.display = "none";
|
|
|
+viewer.camera.setView({
|
|
|
+ destination: Cesium.Cartesian3.fromDegrees(120.169103, 31.226174, 500000),
|
|
|
+ orientation: {
|
|
|
+ heading: Cesium.Math.toRadians(0),
|
|
|
+ pitch: Cesium.Math.toRadians(-90),
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+// 点击事件处理(核心修改)
|
|
|
+handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
|
|
|
+handler.setInputAction((click) => {
|
|
|
+ const scaleRatio = getScaleRatio();
|
|
|
+ const correctedX = click.position.x / scaleRatio;
|
|
|
+ const correctedY = click.position.y / scaleRatio;
|
|
|
+ const pickedObject = viewer.scene.pick(new Cesium.Cartesian2(correctedX, correctedY));
|
|
|
+
|
|
|
+ if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
|
|
|
+ const entityId = pickedObject.id.id;
|
|
|
+ const data = entityDataMap.get(entityId) || pickedObject.id.properties?.data?.getValue();
|
|
|
+
|
|
|
+ if (data) {
|
|
|
+ selectedPoint.value = data;
|
|
|
+ // 关键:计算图标屏幕坐标,固定显示在图标上方
|
|
|
+ const entityPosition = viewer.scene.cartesianToCanvasCoordinates(pickedObject.id.position._value);
|
|
|
+ if (entityPosition) {
|
|
|
+ popupPosition.value = {
|
|
|
+ // 水平居中对齐图标
|
|
|
+ x: (entityPosition.x / scaleRatio) - 100,
|
|
|
+ // 固定显示在图标上方(距离图标底部10px)
|
|
|
+ y: (entityPosition.y / scaleRatio) - 130 // 130 = 弹框高度 + 间距
|
|
|
+ };
|
|
|
+ }
|
|
|
+ viewer.flyTo(pickedObject.id, {
|
|
|
+ offset: new Cesium.HeadingPitchRange(0, -0.5, 1500)
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ selectedPoint.value = null;
|
|
|
+ }
|
|
|
+}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
|
|
+
|
|
|
+// 清理函数(移除鼠标移动监听)
|
|
|
+onUnmounted(() => {
|
|
|
+ if (handler) {
|
|
|
+ handler.destroy();
|
|
|
+ handler = null;
|
|
|
+ }
|
|
|
+ if (viewer && !viewer.isDestroyed()) {
|
|
|
+ viewer.destroy();
|
|
|
+ }
|
|
|
+});
|
|
|
});
|
|
|
</script>
|
|
|
|
|
@@ -185,7 +273,8 @@ onMounted(async () => {
|
|
|
.custom-popup {
|
|
|
position: absolute;
|
|
|
z-index: 1000;
|
|
|
- display: block; /* 始终显示(由v-if控制显隐) */
|
|
|
+ display: block;
|
|
|
+ /* 始终显示(由v-if控制显隐) */
|
|
|
pointer-events: none;
|
|
|
}
|
|
|
|
|
@@ -200,7 +289,8 @@ onMounted(async () => {
|
|
|
|
|
|
.popup-arrow {
|
|
|
position: absolute;
|
|
|
- bottom: -10px; /* 指向图标 */
|
|
|
+ bottom: -10px;
|
|
|
+ /* 指向图标 */
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
width: 0;
|
|
@@ -222,4 +312,4 @@ onMounted(async () => {
|
|
|
color: #666;
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|