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. console.log(type, dom)
  12. if (type === fuseModel) {
  13. if (!fuseInitialed) {
  14. await initialSDK({ layout: dom })
  15. }
  16. return exposeFactory(fuseModel)
  17. } else {
  18. const iframe = dom as HTMLIFrameElement
  19. const win = await new Promise<Window | null>((resolve, reject) => {
  20. const loadedHandler = () => {
  21. resolve(iframe.contentWindow)
  22. cleanup()
  23. }
  24. const errorHandler = (err: any) => {
  25. reject(err)
  26. cleanup()
  27. }
  28. const cleanup = () => {
  29. iframe.removeEventListener('load', loadedHandler)
  30. iframe.removeEventListener('error', errorHandler)
  31. }
  32. iframe.addEventListener('load', loadedHandler)
  33. iframe.addEventListener('error', errorHandler)
  34. })
  35. if (!win) {
  36. throw new Error('场景加载失败')
  37. }
  38. return await exposeFactory(type, win)
  39. }
  40. }
  41. const findObjectAttr = <T, K extends keyof T>(data: T, key: K): Promise<T[K]> => {
  42. return new Promise<T[K]>(resolve => {
  43. const query = () => {
  44. if (key in data) {
  45. resolve(data[key])
  46. } else {
  47. setTimeout(query, 6)
  48. }
  49. }
  50. query()
  51. })
  52. }
  53. const fuseLoaded = new Promise<void>(resolve => {
  54. const stop = watchEffect(() => {
  55. if (fuseModelsLoaded.value) {
  56. resolve()
  57. nextTick(() => stop())
  58. }
  59. })
  60. })
  61. export interface ModelExpose {
  62. getView: () => Promise<{ image: Blob, flyData: string }>
  63. setView: (flyData: string) => void
  64. }
  65. export async function exposeFactory(type: ModelType, win?: any): Promise<ModelExpose> {
  66. const sceneType = type === fuseModel ? fuseModel : type.type
  67. const platforms: {[key in any]: {getSDK: () => Promise<any>, expose: ModelExpose}} = {
  68. [fuseModel]: {
  69. getSDK: async () => {
  70. await fuseLoaded
  71. return fuseSDK
  72. },
  73. expose: {
  74. async getView() {
  75. const dataURL = await sdk.screenshot(260, 160)
  76. const res = await fetch(dataURL)
  77. const image = await res.blob()
  78. const pose = sdk.getPose()
  79. return {
  80. image,
  81. flyData: JSON.stringify(pose)
  82. }
  83. },
  84. async setView(flyData: string) {
  85. const pose = JSON.parse(flyData)
  86. sdk.comeTo({ dur: 300, ...pose })
  87. }
  88. }
  89. },
  90. [SceneType.SWKK]: {
  91. getSDK: async () => {
  92. const sdk = await findObjectAttr(win , '__sdk')
  93. if (!sdk.Scene.loaded) {
  94. await new Promise(reoslve => sdk.Scene.on('loaded', reoslve))
  95. }
  96. return sdk
  97. },
  98. expose: {
  99. async getView() {
  100. const pose = sdk.Camera.getPose()
  101. const images = await sdk.Camera.screenshot(
  102. [{ width: 260, height: 160, name: '2k' }],
  103. true
  104. )
  105. return {
  106. image: images[0].data,
  107. flyData: JSON.stringify(pose)
  108. }
  109. },
  110. async setView(flyData: string) {
  111. const pose = JSON.parse(flyData)
  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.SWSSMX] = 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. }