Commit 6a08bfbd authored by xinzhedeai's avatar xinzhedeai

add:better + 提示弹窗实体添加

parent 10523982
......@@ -36,13 +36,15 @@ export default {
},
// 其他人员数据...
],
personModelInterval: null,
intervaler: null,
bgEntities: {}, // 所有的key都对应一个实体对象。而人员的实体对应的key不是数字。
};
},
mounted() {
// 组件挂载后初始化地图
this.initCesium();
// 监听窗口大小变化
window.addEventListener("resize", this.handleResize);
},
beforeMount() {
localStg.set("token", 222233);
......@@ -57,152 +59,41 @@ export default {
});
},
beforeDestroy() {
// 清理事件监听
window.removeEventListener("resize", this.handleResize);
// 清理地图资源
if (this.viewer) {
this.viewer.destroy();
this.viewer = null;
}
// 清理点击事件处理器
if (this.clickHandler) {
this.clickHandler.destroy();
this.clickHandler = null;
}
// 组件销毁前清理地图资源
if (this.viewer) {
this.viewer.destroy();
this.viewer = null;
}
// 清理定时器
if (this.intervaler) {
clearInterval(this.intervaler);
}
// 清空实体引用
this.bgEntities = {};
},
methods: {
createPersonModel() {
// 批次号管理(每次定时器触发时生成一个新的批次号)
// var currentBatch = 0;
// const batchMap = {};
if (!this.personModelInterval) {
this.personModelInterval = setInterval(() => {
console.log("开始获取实时数据");
// currentBatch++; // 每次定时器触发,生成新的批次号
if (this.bgEntities) {
for (let key in this.bgEntities) {
if (isNaN(parseFloat(key))) {
// 非数字键名的是人员实体
this.viewer.entities.remove(this.bgEntities[key]);
delete this.bgEntities[key];
}
}
}
// 从API获取最新的人员定位数据
this.personCardList((list) => {
// let perList = list; // 使用全部人员数据
console.log("人员数据", this.personnelList);
// 创建新实体
for (let item of this.personnelList) {
let lng = Number(item.lng);
let lat = Number(item.lat);
let height = Number(item.height);
let position = Cesium.Cartesian3.fromDegrees(lng, lat, height);
console.log(item.perName, position);
// 创建人员标记
let entity = this.viewer.entities.add({
position: position,
label: {
text: item.perName,
font: "16px",
backgroundColor: Cesium.Color.fromCssColorString("#173349"),
showBackground: true,
fillColor: Cesium.Color.YELLOW,
depthTestAgainstTerrain: false, // 禁用地形深度测试
// text: "高区管委",
// font: "16px",
// // scale: 0.5,
// backgroundColor: Cesium.Color.fromCssColorString("#173349"),
// color: Cesium.Color.WHITE,
// showBackground: true,
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0,
// 8000.0
// ),
pixelOffset: new Cesium.Cartesian2(0, -35),
// fillColor: Cesium.Color.WHITE,
// backgroundColor: new Cesium.Color(0.0, 0.486, 0.65, 0.8),
// disableDepthTestDistance: 5,
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
billboard: {
image: "/poi-marker-default.png",
scale: 0.5,
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
// disableDepthTestDistance: 5,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0,
// 8000.0
// ),
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
},
description: `<div><h4>${item.perName}${item.status}</h4></div>`,
fixedFrame: Cesium.Transforms.eastNorthUpToFixedFrame(position),
});
entity.info = item; // 添加 info 属性
// entity.batch = currentBatch; // 标记当前批次
this.bgEntities[item.perName] = entity; // 存储新实体
}
});
}, 10000); // 每10秒刷新一次
}
},
personCardList(fn) {
console.log("人员定位数据", this.personnelList);
// 将笛卡尔坐标转换为经纬度坐标
const cartographic = Cesium.Cartographic.fromCartesian({
x: -2686273.730145489,
y: 4293961.185794622,
z: 3863430.5618300107,
});
const baseLongitude = Cesium.Math.toDegrees(cartographic.longitude);
const baseLatitude = Cesium.Math.toDegrees(cartographic.latitude);
const baseHeight = cartographic.height + 1;
console.log("人员经纬度基准点:", {
longitude: baseLongitude,
latitude: baseLatitude,
height: baseHeight,
});
// 清除现有的人员列表
this.personnelList = [];
// 生成10个不同的经纬度坐标,确保它们之间的距离不超过100米
// 在经纬度上,约0.00001度的变化大约对应1米(赤道附近)
// 为了确保不超过100米,我们使用±0.00005度的随机偏移
const maxOffset = 0.00005;
for (let index = 0; index < 10; index++) {
// 生成随机偏移量,确保每个点都不同但距离不远
const lngOffset = (Math.random() - 0.5) * 2 * maxOffset;
const latOffset = (Math.random() - 0.5) * 2 * maxOffset;
this.personnelList.push({
lng: baseLongitude + lngOffset,
lat: baseLatitude + latOffset,
height: baseHeight, // 高度略有不同,便于区分
perName: "张三" + index,
status: "online", // 在线
avatar: "/static/images/avatars/zhangsan.png", // 头像
});
// 新增:清除实体
clearEntities() {
if (this.viewer && this.bgEntities) {
for (let key in this.bgEntities) {
this.viewer.entities.remove(this.bgEntities[key]);
delete this.bgEntities[key];
}
}
fn(this.personnelList);
},
showPersonInfo(description) {
// 使用 Cesium 的 InfoBox 显示信息
this.viewer.selectedEntity = this.viewer.entities.add({
description: description,
});
this.viewer.infoBox.frame.sandbox =
"allow-same-origin allow-top-navigation allow-pointer-lock allow-popups allow-forms allow-scripts";
this.viewer.infoBox.frame.src = "about:blank";
this.viewer.infoBox.frame.contentDocument.write(description);
this.viewer.infoBox.frame.contentDocument.close();
this.viewer.infoBox.viewModel.showInfo = true;
this.viewer.scene.globe.depthTestAgainstTerrain = true;
},
goTarget(href) {
window.open(href, "_blank");
},
/**
......@@ -223,12 +114,12 @@ export default {
// 配置是否显示各种控件
animation: false, // 动画控件
baseLayerPicker: true, // 底图选择器
fullscreenButton: true, // 全屏按钮
geocoder: true, // 地址搜索
homeButton: true, // 主页按钮
infoBox: true, // 信息框
sceneModePicker: true, // 场景模式选择器
selectionIndicator: true, // 选择指示器
fullscreenButton: false, // 全屏按钮
geocoder: false, // 地址搜索
homeButton: false, // 主页按钮
infoBox: false, // 信息框
sceneModePicker: false, // 场景模式选择器
selectionIndicator: false, // 选择指示器
timeline: false, // 时间线
navigationHelpButton: false, // 导航帮助按钮
navigationInstructionsInitiallyVisible: false,
......@@ -236,16 +127,6 @@ export default {
center: Cesium.Cartesian3.fromDegrees(104.06, 30.67, 10000000),
});
// 设置相机视图
// this.viewer.camera.setView({
// destination: Cesium.Cartesian3.fromDegrees(104.06, 30.67, 10000000), // 经度、纬度、高度
// orientation: {
// heading: Cesium.Math.toRadians(0.0), // 方向
// pitch: Cesium.Math.toRadians(-90.0), // 倾斜角度
// roll: 0.0, // 翻滚角度
// },
// });
this.viewer.scene.camera.setView({
// 视角-环翠
duration: 1,
......@@ -277,6 +158,8 @@ export default {
if (tileset) {
this.tileset = tileset;
this.locateToTileset();
// 添加鼠标点击事件监听器,用于控制人员信息label显示
this.addEntityClickHandler();
}
} catch (error) {
console.error(`加载倾斜摄影模型失败: ${error}`);
......@@ -287,6 +170,7 @@ export default {
console.error("Cesium地图初始化失败:", error);
}
},
/**
* 获取倾斜摄影模型的经纬度并将摄像机视角转向模型上方
*/
......@@ -346,6 +230,8 @@ export default {
duration: 2, // 过渡时间2秒
complete: () => {
console.log("相机已成功定位到模型上方");
// this.createPersonModel(); // 定位后创建人员模型
// 根据当前选择的类型创建相应的模型
this.createPersonModel(); // 定位后创建人员模型
},
});
......@@ -353,6 +239,261 @@ export default {
console.error("定位到模型上方失败:", error);
}
},
personCardList(fn) {
// 将笛卡尔坐标转换为经纬度坐标
const cartographic = Cesium.Cartographic.fromCartesian({
x: -2686273.730145489,
y: 4293961.185794622,
z: 3863430.5618300107,
});
const baseLongitude = Cesium.Math.toDegrees(cartographic.longitude);
const baseLatitude = Cesium.Math.toDegrees(cartographic.latitude);
const baseHeight = cartographic.height + 1;
console.log("人员经纬度基准点:", {
longitude: baseLongitude,
latitude: baseLatitude,
height: baseHeight,
});
// 清除现有的人员列表
this.personnelList = [];
// 生成10个不同的经纬度坐标
const maxOffset = 0.00005;
for (let index = 0; index < 10; index++) {
// 生成随机偏移量
const lngOffset = (Math.random() - 0.5) * 2 * maxOffset;
const latOffset = (Math.random() - 0.5) * 2 * maxOffset;
this.personnelList.push({
lng: baseLongitude + lngOffset,
lat: baseLatitude + latOffset,
height: baseHeight,
perName: "张三" + index,
status: "online", // 在线
avatar: "/static/images/avatars/zhangsan.png", // 头像
});
}
fn(this.personnelList);
},
// 修改:更新点击事件处理器,支持车辆显示
addEntityClickHandler() {
// 创建鼠标事件处理器
this.clickHandler = new Cesium.ScreenSpaceEventHandler(
this.viewer.canvas
);
// 监听鼠标左键点击事件
this.clickHandler.setInputAction((click) => {
// 检测点击位置的实体
const pickedObject = this.viewer.scene.pick(click.position);
// 修复条件判断:检查是否有info属性
if (
Cesium.defined(pickedObject) &&
pickedObject.id &&
pickedObject.id.info
) {
// 获取点击的实体
const entity = pickedObject.id;
const entityInfo = entity.info;
// 如果已有详细信息label,则移除它
if (entity.detailLabel) {
this.viewer.entities.remove(entity.detailLabel);
delete entity.detailLabel;
return;
}
console.log("点击实体了", entityInfo);
// 根据实体类型显示不同的信息
let labelText = "";
// 人员信息
labelText = `${entityInfo.perName}\n状态: ${
entityInfo.status === "online" ? "在线" : "离线"
}\n高度: ${entityInfo.height.toFixed(2)}m`;
// 创建详细信息label
const detailLabel = this.viewer.entities.add({
position: entity.position.getValue(),
label: {
text: labelText,
font: "14px 微软雅黑",
backgroundColor: Cesium.Color.fromCssColorString("#173349"),
showBackground: true,
fillColor: Cesium.Color.WHITE,
pixelOffset: new Cesium.Cartesian2(0, -60),
eyeOffset: new Cesium.Cartesian3(0, 0, -10),
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.TOP,
scaleByDistance: new Cesium.NearFarScalar(1000, 1, 500000, 0.5),
disableDepthTestDistance: Number.POSITIVE_INFINITY, // 确保始终显示在最前面
},
});
// 将详细信息label关联到实体,便于后续管理
entity.detailLabel = detailLabel;
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
},
// 处理窗口大小变化
handleResize() {
// 重新调整Cesium视图大小
if (this.viewer) {
this.viewer.resize();
}
// 重新绘制图表
const chartContainer = document.getElementById("trendChart");
if (chartContainer && chartContainer.firstChild) {
chartContainer.removeChild(chartContainer.firstChild);
this.drawTrendChart();
}
},
// 1. 提取通用实体创建函数
createEntity(item, type) {
const isPerson = type === "person";
const idField = isPerson ? "perName" : "vehicleName";
const labelColor = isPerson ? Cesium.Color.YELLOW : Cesium.Color.CYAN;
const iconPath = isPerson
? "/poi-marker-default.png"
: "/poi-marker-vehicle.png";
let lng = Number(item.lng);
let lat = Number(item.lat);
let height = Number(item.height);
let position = Cesium.Cartesian3.fromDegrees(lng, lat, height);
console.log(item[idField], position);
// 创建实体
let entity = this.viewer.entities.add({
position: position,
label: {
text: item[idField],
font: "16px",
backgroundColor: Cesium.Color.fromCssColorString("#173349"),
showBackground: true,
fillColor: labelColor,
depthTestAgainstTerrain: false,
pixelOffset: new Cesium.Cartesian2(0, -35),
},
billboard: {
image: iconPath,
scale: 0.5,
heightReference: Cesium.HeightReference.CLAMP_TO_3D_TILE,
},
description: `<div><h4>${item[idField]}${item.status}</h4></div>`,
fixedFrame: Cesium.Transforms.eastNorthUpToFixedFrame(position),
});
entity.info = item;
entity.type = type;
this.bgEntities[item[idField]] = entity;
return entity;
},
// 2. 提取实体更新函数
updateEntity(entity, item) {
let position = Cesium.Cartesian3.fromDegrees(
item.lng,
item.lat,
item.height
);
entity.position.setValue(position);
entity.fixedFrame = Cesium.Transforms.eastNorthUpToFixedFrame(position);
},
// 3. 提取批量创建实体的函数
createEntities(entityList, type) {
const isPerson = type === "person";
const idField = isPerson ? "perName" : "vehicleName";
for (let item of entityList) {
this.createEntity(item, type);
}
},
// 4. 提取批量更新实体的函数(增量更新模式)
updateEntities(entityList, type) {
const isPerson = type === "person";
const idField = isPerson ? "perName" : "vehicleName";
for (let item of entityList) {
let entity = this.bgEntities[item[idField]];
if (entity && entity.type === type) {
// 更新现有实体
this.updateEntity(entity, item);
} else {
// 创建新实体
this.createEntity(item, type);
}
}
},
// 5. 提取定时器逻辑为可重用函数
setupEntityUpdateInterval(type, dataGenerator, interval = 10000) {
// 清除现有定时器
if (this.intervaler) {
clearInterval(this.intervaler);
this.intervaler = null;
}
// 设置新的定时器
this.intervaler = setInterval(() => {
console.log(`开始获取实时${type === "person" ? "人员" : "车辆"}数据`);
// 生成或获取最新数据
if (typeof dataGenerator === "function") {
dataGenerator();
}
const entityList =
type === "person" ? this.personnelList : this.vehicleList;
// 更新实体(这里可以选择清除重建或增量更新)
// 方案1:清除所有实体后重建
this.clearEntities();
this.createEntities(entityList, type);
// 方案2:增量更新(推荐,性能更好)
// this.updateEntities(entityList, type);
}, interval);
},
// 修改后的createPersonModel方法
createPersonModel() {
// 清除现有定时器
if (this.intervaler) {
clearInterval(this.intervaler);
this.intervaler = null;
}
// 清除现有实体
this.clearEntities();
// 立即生成并显示人员实体
console.log("立即创建人员实体");
this.personCardList((list) => {
console.log("人员数据", this.personnelList);
this.createEntities(this.personnelList, "person");
});
// 设置定时刷新
this.setupEntityUpdateInterval("person", () => {
this.personCardList(() => {
console.log("人员数据", this.personnelList);
});
});
},
},
};
</script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment