import pako from "pako"; // 解密gzip插件 import { useWebSocket } from "@vueuse/core"; import { useUserStore } from "@/pinia/user"; import pinia from "@/pinia"; import { getFenceList } from "@/request/map"; const userStore = useUserStore(pinia); const pls_ip = userStore.getUserInfo.POST_URL; // const pls_ip = "http://121.22.38.202:8084"; let entityArr = []; let billboardArr = []; const fencesArr = []; const { open, close } = useWebSocket( encodeURI("ws://" + pls_ip.replace("http://", "") + "/netty/test.io?u=1"), { immediate: false, heartbeat: { message: "ping", interval: 5000, pongTimeout: 1000, }, delay: 1000, onMessage: (ws, event) => { const msg = unzip(event.data); const decodedMsg = JSON.parse(decodeURIComponent(msg)); if (decodedMsg.msg === "000") { peoMovement(decodedMsg.data); } if (decodedMsg.msg === "006") { addNewPerson(decodedMsg.data); } }, onDisconnected: () => { if (entityArr) { entityArr.children.forEach((e) => { e.destroy(); }); billboardArr.children.forEach((e) => { e.destroy(); }); entityArr = []; billboardArr = []; } }, } ); export const handleTrajectory = (b) => { if (b) { open(); } else { close(); } }; const addEntity = (id, name, lon, lat, height) => { const obj = new window.CustomCesium.Model(window.$icy, { url: "/src/assets/glb/person_000002_blue.gltf", height: 0, scale: 1, angle: [-90, 0, 0], }); let e; // eslint-disable-next-line prefer-const e = obj.clone(e); const enModule = new window.CustomCesium.Model( window.$icy, { name: "人物", height, id, lon, lat, // 位置 scale: 1, // 大小 angle: [-90, 0, 0], }, e ); // 修改模型方向 第一个参数是航向角 // enModule.updateAngle([-90,20,20]); entityArr.add(enModule); }; const addBillboard = (id, name, lon, lat, height) => { // 创建广告牌 const bulletinBoard = new window.CustomCesium.BulletinBoard(window.$icy); bulletinBoard.loadCanvas(drawCanvas(name), { name: "人物铭牌", id: id + "_name", lon, lat, height: height + 2.05, }); billboardArr.add(bulletinBoard); }; // eslint-disable-next-line no-unused-vars const drawCanvas = (name) => { const canvas = document.createElement("canvas"); const width = 70; const height = 20; canvas.width = width; canvas.height = height; const borderRadius = 5; // 圆角半径 const ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(borderRadius, 0); ctx.lineTo(width - borderRadius, 0); ctx.arcTo(width, 0, width, borderRadius, borderRadius); ctx.lineTo(width, height - borderRadius); ctx.arcTo(width, height, width - borderRadius, height, borderRadius); ctx.lineTo(borderRadius, height); ctx.arcTo(0, height, 0, height - borderRadius, borderRadius); ctx.lineTo(0, borderRadius); ctx.arcTo(0, 0, borderRadius, 0, borderRadius); ctx.closePath(); ctx.fillStyle = "rgba(42, 86, 158, 1)"; ctx.fill(); ctx.fillStyle = "#fff"; ctx.font = "normal 12px 'Microsoft YaHei'"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText(name, width / 2, height / 2); return canvas; }; const addNewPerson = (data) => { data.forEach((item) => { const entity = item.split(","); addEntity(entity[0], entity[5], entity[1], entity[2], entity[4]); addBillboard(entity[0], entity[5], entity[1], entity[2], entity[4]); }); }; const unzip = (b64Data) => { let strData = atob(b64Data); const charData = strData.split("").map(function (x) { return x.charCodeAt(0); }); const binData = new Uint8Array(charData); const data = pako.inflate(binData); strData = String.fromCharCode.apply(null, new Uint16Array(data)); return strData; }; /** * moveData 接收webscoket人物移动数据 * entityArr 接收人物模型分组 * billboardArr 接收人物铭牌分组 */ function peoMovement(moveData) { const map = new Map(); moveData.forEach((i, n) => { map.set(i.split(",")[0], n); if (!entityArr || !entityArr.children) { entityArr = new window.CustomCesium.GroupModel("人物模型"); billboardArr = new window.CustomCesium.GroupModel("人物姓名"); const entity = i.split(","); addEntity(entity[0], entity[8], entity[1], entity[2], entity[4]); addBillboard(entity[0], entity[8], entity[1], entity[2], entity[4]); } entityArr.children.forEach((b, m) => { if (!b.entity) { const entity = i.split(","); addEntity(entity[0], entity[8], entity[1], entity[2], entity[4]); addBillboard(entity[0], entity[8], entity[1], entity[2], entity[4]); return; } const index = map.get(b.entity._id); const item = moveData[index]; if (index !== undefined) { const itData = item.split(","); // itData下标:0=【卡号】,(1,2,4)=【lon,lat,alt】,3=【人物朝向角度】,5=【工号】,6=【当前楼层】 if (itData[4] != null && itData.length >= 6) { b.updateAngle([itData[3], 0, 0]); // 改变人物朝向 b.animationMove( itData[1], itData[2], Number(itData[4]), 2000, () => {} ); // 人物平滑移动 billboardArr.children[m].animationMove( itData[1], itData[2], Number(Number(itData[4]) + 2.05), 2000 ); // 人物铭牌平滑移动 } else { console.log(`人物移动数据错误,错误参数:'${item}'`); } } else { const entity = i.split(","); addEntity(entity[0], entity[8], entity[1], entity[2], entity[4]); addBillboard(entity[0], entity[8], entity[1], entity[2], entity[4]); } }); }); } export const handleFence = async (b) => { if (b) { const { data } = await getFenceList(); const fences = data.rows; fences.forEach((fence) => { if (fence.list.length > 0) { const enclosure = new window.CustomCesium.Enclosure(window.$icy); enclosure.showDataSource( fence.list, // 数据 30, // 高度 "yellow" // 颜色默认黄色 ); fencesArr.push(enclosure); } }); } else { if (fencesArr) { fencesArr.forEach((fence) => { fence.clear(); fence.destroy(); }); } } };