platform.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import { watchEffect, nextTick } from "vue";
  2. import {
  3. fuseModelsLoaded,
  4. scenes,
  5. SceneType,
  6. setting,
  7. caseProject,
  8. } from "@/store";
  9. import { fuseModel } from "./";
  10. import {
  11. initialSDK,
  12. initialed as fuseInitialed,
  13. sdk as fuseSDK,
  14. analysisPose,
  15. analysisPoseInfo,
  16. setPose,
  17. } from "@/sdk";
  18. import { asyncTimeout } from "@/utils";
  19. import { aMapToWgs84 } from "@/utils/coord";
  20. import type { ModelType } from "./";
  21. import { offlinePrev } from "@/api/offline";
  22. import { params } from "@/env";
  23. export async function modelSDKFactory(
  24. type: ModelType,
  25. dom: HTMLDivElement | HTMLIFrameElement
  26. ): Promise<ModelExpose> {
  27. let center: number[] | undefined = undefined;
  28. const lonlatStr = caseProject.value?.latAndLong || "22.364093,113.600356";
  29. // const lonlatStr = caseProject.value?.latAndLong || "22.364093,113.600356";
  30. const lonlat = lonlatStr.split(",").map(Number);
  31. const gcenter = aMapToWgs84({
  32. x: lonlat[1],
  33. y: lonlat[0],
  34. });
  35. center = [gcenter.x, gcenter.y];
  36. if (type === fuseModel) {
  37. if (!fuseInitialed) {
  38. await initialSDK({
  39. laserRoot: offline ? offlinePrev : params.laserRoot,
  40. panoOSSRoot: offline ? offlinePrev : params.panoOSSRoot,
  41. ossRoot: offline ? offlinePrev : params.ossRoot,
  42. laserOSSRoot: offline ? offlinePrev : params.laserOSSRoot,
  43. layout: dom,
  44. scenes: scenes.value,
  45. lonlat: center,
  46. });
  47. }
  48. return exposeFactory(fuseModel);
  49. } else {
  50. const iframe = dom as HTMLIFrameElement;
  51. const win = await new Promise<Window | null>((resolve, reject) => {
  52. const loadedHandler = () => {
  53. resolve(iframe.contentWindow);
  54. cleanup();
  55. };
  56. const errorHandler = (err: any) => {
  57. reject(err);
  58. cleanup();
  59. };
  60. const cleanup = () => {
  61. iframe.removeEventListener("load", loadedHandler);
  62. iframe.removeEventListener("error", errorHandler);
  63. };
  64. iframe.addEventListener("load", loadedHandler);
  65. iframe.addEventListener("error", errorHandler);
  66. });
  67. if (!win) {
  68. throw new Error("场景加载失败");
  69. }
  70. return await exposeFactory(type, win);
  71. }
  72. }
  73. const findObjectAttr = <T extends {}, K extends keyof T>(
  74. data: T,
  75. key: K
  76. ): Promise<T[K]> => {
  77. return new Promise<T[K]>((resolve) => {
  78. const query = () => {
  79. if (key in data) {
  80. resolve(data[key]);
  81. } else {
  82. setTimeout(query, 6);
  83. }
  84. };
  85. query();
  86. });
  87. };
  88. const fuseLoaded = new Promise<void>((resolve) => {
  89. const stop = watchEffect(() => {
  90. if (fuseModelsLoaded.value) {
  91. resolve();
  92. nextTick(() => stop());
  93. }
  94. });
  95. });
  96. export interface ModelExpose {
  97. getView: () => Promise<{ image: Blob; flyData: string }>;
  98. setView: (flyData: string) => void;
  99. }
  100. export async function exposeFactory(
  101. type: ModelType,
  102. win?: any
  103. ): Promise<ModelExpose> {
  104. const sceneType = type === fuseModel ? fuseModel : type.type;
  105. const platforms: {
  106. [key in any]: { getSDK: () => Promise<any>; expose: ModelExpose };
  107. } = {
  108. [fuseModel]: {
  109. getSDK: async () => {
  110. await fuseLoaded;
  111. return fuseSDK;
  112. },
  113. expose: {
  114. async getView() {
  115. const dataURL = await sdk.screenshot(260, 160);
  116. const res = await fetch(dataURL);
  117. const image = await res.blob();
  118. const pose = analysisPose(sdk.getPose());
  119. return {
  120. image,
  121. flyData: JSON.stringify(pose),
  122. };
  123. },
  124. async setView(flyData: string) {
  125. console.error(JSON.parse(flyData));
  126. setPose(JSON.parse(flyData), sdk);
  127. },
  128. },
  129. },
  130. [SceneType.SWKK]: {
  131. getSDK: async () => {
  132. const sdk = await findObjectAttr(win, "__sdk");
  133. if (!sdk.Scene.loaded) {
  134. await new Promise((reoslve) => sdk.Scene.on("loaded", reoslve));
  135. }
  136. return sdk;
  137. },
  138. expose: {
  139. async getView() {
  140. const pose = sdk.Camera.getPose();
  141. const images = await sdk.Camera.screenshot(
  142. [{ width: 260, height: 160, name: "2k" }],
  143. true
  144. );
  145. return {
  146. image: images[0].data,
  147. flyData: JSON.stringify(pose),
  148. };
  149. },
  150. async setView(flyData: string) {
  151. const pose = JSON.parse(flyData);
  152. sdk.Camera.setPose({ dur: 300, ...pose });
  153. },
  154. },
  155. },
  156. [SceneType.SWSS]: {
  157. getSDK: async () => {
  158. await findObjectAttr(win, "laserLoaded");
  159. return await findObjectAttr(win, "__sdk");
  160. },
  161. expose: {
  162. async getView() {
  163. const dataURL = await sdk.scene.screenshot(260, 160);
  164. const res = await fetch(dataURL.dataUrl);
  165. const image = await res.blob();
  166. const pose = await sdk.scene.getPose();
  167. const mode = sdk.customMap.mode;
  168. return {
  169. image,
  170. flyData: JSON.stringify({ pose, mode }),
  171. };
  172. },
  173. async setView(flyData: string) {
  174. const { pose, mode } = JSON.parse(flyData);
  175. sdk.customMap.mode = mode;
  176. sdk.scene.setPose(pose, 300);
  177. },
  178. },
  179. },
  180. };
  181. platforms[SceneType.SWYDSS] = platforms[SceneType.SWSS];
  182. platforms[SceneType.DSFXJ] = platforms[SceneType.SWYDMX] =
  183. platforms[SceneType.SWSSMX] =
  184. platforms[SceneType.SWKJ] =
  185. platforms[SceneType.SWKK];
  186. platforms[SceneType.SWMX] = {
  187. getSDK: async () => findObjectAttr(win, "__sdk"),
  188. expose: platforms[fuseModel].expose,
  189. };
  190. if (!(sceneType in platforms)) {
  191. throw new Error("不支持该类型场景!");
  192. }
  193. const sdk: any = await Promise.race([
  194. asyncTimeout(100000).then(() => Promise.reject(new Error("加载超时"))),
  195. platforms[sceneType].getSDK(),
  196. ]);
  197. return platforms[sceneType].expose;
  198. }