platform.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import { watchEffect, nextTick } from 'vue'
  2. import { fuseModelsLoaded, SceneType } from '@/store'
  3. import { fuseModel } from './'
  4. import { initialSDK, initialed as fuseInitialed, sdk as fuseSDK } from '@/sdk'
  5. import { asyncTimeout } from '@/utils'
  6. import type { ModelType } from './'
  7. export async function modelSDKFactory (
  8. type: ModelType,
  9. dom: HTMLDivElement | HTMLIFrameElement
  10. ): Promise<ModelExpose> {
  11. if (type === fuseModel) {
  12. if (!fuseInitialed) {
  13. await initialSDK({ layout: dom })
  14. }
  15. return exposeFactory(fuseModel)
  16. } else {
  17. const iframe = dom as HTMLIFrameElement
  18. const win = await new Promise<Window | null>((resolve, reject) => {
  19. const loadedHandler = () => {
  20. resolve(iframe.contentWindow)
  21. cleanup()
  22. }
  23. const errorHandler = (err: any) => {
  24. reject(err)
  25. cleanup()
  26. }
  27. const cleanup = () => {
  28. iframe.removeEventListener('load', loadedHandler)
  29. iframe.removeEventListener('error', errorHandler)
  30. }
  31. iframe.addEventListener('load', loadedHandler)
  32. iframe.addEventListener('error', errorHandler)
  33. })
  34. if (!win) {
  35. throw new Error('场景加载失败')
  36. }
  37. return await exposeFactory(type, win)
  38. }
  39. }
  40. const findObjectAttr = <T, K extends keyof T>(data: T, key: K): Promise<T[K]> => {
  41. return new Promise<T[K]>(resolve => {
  42. const query = () => {
  43. if (key in data) {
  44. resolve(data[key])
  45. } else {
  46. setTimeout(query, 6)
  47. }
  48. }
  49. query()
  50. })
  51. }
  52. const fuseLoaded = new Promise<void>(resolve => {
  53. const stop = watchEffect(() => {
  54. if (fuseModelsLoaded.value) {
  55. resolve()
  56. nextTick(() => stop())
  57. }
  58. })
  59. })
  60. export interface ModelExpose {
  61. getView: () => Promise<{ image: Blob, flyData: string }>
  62. setView: (flyData: string) => void
  63. }
  64. export async function exposeFactory(type: ModelType, win?: any): Promise<ModelExpose> {
  65. const sceneType = type === fuseModel ? fuseModel : type.type
  66. const platforms: {[key in any]: {getSDK: () => Promise<any>, expose: ModelExpose}} = {
  67. [fuseModel]: {
  68. getSDK: async () => {
  69. await fuseLoaded
  70. return fuseSDK
  71. },
  72. expose: {
  73. async getView() {
  74. const dataURL = await sdk.screenshot(260, 160)
  75. const res = await fetch(dataURL)
  76. const image = await res.blob()
  77. const pose = sdk.getPose()
  78. return {
  79. image,
  80. flyData: JSON.stringify(pose)
  81. }
  82. },
  83. async setView(flyData: string) {
  84. const pose = JSON.parse(flyData)
  85. sdk.comeTo({ dur: 300, ...pose })
  86. }
  87. }
  88. },
  89. [SceneType.SWKK]: {
  90. getSDK: async () => {
  91. const sdk = await findObjectAttr(win , '__sdk')
  92. if (!sdk.Scene.loaded) {
  93. await new Promise(reoslve => sdk.Scene.on('loaded', reoslve))
  94. }
  95. return sdk
  96. },
  97. expose: {
  98. async getView() {
  99. const pose = sdk.Camera.getPose()
  100. const images = await sdk.Camera.screenshot(
  101. [{ width: 260, height: 160, name: '2k' }],
  102. true
  103. )
  104. return {
  105. image: images[0].data,
  106. flyData: JSON.stringify(pose)
  107. }
  108. },
  109. async setView(flyData: string) {
  110. const pose = JSON.parse(flyData)
  111. console.log('===>?', pose)
  112. sdk.Camera.setPose({ dur: 300, ...pose })
  113. }
  114. }
  115. },
  116. [SceneType.SWSS]: {
  117. getSDK: async () => {
  118. await findObjectAttr(win, 'laserLoaded')
  119. return await findObjectAttr(win, '__sdk')
  120. },
  121. expose: {
  122. async getView() {
  123. const dataURL = await sdk.scene.screenshot(260, 160)
  124. const res = await fetch(dataURL)
  125. const image = await res.blob()
  126. const pose = await sdk.scene.getPose()
  127. const mode = sdk.customMap.mode
  128. return {
  129. image,
  130. flyData: JSON.stringify({ pose, mode })
  131. }
  132. },
  133. async setView(flyData: string) {
  134. const { pose, mode } = JSON.parse(flyData)
  135. sdk.customMap.mode = mode
  136. sdk.scene.setPose(pose, 300)
  137. }
  138. }
  139. }
  140. }
  141. platforms[SceneType.SWKJ] = platforms[SceneType.SWKK]
  142. platforms[SceneType.SWMX] = {
  143. getSDK: async () => findObjectAttr(win , '__sdk'),
  144. expose: platforms[fuseModel].expose
  145. }
  146. if (!(sceneType in platforms)) {
  147. throw new Error('不支持该类型场景!')
  148. }
  149. const sdk: any = await Promise.race([
  150. asyncTimeout(10000)
  151. .then(() => Promise.reject(new Error('加载超时'))),
  152. platforms[sceneType].getSDK()
  153. ])
  154. return platforms[sceneType].expose
  155. }