|
|
@@ -175,6 +175,8 @@ export default {
|
|
|
jsHeapSize: "", // 内存占用
|
|
|
gVendor: "",
|
|
|
gRenderer: "",
|
|
|
+ labelLayer: null, // 城市名称 label 集合
|
|
|
+ loadDone: false, // 地球首次加载滚动到 reset 位置是否完成
|
|
|
};
|
|
|
},
|
|
|
|
|
|
@@ -184,6 +186,7 @@ export default {
|
|
|
if (this.showDevInfoBox) {
|
|
|
this.initSystemInfo();
|
|
|
}
|
|
|
+ this.getData(106.169866, 38.46637);
|
|
|
},
|
|
|
|
|
|
unmounted() {
|
|
|
@@ -199,6 +202,15 @@ export default {
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
+ getData(lat, lon) {
|
|
|
+ // axios
|
|
|
+ // .get(
|
|
|
+ // `https://api.waqi.info/feed/geo:${lat};${lon}/?token=904a1bc6edf77c428347f2fe54cf663bcffaec21`
|
|
|
+ // )
|
|
|
+ // .then((res) => {
|
|
|
+ // console.log(1122, res);
|
|
|
+ // });
|
|
|
+ },
|
|
|
// 初始化一些监听事件
|
|
|
initEventListener() {
|
|
|
const mapBox = document.querySelector(".mapBox");
|
|
|
@@ -266,17 +278,26 @@ export default {
|
|
|
// addModel("模型1", 116.4, 39.9, 1000);
|
|
|
// addModel("模型2", 121.47, 31.23, 1000);
|
|
|
|
|
|
- // 添加点击事件显示坐标
|
|
|
- viewer.screenSpaceEventHandler.setInputAction((movement) => {
|
|
|
- try {
|
|
|
- const ray = viewer.camera.getPickRay(movement.position);
|
|
|
+ this.viewer = viewer;
|
|
|
+
|
|
|
+ this.setMapImageryProvider();
|
|
|
+ this.initGeoJsonData();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化Cesium内部鼠标事件
|
|
|
+ initEventInputAction() {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const viewer = this.viewer;
|
|
|
+ // 添加点击事件显示坐标
|
|
|
+ viewer.screenSpaceEventHandler.setInputAction((movement) => {
|
|
|
+ const ray = this.viewer.camera.getPickRay(movement.position);
|
|
|
if (!ray) {
|
|
|
this.tagMsg = null;
|
|
|
console.log("无法获取射线");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const position = viewer.scene.globe.pick(ray, viewer.scene);
|
|
|
+ const position = this.viewer.scene.globe.pick(ray, this.viewer.scene);
|
|
|
if (!position) {
|
|
|
this.tagMsg = null;
|
|
|
console.log("未找到地球表面交点");
|
|
|
@@ -290,143 +311,98 @@ export default {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const level = this.calculateTileLevel(viewer);
|
|
|
- const tilingScheme = new Cesium.WebMercatorTilingScheme();
|
|
|
-
|
|
|
- // 确保tilingScheme有positionToTileXY方法
|
|
|
- if (!tilingScheme.positionToTileXY) {
|
|
|
- console.error("tilingScheme没有positionToTileXY方法");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (!this.cloudLayer) {
|
|
|
- this.tagMsg = null;
|
|
|
- } else {
|
|
|
- this.tagMsg = "";
|
|
|
- }
|
|
|
-
|
|
|
- const tileXY = tilingScheme.positionToTileXY(cartographic, level);
|
|
|
+ this.getClickCloudOpacity(cartographic);
|
|
|
+ this.getLocationData(cartographic);
|
|
|
+ return;
|
|
|
|
|
|
- this.checkMode &&
|
|
|
- console.log(
|
|
|
- `瓦片坐标: 级别=${level}, X=${tileXY.x}, Y=${tileXY.y}`
|
|
|
+ const cartesian = viewer.camera.pickEllipsoid(
|
|
|
+ movement.position,
|
|
|
+ viewer.scene.globe.ellipsoid
|
|
|
+ );
|
|
|
+ if (cartesian) {
|
|
|
+ const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
|
|
|
+ const lon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(
|
|
|
+ 5
|
|
|
);
|
|
|
+ const lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(5);
|
|
|
+
|
|
|
+ viewer.entities.removeAll();
|
|
|
+ viewer.entities.add({
|
|
|
+ position: cartesian,
|
|
|
+ point: {
|
|
|
+ pixelSize: 10,
|
|
|
+ color: Cesium.Color.RED,
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ text: `经度: ${lon}°, 纬度: ${lat}°`,
|
|
|
+ font: '16px "Microsoft YaHei"',
|
|
|
+ fillColor: Cesium.Color.WHITE,
|
|
|
+ outlineColor: Cesium.Color.BLACK,
|
|
|
+ outlineWidth: 2,
|
|
|
+ style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
|
|
+ pixelOffset: new Cesium.Cartesian2(0, -30),
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
|
|
|
|
|
- // const mapSelect = this.basicMapList.find((ele) => {
|
|
|
- // return ele.id === this.basicMapId;
|
|
|
- // });
|
|
|
+ // 监听鼠标滚轮事件
|
|
|
+ viewer.screenSpaceEventHandler.setInputAction((wheelment) => {
|
|
|
+ this.tagMsg = null;
|
|
|
+ }, Cesium.ScreenSpaceEventType.WHEEL);
|
|
|
|
|
|
- const clickTileUrl = this.replaceTemplate(
|
|
|
- // mapSelect.url,
|
|
|
- "https://tile.openweathermap.org/map/clouds_new/{z}/{x}/{y}.png?appid=3b66d35579770393051599f8d518df4a",
|
|
|
- level,
|
|
|
- tileXY
|
|
|
- );
|
|
|
-
|
|
|
- this.checkMode && console.log(`用户点击位置瓦片url: ${clickTileUrl}`);
|
|
|
-
|
|
|
- // 存储当前瓦片信息
|
|
|
- const layer = viewer.imageryLayers.get(0);
|
|
|
- const provider = layer.imageryProvider;
|
|
|
- const currentTile = {
|
|
|
- x: tileXY.x,
|
|
|
- y: tileXY.y,
|
|
|
- level: level,
|
|
|
- rectangle: tilingScheme.tileXYToRectangle(
|
|
|
- tileXY.x,
|
|
|
- tileXY.y,
|
|
|
- level
|
|
|
- ),
|
|
|
- size: {
|
|
|
- width: provider.tileWidth || 256,
|
|
|
- height: provider.tileHeight || 256,
|
|
|
- },
|
|
|
- };
|
|
|
+ // 监听鼠标移动事件
|
|
|
+ viewer.screenSpaceEventHandler.setInputAction((movement) => {
|
|
|
+ this.getHoverCityLabel(movement);
|
|
|
+ }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
|
|
+ });
|
|
|
+ },
|
|
|
|
|
|
- // 计算并显示在瓦片内的位置
|
|
|
- const clickPos = this.calculateTilePosition(
|
|
|
- cartographic,
|
|
|
- currentTile
|
|
|
- );
|
|
|
+ // 获取鼠标划过位置的城市名称 label
|
|
|
+ getHoverCityLabel(movement) {
|
|
|
+ const picked = this.viewer.scene.pick(movement.startPosition);
|
|
|
+ const label = picked ? picked.primitive : null;
|
|
|
|
|
|
- if (this.cloudLayer) {
|
|
|
- this.getTileImageOpacity(
|
|
|
- clickTileUrl,
|
|
|
- clickPos.pixelX,
|
|
|
- clickPos.pixelY
|
|
|
- ).then((imgSource) => {
|
|
|
- const {
|
|
|
- rawAlpha, // 原始透明度值 (0-255)
|
|
|
- alphaPercentage, // 透明度百分比
|
|
|
- whiteScore, // 白色程度得分 (0-100)
|
|
|
- } = imgSource;
|
|
|
- this.checkMode && console.log(111, alphaPercentage);
|
|
|
- this.tagMsg = `${alphaPercentage * 2}%`;
|
|
|
- });
|
|
|
- }
|
|
|
+ if (label) {
|
|
|
+ this.viewer.scene.canvas.style.cursor = "pointer";
|
|
|
+ } else {
|
|
|
+ this.viewer.scene.canvas.style.cursor = "default";
|
|
|
+ }
|
|
|
|
|
|
- if (this.checkMode) {
|
|
|
- const tileRectangle = tilingScheme.tileXYToRectangle(
|
|
|
- tileXY.x,
|
|
|
- tileXY.y,
|
|
|
- level
|
|
|
- );
|
|
|
- this.highlightTile(viewer, tileRectangle);
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error("获取瓦片时出错:", error);
|
|
|
+ this.labelLayer._labels.forEach((ele) => {
|
|
|
+ if (ele.id === label?.id) {
|
|
|
+ label.fillColor = Cesium.Color.YELLOW;
|
|
|
+ label.outlineColor = Cesium.Color.BLACK;
|
|
|
+ } else {
|
|
|
+ ele.fillColor = Cesium.Color.fromCssColorString("#000");
|
|
|
+ ele.outlineColor = Cesium.Color.WHITE;
|
|
|
}
|
|
|
+ });
|
|
|
+ },
|
|
|
|
|
|
- return;
|
|
|
-
|
|
|
- // const cartesian = viewer.camera.pickEllipsoid(
|
|
|
- // movement.position,
|
|
|
- // viewer.scene.globe.ellipsoid
|
|
|
- // );
|
|
|
- // if (cartesian) {
|
|
|
- // const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
|
|
|
- // const lon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(5);
|
|
|
- // const lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(5);
|
|
|
-
|
|
|
- // viewer.entities.removeAll();
|
|
|
- // viewer.entities.add({
|
|
|
- // position: cartesian,
|
|
|
- // point: {
|
|
|
- // pixelSize: 10,
|
|
|
- // color: Cesium.Color.RED,
|
|
|
- // },
|
|
|
- // label: {
|
|
|
- // text: `经度: ${lon}°, 纬度: ${lat}°`,
|
|
|
- // font: '16px "Microsoft YaHei"',
|
|
|
- // fillColor: Cesium.Color.WHITE,
|
|
|
- // outlineColor: Cesium.Color.BLACK,
|
|
|
- // outlineWidth: 2,
|
|
|
- // style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
|
|
- // pixelOffset: new Cesium.Cartesian2(0, -30),
|
|
|
- // },
|
|
|
- // });
|
|
|
- // }
|
|
|
- }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
|
|
-
|
|
|
- // 监听鼠标滚轮事件
|
|
|
- viewer.screenSpaceEventHandler.setInputAction((wheelment) => {
|
|
|
- this.tagMsg = null;
|
|
|
- //从Cesium中获取当前地图瓦片等级
|
|
|
- // let tiles = new Set();
|
|
|
- // let tilesToRender = viewer.scene.globe._surface._tilesToRender;
|
|
|
- // if (Cesium.defined(tilesToRender)) {
|
|
|
- // for (let i = 0; i < tilesToRender.length; i++) {
|
|
|
- // tiles.add(tilesToRender[i].level);
|
|
|
- // }
|
|
|
- // console.log("当前地图瓦片级别为:");
|
|
|
- // console.log(tiles);
|
|
|
- // }
|
|
|
- }, Cesium.ScreenSpaceEventType.WHEEL);
|
|
|
-
|
|
|
- this.viewer = viewer;
|
|
|
+ // 根据经纬度获取周围一定范围城市基础信息
|
|
|
+ getLocationData({ latitude, longitude }) {
|
|
|
+ const lat = Cesium.Math.toDegrees(latitude);
|
|
|
+ const lon = Cesium.Math.toDegrees(longitude);
|
|
|
+ axios
|
|
|
+ .get(
|
|
|
+ `/ventusky/ventusky_location.json.php?lat=${lat}&lon=${lon}&zoom=${this.getZoomLevel()}`
|
|
|
+ )
|
|
|
+ .then((res) => {
|
|
|
+ console.log(111, res.data);
|
|
|
+ // https://api.waqi.info/feed/geo:35.3286804492;108.9025100708/?token=904a1bc6edf77c428347f2fe54cf663bcffaec21
|
|
|
+ // res.data.city
|
|
|
+ });
|
|
|
+ },
|
|
|
|
|
|
- this.setMapImageryProvider();
|
|
|
- this.initGeoJsonData();
|
|
|
+ // 获取 zoom 级别
|
|
|
+ getZoomLevel() {
|
|
|
+ let zoomLevel = 0;
|
|
|
+ const tilesToRender = this.viewer.scene.globe._surface._tilesToRender;
|
|
|
+ if (tilesToRender.length !== 0) {
|
|
|
+ zoomLevel = tilesToRender[0].level;
|
|
|
+ }
|
|
|
+ return zoomLevel - 1;
|
|
|
},
|
|
|
|
|
|
// 初始化性能监控
|
|
|
@@ -491,6 +467,82 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
+ getClickCloudOpacity(cartographic) {
|
|
|
+ try {
|
|
|
+ const level = this.calculateTileLevel(this.viewer);
|
|
|
+ const tilingScheme = new Cesium.WebMercatorTilingScheme();
|
|
|
+
|
|
|
+ // 确保 tilingScheme 有 positionToTileXY 方法
|
|
|
+ if (!tilingScheme.positionToTileXY) {
|
|
|
+ console.error("tilingScheme没有positionToTileXY方法");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.cloudLayer) {
|
|
|
+ this.tagMsg = null;
|
|
|
+ } else {
|
|
|
+ this.tagMsg = "";
|
|
|
+ }
|
|
|
+ const tileXY = tilingScheme.positionToTileXY(cartographic, level);
|
|
|
+
|
|
|
+ this.checkMode &&
|
|
|
+ console.log(`瓦片坐标: 级别=${level}, X=${tileXY.x}, Y=${tileXY.y}`);
|
|
|
+
|
|
|
+ const clickTileUrl = this.replaceTemplate(
|
|
|
+ // mapSelect.url,
|
|
|
+ "https://tile.openweathermap.org/map/clouds_new/{z}/{x}/{y}.png?appid=3b66d35579770393051599f8d518df4a",
|
|
|
+ level,
|
|
|
+ tileXY
|
|
|
+ );
|
|
|
+
|
|
|
+ this.checkMode && console.log(`用户点击位置瓦片url: ${clickTileUrl}`);
|
|
|
+
|
|
|
+ // 存储当前瓦片信息
|
|
|
+ const layer = this.viewer.imageryLayers.get(0);
|
|
|
+ const provider = layer.imageryProvider;
|
|
|
+ const currentTile = {
|
|
|
+ x: tileXY.x,
|
|
|
+ y: tileXY.y,
|
|
|
+ level: level,
|
|
|
+ rectangle: tilingScheme.tileXYToRectangle(tileXY.x, tileXY.y, level),
|
|
|
+ size: {
|
|
|
+ width: provider.tileWidth || 256,
|
|
|
+ height: provider.tileHeight || 256,
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ // 计算并显示在瓦片内的位置
|
|
|
+ const clickPos = this.calculateTilePosition(cartographic, currentTile);
|
|
|
+
|
|
|
+ if (this.cloudLayer) {
|
|
|
+ this.getTileImageOpacity(
|
|
|
+ clickTileUrl,
|
|
|
+ clickPos.pixelX,
|
|
|
+ clickPos.pixelY
|
|
|
+ ).then((imgSource) => {
|
|
|
+ const {
|
|
|
+ rawAlpha, // 原始透明度值 (0-255)
|
|
|
+ alphaPercentage, // 透明度百分比
|
|
|
+ whiteScore, // 白色程度得分 (0-100)
|
|
|
+ } = imgSource;
|
|
|
+ this.checkMode && console.log(111, alphaPercentage);
|
|
|
+ this.tagMsg = `${alphaPercentage * 2}%`;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.checkMode) {
|
|
|
+ const tileRectangle = tilingScheme.tileXYToRectangle(
|
|
|
+ tileXY.x,
|
|
|
+ tileXY.y,
|
|
|
+ level
|
|
|
+ );
|
|
|
+ this.highlightTile(viewer, tileRectangle);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取瓦片时出错:", error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
// 计算瓦片级别的辅助函数
|
|
|
calculateTileLevel(viewer) {
|
|
|
// 方法1:根据相机高度估算
|
|
|
@@ -614,7 +666,7 @@ export default {
|
|
|
async initGeoJsonData() {
|
|
|
// 创建GeoJSON数据源
|
|
|
await new Cesium.GeoJsonDataSource.load(basicGeoJson, {
|
|
|
- stroke: Cesium.Color.WHITE, // 边界线颜色
|
|
|
+ stroke: Cesium.Color.GRAY, // 边界线颜色
|
|
|
fill: Cesium.Color.BLACK.withAlpha(0), // 填充颜色
|
|
|
strokeWidth: 1, // 边界线宽度
|
|
|
markerSymbol: "?", // 点要素的符号
|
|
|
@@ -650,14 +702,15 @@ export default {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- cities.forEach((city) => {
|
|
|
+ cities.forEach((city, index) => {
|
|
|
labelLayer.add({
|
|
|
+ id: index,
|
|
|
name: "cityLabel",
|
|
|
position: Cesium.Cartesian3.fromDegrees(city.lon, city.lat, 10),
|
|
|
text: city.name,
|
|
|
font: 'bold 14px "Microsoft YaHei", sans-serif',
|
|
|
- fillColor: Cesium.Color.YELLOW,
|
|
|
- outlineColor: Cesium.Color.BLACK,
|
|
|
+ fillColor: Cesium.Color.fromCssColorString("#000"),
|
|
|
+ outlineColor: Cesium.Color.WHITE,
|
|
|
outlineWidth: 2,
|
|
|
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
|
|
pixelOffset: new Cesium.Cartesian2(0, 0), // 设置为0
|
|
|
@@ -666,6 +719,7 @@ export default {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
+ this.labelLayer = labelLayer;
|
|
|
this.resetViewport();
|
|
|
});
|
|
|
},
|
|
|
@@ -673,6 +727,7 @@ export default {
|
|
|
// 重置视角
|
|
|
resetViewport(height = 0) {
|
|
|
// 设置初始视图为宁夏
|
|
|
+ const that = this;
|
|
|
this.viewer.camera.flyTo({
|
|
|
destination: Cesium.Cartesian3.fromDegrees(
|
|
|
106.169866,
|
|
|
@@ -685,6 +740,13 @@ export default {
|
|
|
roll: 0.0,
|
|
|
},
|
|
|
duration: 1.0,
|
|
|
+ complete() {
|
|
|
+ // 为什么要加这个?因为破库地球没完全加载完成时如果执行了监听鼠标滑动事件会光速报错滑跪
|
|
|
+ if (!that.loadDone) {
|
|
|
+ that.initEventInputAction();
|
|
|
+ that.loadDone = true;
|
|
|
+ }
|
|
|
+ },
|
|
|
});
|
|
|
},
|
|
|
|