import { watchEffect, nextTick } from "vue"; import { fuseModelsLoaded, scenes, SceneType, setting, caseProject, } from "@/store"; import { fuseModel } from "./"; import { initialSDK, initialed as fuseInitialed, sdk as fuseSDK, analysisPose, analysisPoseInfo, setPose, } from "@/sdk"; import { asyncTimeout } from "@/utils"; import { aMapToWgs84 } from "@/utils/coord"; import type { ModelType } from "./"; import { offlinePrev } from "@/api/offline"; export async function modelSDKFactory( type: ModelType, dom: HTMLDivElement | HTMLIFrameElement ): Promise { let center: number[] | undefined = undefined; if (caseProject.value) { const lonlatStr = caseProject.value?.latAndLong || "22.364093,113.600356"; const lonlat = lonlatStr.split(",").map(Number); const gcenter = aMapToWgs84({ x: lonlat[1], y: lonlat[0], }); center = [gcenter.x, gcenter.y]; } if (type === fuseModel) { if (!fuseInitialed) { await initialSDK({ laserRoot: offline ? offlinePrev : import.meta.env.VITE_LASER_HOST, panoOSSRoot: offline ? offlinePrev : import.meta.env.VITE_PANO_OSS, laserOSSRoot: offline ? offlinePrev : import.meta.env.VITE_LASER_OSS, layout: dom, scenes: scenes.value, lonlat: center, }); } return exposeFactory(fuseModel); } else { const iframe = dom as HTMLIFrameElement; const win = await new Promise((resolve, reject) => { const loadedHandler = () => { resolve(iframe.contentWindow); cleanup(); }; const errorHandler = (err: any) => { reject(err); cleanup(); }; const cleanup = () => { iframe.removeEventListener("load", loadedHandler); iframe.removeEventListener("error", errorHandler); }; iframe.addEventListener("load", loadedHandler); iframe.addEventListener("error", errorHandler); }); if (!win) { throw new Error("场景加载失败"); } return await exposeFactory(type, win); } } const findObjectAttr = ( data: T, key: K ): Promise => { return new Promise((resolve) => { const query = () => { if (key in data) { resolve(data[key]); } else { setTimeout(query, 6); } }; query(); }); }; const fuseLoaded = new Promise((resolve) => { const stop = watchEffect(() => { if (fuseModelsLoaded.value) { resolve(); nextTick(() => stop()); } }); }); export interface ModelExpose { getView: () => Promise<{ image: Blob; flyData: string }>; setView: (flyData: string) => void; } export async function exposeFactory( type: ModelType, win?: any ): Promise { const sceneType = type === fuseModel ? fuseModel : type.type; const platforms: { [key in any]: { getSDK: () => Promise; expose: ModelExpose }; } = { [fuseModel]: { getSDK: async () => { await fuseLoaded; return fuseSDK; }, expose: { async getView() { const dataURL = await sdk.screenshot(260, 160); const res = await fetch(dataURL); const image = await res.blob(); const pose = analysisPose(sdk.getPose()); return { image, flyData: JSON.stringify(pose), }; }, async setView(flyData: string) { console.error(JSON.parse(flyData)); setPose(JSON.parse(flyData), sdk); }, }, }, [SceneType.SWKK]: { getSDK: async () => { const sdk = await findObjectAttr(win, "__sdk"); if (!sdk.Scene.loaded) { await new Promise((reoslve) => sdk.Scene.on("loaded", reoslve)); } return sdk; }, expose: { async getView() { const pose = sdk.Camera.getPose(); const images = await sdk.Camera.screenshot( [{ width: 260, height: 160, name: "2k" }], true ); return { image: images[0].data, flyData: JSON.stringify(pose), }; }, async setView(flyData: string) { const pose = JSON.parse(flyData); sdk.Camera.setPose({ dur: 300, ...pose }); }, }, }, [SceneType.SWSS]: { getSDK: async () => { await findObjectAttr(win, "laserLoaded"); return await findObjectAttr(win, "__sdk"); }, expose: { async getView() { const dataURL = await sdk.scene.screenshot(260, 160); const res = await fetch(dataURL.dataUrl); const image = await res.blob(); const pose = await sdk.scene.getPose(); const mode = sdk.customMap.mode; return { image, flyData: JSON.stringify({ pose, mode }), }; }, async setView(flyData: string) { const { pose, mode } = JSON.parse(flyData); sdk.customMap.mode = mode; sdk.scene.setPose(pose, 300); }, }, }, }; platforms[SceneType.SWYDSS] = platforms[SceneType.SWSS]; platforms[SceneType.SWYDMX] = platforms[SceneType.SWSSMX] = platforms[SceneType.SWKJ] = platforms[SceneType.SWKK]; platforms[SceneType.SWMX] = { getSDK: async () => findObjectAttr(win, "__sdk"), expose: platforms[fuseModel].expose, }; if (!(sceneType in platforms)) { throw new Error("不支持该类型场景!"); } const sdk: any = await Promise.race([ asyncTimeout(100000).then(() => Promise.reject(new Error("加载超时"))), platforms[sceneType].getSDK(), ]); return platforms[sceneType].expose; }