@zenvor/view360 4.0.0-beta.7-fork.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +88 -0
  3. package/css/base.css +19 -0
  4. package/css/base.min.css +1 -0
  5. package/css/control-bar.css +329 -0
  6. package/css/control-bar.min.css +1 -0
  7. package/css/helper.css +51 -0
  8. package/css/helper.min.css +1 -0
  9. package/css/hotspot.css +21 -0
  10. package/css/hotspot.min.css +1 -0
  11. package/css/loading-spinner.css +37 -0
  12. package/css/loading-spinner.min.css +1 -0
  13. package/css/variable.css +1 -0
  14. package/css/variable.min.css +0 -0
  15. package/css/view360.css +468 -0
  16. package/css/view360.min.css +1 -0
  17. package/css/vr.css +8 -0
  18. package/css/vr.min.css +1 -0
  19. package/declaration/View360.d.ts +150 -0
  20. package/declaration/cfc/const.d.ts +1 -0
  21. package/declaration/cfc/index.d.ts +4 -0
  22. package/declaration/cfc/utils.d.ts +1 -0
  23. package/declaration/cfc/withMethods.d.ts +2 -0
  24. package/declaration/const/browser.d.ts +71 -0
  25. package/declaration/const/error.d.ts +47 -0
  26. package/declaration/const/external.d.ts +33 -0
  27. package/declaration/const/internal.d.ts +34 -0
  28. package/declaration/control/CameraControl.d.ts +10 -0
  29. package/declaration/control/GyroControl.d.ts +30 -0
  30. package/declaration/control/PanoControl.d.ts +58 -0
  31. package/declaration/control/RotateControl.d.ts +75 -0
  32. package/declaration/control/ZoomControl.d.ts +45 -0
  33. package/declaration/control/index.d.ts +7 -0
  34. package/declaration/control/input/GyroInput.d.ts +46 -0
  35. package/declaration/control/input/KeyboardInput.d.ts +21 -0
  36. package/declaration/control/input/MouseInput.d.ts +16 -0
  37. package/declaration/control/input/PinchInput.d.ts +14 -0
  38. package/declaration/control/input/PointerInput.d.ts +18 -0
  39. package/declaration/control/input/TouchInput.d.ts +21 -0
  40. package/declaration/control/input/WheelInput.d.ts +16 -0
  41. package/declaration/core/AutoResizer.d.ts +13 -0
  42. package/declaration/core/Autoplay.d.ts +54 -0
  43. package/declaration/core/Camera.d.ts +88 -0
  44. package/declaration/core/CameraAnimation.d.ts +25 -0
  45. package/declaration/core/CameraPath.d.ts +55 -0
  46. package/declaration/core/CubeTexturePainter.d.ts +16 -0
  47. package/declaration/core/FrameAnimator.d.ts +13 -0
  48. package/declaration/core/Motion.d.ts +39 -0
  49. package/declaration/core/Object3D.d.ts +21 -0
  50. package/declaration/core/ShaderProgram.d.ts +10 -0
  51. package/declaration/core/TextureLoader.d.ts +26 -0
  52. package/declaration/core/TriangleMesh.d.ts +20 -0
  53. package/declaration/core/VertexArrayObject.d.ts +14 -0
  54. package/declaration/core/VertexData.d.ts +8 -0
  55. package/declaration/core/View360Error.d.ts +5 -0
  56. package/declaration/core/WebGLContext.d.ts +74 -0
  57. package/declaration/core/WebGLRenderer.d.ts +26 -0
  58. package/declaration/core/XRManager.d.ts +33 -0
  59. package/declaration/core/index.d.ts +12 -0
  60. package/declaration/geometry/CubeGeometry.d.ts +9 -0
  61. package/declaration/geometry/CylinderGeometry.d.ts +5 -0
  62. package/declaration/geometry/Geometry.d.ts +8 -0
  63. package/declaration/geometry/PlaneGeometry.d.ts +5 -0
  64. package/declaration/geometry/SphereGeometry.d.ts +5 -0
  65. package/declaration/hotspot/Hotspot.d.ts +7 -0
  66. package/declaration/hotspot/HotspotRenderer.d.ts +17 -0
  67. package/declaration/hotspot/index.d.ts +4 -0
  68. package/declaration/index.cjs.d.ts +3 -0
  69. package/declaration/index.d.ts +11 -0
  70. package/declaration/index.umd.d.ts +2 -0
  71. package/declaration/plugin/ControlBar/AutoHide.d.ts +42 -0
  72. package/declaration/plugin/ControlBar/ControlBar.d.ts +113 -0
  73. package/declaration/plugin/ControlBar/ControlBarItem.d.ts +15 -0
  74. package/declaration/plugin/ControlBar/FullscreenButton.d.ts +19 -0
  75. package/declaration/plugin/ControlBar/GyroButton.d.ts +14 -0
  76. package/declaration/plugin/ControlBar/PieView.d.ts +26 -0
  77. package/declaration/plugin/ControlBar/PlayButton.d.ts +16 -0
  78. package/declaration/plugin/ControlBar/ProgressBar.d.ts +23 -0
  79. package/declaration/plugin/ControlBar/RangeControl.d.ts +27 -0
  80. package/declaration/plugin/ControlBar/VRButton.d.ts +12 -0
  81. package/declaration/plugin/ControlBar/VideoControl.d.ts +11 -0
  82. package/declaration/plugin/ControlBar/VideoTime.d.ts +17 -0
  83. package/declaration/plugin/ControlBar/VolumeControl.d.ts +23 -0
  84. package/declaration/plugin/ControlBar/const.d.ts +41 -0
  85. package/declaration/plugin/ControlBar/index.d.ts +11 -0
  86. package/declaration/plugin/LoadingSpinner/LoadingSpinner.d.ts +22 -0
  87. package/declaration/plugin/View360Plugin.d.ts +6 -0
  88. package/declaration/plugin/index.d.ts +5 -0
  89. package/declaration/projection/CorrectionPass.d.ts +26 -0
  90. package/declaration/projection/CubemapProjection.d.ts +19 -0
  91. package/declaration/projection/CubestripProjection.d.ts +18 -0
  92. package/declaration/projection/CylindricalProjection.d.ts +22 -0
  93. package/declaration/projection/EquiangularProjection.d.ts +13 -0
  94. package/declaration/projection/EquirectProjection.d.ts +15 -0
  95. package/declaration/projection/LittlePlanetProjection.d.ts +21 -0
  96. package/declaration/projection/Projection.d.ts +19 -0
  97. package/declaration/projection/StereoEquiProjection.d.ts +25 -0
  98. package/declaration/projection/WideAngleCorrectionProjection.d.ts +27 -0
  99. package/declaration/projection/WideAngleRealtimeProjection.d.ts +50 -0
  100. package/declaration/projection/index.d.ts +12 -0
  101. package/declaration/texture/Texture.d.ts +18 -0
  102. package/declaration/texture/Texture2D.d.ts +11 -0
  103. package/declaration/texture/TextureCube.d.ts +12 -0
  104. package/declaration/texture/TextureRenderTarget.d.ts +8 -0
  105. package/declaration/texture/TextureVideo.d.ts +11 -0
  106. package/declaration/type/events.d.ts +74 -0
  107. package/declaration/type/external.d.ts +13 -0
  108. package/declaration/type/internal.d.ts +47 -0
  109. package/declaration/type/utils.d.ts +11 -0
  110. package/declaration/uniform/Uniform.d.ts +7 -0
  111. package/declaration/uniform/UniformBoolean.d.ts +7 -0
  112. package/declaration/uniform/UniformCanvasCube.d.ts +12 -0
  113. package/declaration/uniform/UniformFloat.d.ts +7 -0
  114. package/declaration/uniform/UniformInt.d.ts +7 -0
  115. package/declaration/uniform/UniformMatrix.d.ts +8 -0
  116. package/declaration/uniform/UniformTexture2D.d.ts +11 -0
  117. package/declaration/uniform/UniformTextureCube.d.ts +12 -0
  118. package/declaration/uniform/UniformTextureRenderTarget.d.ts +11 -0
  119. package/declaration/uniform/UniformVec2.d.ts +7 -0
  120. package/declaration/uniform/UniformVec3.d.ts +7 -0
  121. package/declaration/uniform/UniformVector4Array.d.ts +7 -0
  122. package/declaration/utils.d.ts +25 -0
  123. package/dist/view360.cjs.js +9392 -0
  124. package/dist/view360.cjs.js.map +1 -0
  125. package/dist/view360.esm.js +9274 -0
  126. package/dist/view360.esm.js.map +1 -0
  127. package/dist/view360.js +9350 -0
  128. package/dist/view360.js.map +1 -0
  129. package/dist/view360.min.js +2 -0
  130. package/dist/view360.min.js.map +1 -0
  131. package/dist/view360.pkgd.js +48537 -0
  132. package/dist/view360.pkgd.js.map +1 -0
  133. package/dist/view360.pkgd.min.js +16 -0
  134. package/dist/view360.pkgd.min.js.map +1 -0
  135. package/package.json +110 -0
  136. package/sass/base.sass +17 -0
  137. package/sass/control-bar.sass +284 -0
  138. package/sass/helper.sass +51 -0
  139. package/sass/hotspot.sass +20 -0
  140. package/sass/loading-spinner.sass +34 -0
  141. package/sass/variable.sass +2 -0
  142. package/sass/view360.sass +6 -0
  143. package/sass/vr.sass +10 -0
  144. package/src/View360.ts +1220 -0
  145. package/src/cfc/const.ts +15 -0
  146. package/src/cfc/index.ts +8 -0
  147. package/src/cfc/utils.ts +12 -0
  148. package/src/cfc/withMethods.ts +40 -0
  149. package/src/const/browser.ts +109 -0
  150. package/src/const/error.ts +83 -0
  151. package/src/const/external.ts +77 -0
  152. package/src/const/internal.ts +53 -0
  153. package/src/control/CameraControl.ts +53 -0
  154. package/src/control/GyroControl.ts +225 -0
  155. package/src/control/PanoControl.ts +434 -0
  156. package/src/control/RotateControl.ts +411 -0
  157. package/src/control/ZoomControl.ts +254 -0
  158. package/src/control/index.ts +24 -0
  159. package/src/control/input/GyroInput.ts +315 -0
  160. package/src/control/input/KeyboardInput.ts +151 -0
  161. package/src/control/input/MouseInput.ts +102 -0
  162. package/src/control/input/PinchInput.ts +101 -0
  163. package/src/control/input/PointerInput.ts +118 -0
  164. package/src/control/input/TouchInput.ts +138 -0
  165. package/src/control/input/WheelInput.ts +89 -0
  166. package/src/core/AutoResizer.ts +92 -0
  167. package/src/core/Autoplay.ts +326 -0
  168. package/src/core/Camera.ts +616 -0
  169. package/src/core/CameraAnimation.ts +110 -0
  170. package/src/core/CameraPath.ts +454 -0
  171. package/src/core/CubeTexturePainter.ts +95 -0
  172. package/src/core/FrameAnimator.ts +69 -0
  173. package/src/core/Motion.ts +205 -0
  174. package/src/core/Object3D.ts +81 -0
  175. package/src/core/ShaderProgram.ts +21 -0
  176. package/src/core/TextureLoader.ts +303 -0
  177. package/src/core/TriangleMesh.ts +54 -0
  178. package/src/core/VertexArrayObject.ts +29 -0
  179. package/src/core/VertexData.ts +23 -0
  180. package/src/core/View360Error.ts +35 -0
  181. package/src/core/WebGLContext.ts +558 -0
  182. package/src/core/WebGLRenderer.ts +205 -0
  183. package/src/core/XRManager.ts +193 -0
  184. package/src/core/index.ts +35 -0
  185. package/src/geometry/CubeGeometry.ts +121 -0
  186. package/src/geometry/CylinderGeometry.ts +49 -0
  187. package/src/geometry/Geometry.ts +23 -0
  188. package/src/geometry/PlaneGeometry.ts +36 -0
  189. package/src/geometry/SphereGeometry.ts +55 -0
  190. package/src/hotspot/Hotspot.ts +32 -0
  191. package/src/hotspot/HotspotRenderer.ts +155 -0
  192. package/src/hotspot/index.ts +11 -0
  193. package/src/index.cjs.ts +13 -0
  194. package/src/index.ts +21 -0
  195. package/src/index.umd.ts +10 -0
  196. package/src/plugin/ControlBar/AutoHide.ts +246 -0
  197. package/src/plugin/ControlBar/ControlBar.ts +564 -0
  198. package/src/plugin/ControlBar/ControlBarItem.ts +84 -0
  199. package/src/plugin/ControlBar/FullscreenButton.ts +145 -0
  200. package/src/plugin/ControlBar/GyroButton.ts +124 -0
  201. package/src/plugin/ControlBar/PieView.ts +195 -0
  202. package/src/plugin/ControlBar/PlayButton.ts +130 -0
  203. package/src/plugin/ControlBar/ProgressBar.ts +175 -0
  204. package/src/plugin/ControlBar/RangeControl.ts +165 -0
  205. package/src/plugin/ControlBar/VRButton.ts +78 -0
  206. package/src/plugin/ControlBar/VideoControl.ts +79 -0
  207. package/src/plugin/ControlBar/VideoTime.ts +120 -0
  208. package/src/plugin/ControlBar/VolumeControl.ts +220 -0
  209. package/src/plugin/ControlBar/const.ts +72 -0
  210. package/src/plugin/ControlBar/index.ts +31 -0
  211. package/src/plugin/LoadingSpinner/LoadingSpinner.ts +116 -0
  212. package/src/plugin/View360Plugin.ts +30 -0
  213. package/src/plugin/index.ts +16 -0
  214. package/src/projection/CorrectionPass.ts +161 -0
  215. package/src/projection/CubemapProjection.ts +92 -0
  216. package/src/projection/CubestripProjection.ts +85 -0
  217. package/src/projection/CylindricalProjection.ts +123 -0
  218. package/src/projection/EquiangularProjection.ts +52 -0
  219. package/src/projection/EquirectProjection.ts +56 -0
  220. package/src/projection/LittlePlanetProjection.ts +82 -0
  221. package/src/projection/Projection.ts +103 -0
  222. package/src/projection/StereoEquiProjection.ts +104 -0
  223. package/src/projection/WideAngleCorrectionProjection.ts +307 -0
  224. package/src/projection/WideAngleRealtimeProjection.ts +653 -0
  225. package/src/projection/index.ts +36 -0
  226. package/src/shader/common.frag +7 -0
  227. package/src/shader/common.vert +12 -0
  228. package/src/shader/correction.frag +110 -0
  229. package/src/shader/cube.frag +8 -0
  230. package/src/shader/cube.vert +12 -0
  231. package/src/shader/eac.frag +40 -0
  232. package/src/shader/fullscreen.vert +7 -0
  233. package/src/shader/little-planet.frag +47 -0
  234. package/src/shader/little-planet.vert +12 -0
  235. package/src/shader/stereoequi.vert +15 -0
  236. package/src/shader/wideangle_realtime.frag +109 -0
  237. package/src/shader/wideangle_realtime.vert +17 -0
  238. package/src/shim.d.ts +9 -0
  239. package/src/texture/Texture.ts +47 -0
  240. package/src/texture/Texture2D.ts +34 -0
  241. package/src/texture/TextureCube.ts +36 -0
  242. package/src/texture/TextureRenderTarget.ts +33 -0
  243. package/src/texture/TextureVideo.ts +56 -0
  244. package/src/type/events.ts +389 -0
  245. package/src/type/external.ts +78 -0
  246. package/src/type/internal.ts +54 -0
  247. package/src/type/utils.ts +27 -0
  248. package/src/types/hls.d.ts +78 -0
  249. package/src/uniform/Uniform.ts +20 -0
  250. package/src/uniform/UniformBoolean.ts +23 -0
  251. package/src/uniform/UniformCanvasCube.ts +44 -0
  252. package/src/uniform/UniformFloat.ts +23 -0
  253. package/src/uniform/UniformInt.ts +25 -0
  254. package/src/uniform/UniformMatrix.ts +24 -0
  255. package/src/uniform/UniformTexture2D.ts +46 -0
  256. package/src/uniform/UniformTextureCube.ts +51 -0
  257. package/src/uniform/UniformTextureRenderTarget.ts +55 -0
  258. package/src/uniform/UniformVec2.ts +25 -0
  259. package/src/uniform/UniformVec3.ts +25 -0
  260. package/src/uniform/UniformVector4Array.ts +23 -0
  261. package/src/utils.ts +217 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view360.pkgd.min.js","sources":["../src/core/View360Error.ts","../src/const/error.ts","../src/const/browser.ts","../src/const/external.ts","../src/const/internal.ts","../src/utils.ts","../src/core/Motion.ts","../src/core/CameraAnimation.ts","../src/core/Camera.ts","../src/control/input/MouseInput.ts","../src/control/input/TouchInput.ts","../src/control/input/KeyboardInput.ts","../src/control/RotateControl.ts","../src/control/input/WheelInput.ts","../src/control/input/PinchInput.ts","../src/control/ZoomControl.ts","../src/control/input/GyroInput.ts","../src/control/GyroControl.ts","../src/control/PanoControl.ts","../src/texture/Texture.ts","../src/texture/Texture2D.ts","../src/texture/TextureVideo.ts","../src/texture/TextureCube.ts","../src/core/TextureLoader.ts","../src/core/FrameAnimator.ts","../src/core/AutoResizer.ts","../src/core/Autoplay.ts","../src/core/CameraPath.ts","../src/core/XRManager.ts","../src/hotspot/Hotspot.ts","../src/hotspot/HotspotRenderer.ts","../src/core/VertexArrayObject.ts","../src/core/WebGLContext.ts","../src/core/WebGLRenderer.ts","../src/View360.ts","../src/core/Object3D.ts","../src/plugin/LoadingSpinner/LoadingSpinner.ts","../src/plugin/ControlBar/ControlBarItem.ts","../src/plugin/ControlBar/const.ts","../src/plugin/ControlBar/RangeControl.ts","../src/plugin/ControlBar/ProgressBar.ts","../src/plugin/ControlBar/PlayButton.ts","../src/plugin/ControlBar/VolumeControl.ts","../src/plugin/ControlBar/FullscreenButton.ts","../src/plugin/ControlBar/VideoTime.ts","../src/plugin/ControlBar/PieView.ts","../src/plugin/ControlBar/VRButton.ts","../src/plugin/ControlBar/GyroButton.ts","../src/plugin/ControlBar/AutoHide.ts","../src/plugin/ControlBar/VideoControl.ts","../src/plugin/ControlBar/ControlBar.ts","../src/projection/Projection.ts","../src/uniform/Uniform.ts","../src/uniform/UniformTextureCube.ts","../src/core/CubeTexturePainter.ts","../src/uniform/UniformCanvasCube.ts","../src/core/TriangleMesh.ts","../src/core/ShaderProgram.ts","../src/core/VertexData.ts","../src/geometry/Geometry.ts","../src/geometry/CubeGeometry.ts","../src/uniform/UniformTexture2D.ts","../src/geometry/CylinderGeometry.ts","../src/geometry/SphereGeometry.ts","../src/uniform/UniformFloat.ts","../src/geometry/PlaneGeometry.ts","../src/uniform/UniformVector4Array.ts","../src/projection/StereoEquiProjection.ts","../src/texture/TextureRenderTarget.ts","../src/projection/CorrectionPass.ts","../src/uniform/UniformTextureRenderTarget.ts","../src/uniform/UniformInt.ts","../src/uniform/UniformVec2.ts","../src/uniform/UniformVec3.ts","../src/projection/WideAngleRealtimeProjection.ts","../src/projection/CubemapProjection.ts","../src/projection/CubestripProjection.ts","../src/projection/CylindricalProjection.ts","../src/projection/EquiangularProjection.ts","../src/projection/EquirectProjection.ts","../src/projection/LittlePlanetProjection.ts","../src/projection/WideAngleCorrectionProjection.ts","../src/cfc/utils.ts","../src/cfc/const.ts","../src/cfc/withMethods.ts","../src/index.umd.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\n\n/**\n * Error thrown by {@link View360}\n * @ko {@link View360}이 발생시킨 에러\n * @since 4.0.0\n */\nclass View360Error extends Error {\n /**\n * Error code\n * @ko 에러 코드\n * @see ERROR_CODES\n */\n public code: number;\n\n /**\n * Create new instance of View360Error\n * @ko View360Error의 인스턴스를 생성합니다.\n * @param message - Error message {@ko 에러 메시지}\n * @param code - Error code {@ko 에러 코드}\n */\n public constructor(message: string, code: number) {\n super(message);\n\n Object.setPrototypeOf(this, View360Error.prototype);\n\n this.name = \"View360Error\";\n this.code = code;\n }\n}\n\nexport default View360Error;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\n\n/**\n * Error codes of {@link View360Error}\n * @ko {@link View360Error}가 가질 수 있는 에러 코드 값들\n * @since 4.0.0\n */\nexport const ERROR_CODES = {\n /**\n * The given value's type is not expected\n * @ko 주어진 값의 타입이 잘못되었을 경우\n * @since 4.0.0\n */\n WRONG_TYPE: 0,\n /**\n * The given value is not a supported option\n * @ko 잘못된 옵션을 받았을 경우\n * @since 4.0.0\n */\n WRONG_OPTION: 1,\n /**\n * The element with given CSS selector does not exist\n * @ko 주어진 CSS 셀렉터로 엘리먼트를 찾지 못했을 경우\n * @since 4.0.0\n */\n ELEMENT_NOT_FOUND: 2,\n /**\n * Couldn't find canvas element inside the given container element.\n * @ko 컨테이너 엘리먼트 내부에서 캔버스 엘리먼트를 찾지 못했을 경우\n * @since 4.0.0\n */\n CANVAS_NOT_FOUND: 3,\n /**\n * The browser does not support WebGL\n * @ko 브라우저가 WebGL을 지원하지 않는 경우\n * @since 4.0.0\n */\n WEBGL_NOT_SUPPORTED: 4,\n /**\n * Failed creating canvas 2D context\n * @ko 캔버스 2D 컨텍스트를 생성하지 못한 경우\n * @since 4.0.0\n */\n FAILED_CREATE_CONTEXT_2D: 5,\n /**\n * `init()` is called before setting {@link View360Options#projection}\n * @ko {@link View360Options#projection}을 설정하기 전에 `init()`이 호출된 경우\n * @since 4.0.0\n */\n PROVIDE_PROJECTION_FIRST: 6,\n /**\n * Failed linking WebGL program. Only can be thrown when {@link View360Options#debug} is `true`.\n * @ko WebGL 프로그램 링크에 실패한 경우. {@link View360Options#debug}를 `true`로 설정한 경우에만 발생할 수 있습니다.\n * @since 4.0.0\n */\n FAILED_LINKING_PROGRAM: 7,\n /**\n * Arguments are not sufficient for the given property.\n * @ko 프로퍼티에 값이 충분히 주어지지 않았을 때\n * @since 4.0.0\n */\n INSUFFICIENT_ARGS: 8\n} as const;\n\nexport const MESSAGES = {\n WRONG_TYPE: (val: any, types: string[]) => `${typeof val} is not a ${types.map(type => `\"${type}\"`).join(\" or \")}.`,\n WRONG_OPTION: (val: any, optionName: string) => `Bad option: given \"${val}\" for option \"${optionName}\".`,\n ELEMENT_NOT_FOUND: (query: string) => `Element with selector \"${query}\" not found.`,\n CANVAS_NOT_FOUND: \"The canvas element was not found inside the given root element.\",\n WEBGL_NOT_SUPPORTED: \"WebGL is not supported on this browser.\",\n FAILED_CREATE_CONTEXT_2D: \"Failed to create canvas 2D context\",\n PROVIDE_PROJECTION_FIRST: \"\\\"projection\\\" should be provided before initialization.\",\n FAILED_LINKING_PROGRAM: (msg: string | null, shaderLog: string | null) => `Failed linking WebGL program - \"${msg}\\nShader compile Log: ${shaderLog}`,\n INSUFFICIENT_ARGS: (val: any, name: string) => `Insufficient arguments: given \"${val}\" for \"${name}\".`\n};\n\nexport default {\n CODES: ERROR_CODES,\n MESSAGES\n};\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nexport const EVENTS = {\n MOUSE_DOWN: \"mousedown\",\n MOUSE_MOVE: \"mousemove\",\n MOUSE_UP: \"mouseup\",\n TOUCH_START: \"touchstart\",\n TOUCH_MOVE: \"touchmove\",\n TOUCH_END: \"touchend\",\n WHEEL: \"wheel\",\n RESIZE: \"resize\",\n CONTEXT_MENU: \"contextmenu\",\n MOUSE_ENTER: \"mouseenter\",\n MOUSE_LEAVE: \"mouseleave\",\n POINTER_DOWN: \"pointerdown\",\n POINTER_MOVE: \"pointermove\",\n POINTER_UP: \"pointerup\",\n POINTER_CANCEL: \"pointercancel\",\n POINTER_ENTER: \"pointerenter\",\n POINTER_LEAVE: \"pointerleave\",\n KEY_DOWN: \"keydown\",\n KEY_UP: \"keyup\",\n LOAD: \"load\",\n ERROR: \"error\",\n CLICK: \"click\",\n DOUBLE_CLICK: \"dblclick\",\n CONTEXT_CREATE_ERROR: \"webglcontextcreationerror\",\n CONTEXT_LOST: \"webglcontextlost\",\n CONTEXT_RESTORED: \"webglcontextrestored\",\n DEVICE_ORIENTATION: \"deviceorientation\",\n DEVICE_MOTION: \"devicemotion\",\n ORIENTATION_CHANGE: \"orientationchange\",\n VIDEO_PLAY: \"play\",\n VIDEO_PAUSE: \"pause\",\n VIDEO_LOADED_DATA: \"loadeddata\",\n VIDEO_VOLUME_CHANGE: \"volumechange\",\n VIDEO_TIME_UPDATE: \"timeupdate\",\n VIDEO_DURATION_CHANGE: \"durationchange\",\n VIDEO_CAN_PLAYTHROUGH: \"canplaythrough\",\n TRANSITION_END: \"transitionend\",\n XR_END: \"end\"\n} as const;\n\nexport const EL_DIV = \"div\";\nexport const EL_BUTTON = \"button\";\n\n// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent.button\nexport enum MOUSE_BUTTON {\n LEFT,\n MIDDLE,\n RIGHT\n}\n\nexport const CURSOR = {\n GRAB: \"grab\",\n GRABBING: \"grabbing\",\n NONE: \"\"\n} as const;\n\nexport const KEY_DIRECTION = [\"LEFT\", \"UP\", \"RIGHT\", \"DOWN\"] as const;\nexport enum DIRECTION_KEY_CODE {\n LEFT = 37,\n UP = 38,\n RIGHT = 39,\n DOWN = 40\n}\nexport const SPACE_KEY_CODE = 32;\n\nexport const DIRECTION_KEY_NAME = {\n LEFT: \"ArrowLeft\",\n UP: \"ArrowUp\",\n RIGHT: \"ArrowRight\",\n DOWN: \"ArrowDown\"\n} as const;\nexport const SPACE_KEY_NAME = \" \";\n\nexport const FULLSCREEN_REQUEST = [\n \"requestFullscreen\",\n \"webkitRequestFullscreen\",\n \"webkitRequestFullScreen\",\n \"webkitCancelFullScreen\",\n \"mozRequestFullScreen\",\n \"msRequestFullscreen\"\n];\n\nexport const FULLSCREEN_ELEMENT = [\n \"fullscreenElement\",\n \"webkitFullscreenElement\",\n \"webkitCurrentFullScreenElement\",\n \"mozFullScreenElement\",\n \"msFullscreenElement\"\n];\n\nexport const FULLSCREEN_EXIT = [\n \"exitFullscreen\",\n \"webkitExitFullscreen\",\n \"webkitCancelFullScreen\",\n \"mozCancelFullScreen\",\n \"msExitFullscreen\"\n];\n\nexport const FULLSCREEN_CHANGE = [\n \"fullscreenchange\",\n \"webkitfullscreenchange\",\n \"mozfullscreenchange\",\n \"MSFullscreenChange\"\n];\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nexport { ERROR_CODES } from \"./error\";\n\n/**\n * Default class names\n * @ko 기본 클래스 이름들\n * @since 4.0.0\n */\nexport const DEFAULT_CLASS = {\n CONTAINER: \"view360-container\",\n CANVAS: \"view360-canvas\",\n CTX_LOST: \"view360-ctx-lost\",\n IN_VR: \"view360-vr-presenting\",\n HOTSPOT_CONTAINER: \"view360-hotspots\",\n HOTSPOT: \"view360-hotspot\",\n HOTSPOT_VISIBLE: \"view360-hotspot-visible\",\n HOTSPOT_FLIP_X: \"view360-hotspot-flip-x\",\n HOTSPOT_FLIP_Y: \"view360-hotspot-flip-y\",\n} as const;\n\n/**\n * Event names\n * @ko 이벤트 이름들\n * @since 4.0.0\n * @example\n * ```ts\n * import View360, { EVENTS } from \"@egjs/view360\";\n *\n * const viewer = new View360(\"#el_id\");\n *\n * viewer.on(EVENTS.READY, evt => {\n * console.log(\"View360 is ready!\");\n * });\n * ```\n */\nexport const EVENTS = {\n READY: \"ready\",\n LOAD_START: \"loadStart\",\n LOAD: \"load\",\n PROJECTION_CHANGE: \"projectionChange\",\n RESIZE: \"resize\",\n BEFORE_RENDER: \"beforeRender\",\n RENDER: \"render\",\n INPUT_START: \"inputStart\",\n INPUT_END: \"inputEnd\",\n VIEW_CHANGE: \"viewChange\",\n STATIC_CLICK: \"staticClick\",\n VR_START: \"vrStart\",\n VR_END: \"vrEnd\"\n} as const;\n\n/**\n * Collection of predefined easing functions\n * @ko 미리 정의된 easing 함수들\n */\nexport const EASING = {\n LINEAR: (x: number) => x,\n SINE_WAVE: (x: number) => Math.sin(x * Math.PI * 2),\n EASE_OUT_CUBIC: (x: number) => 1 - Math.pow(1 - x, 3),\n EASE_OUT_BOUNCE: (x: number): number => {\n const n1 = 7.5625;\n const d1 = 2.75;\n\n if (x < 1 / d1) {\n return n1 * x * x;\n } else if (x < 2 / d1) {\n return n1 * (x -= 1.5 / d1) * x + 0.75;\n } else if (x < 2.5 / d1) {\n return n1 * (x -= 2.25 / d1) * x + 0.9375;\n } else {\n return n1 * (x -= 2.625 / d1) * x + 0.984375;\n }\n }\n} as const;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport { EASING } from \"./external\";\nimport { Range } from \"../type/utils\";\n\nexport const CAMERA_EVENTS = {\n CHANGE: \"change\",\n ANIMATION_END: \"animationEnd\"\n} as const;\n\nexport const OBJECT_3D_EVENTS = {\n UPDATE: \"update\"\n} as const;\n\nexport const CONTROL_EVENTS = {\n INPUT_START: \"inputStart\",\n CHANGE: \"change\",\n INPUT_END: \"inputEnd\",\n ENABLE: \"enable\",\n DISABLE: \"disable\",\n STATIC_CLICK: \"staticClick\"\n} as const;\n\nexport const DEG_TO_RAD = Math.PI / 180;\nexport const RAD_TO_DEG = 180 / Math.PI;\nexport const DEFAULT_EASING = EASING.EASE_OUT_CUBIC;\nexport const DEFAULT_ANIMATION_DURATION = 300;\nexport const INFINITE_RANGE: Readonly<Range> = {\n min: -Infinity, max: Infinity\n} as const;\nexport const DEFAULT_PITCH_RANGE: Readonly<Range> = {\n min: -90, max: 90\n} as const;\nexport const DEFAULT_ZOOM_RANGE: Readonly<Range> = {\n min: 0.6, max: 10\n} as const;\n\nexport enum ROTATE {\n ZERO,\n CW_90,\n CCW_90,\n CW_180\n}\n\n// Custom event name for video time change\nexport const VIDEO_TIME_CHANGE_EVENT = \"view360videotimechange\";\nexport const SVG_NAMESPACE = \"http://www.w3.org/2000/svg\";\nexport const SESSION_VR = \"immersive-vr\";\nexport const XR_REFERENCE_SPACE = \"local\";\n\nexport const EPSILON = 2.220446049250313e-16;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport { quat, vec3 } from \"gl-matrix\";\nimport View360Error from \"./core/View360Error\";\nimport ERROR from \"./const/error\";\nimport * as BROWSER from \"./const/browser\";\nimport { DEG_TO_RAD, RAD_TO_DEG } from \"./const/internal\";\nimport { NoBoolean } from \"./type/utils\";\n\nexport const isString = (val: any): val is string => typeof val === \"string\";\nexport const isElement = (val: any): val is Element => !!val && val.nodeType === Node.ELEMENT_NODE;\n\nexport const createElement = (className: string, tag = BROWSER.EL_DIV) => {\n const el = document.createElement(tag);\n\n el.classList.add(className);\n\n return el;\n};\n\nexport const getNullableElement = (el: HTMLElement | string | null, parent?: HTMLElement): HTMLElement | null => {\n let targetEl: HTMLElement | null = null;\n\n if (isString(el)) {\n const parentEl = parent ? parent : document;\n const queryResult = parentEl.querySelector(el);\n\n if (!queryResult) {\n return null;\n }\n\n targetEl = queryResult as HTMLElement;\n } else if (isElement(el)) {\n targetEl = el;\n }\n\n return targetEl;\n};\n\nexport const getElement = (el: HTMLElement | string, parent?: HTMLElement): HTMLElement => {\n const targetEl = getNullableElement(el, parent);\n\n if (!targetEl) {\n if (isString(el)) {\n throw new View360Error(ERROR.MESSAGES.ELEMENT_NOT_FOUND(el), ERROR.CODES.ELEMENT_NOT_FOUND);\n } else {\n throw new View360Error(ERROR.MESSAGES.WRONG_TYPE(el, [\"HTMLElement\", \"string\"]), ERROR.CODES.WRONG_TYPE);\n }\n }\n\n return targetEl;\n};\n\nexport const findCanvas = (root: HTMLElement, selector: string): HTMLCanvasElement => {\n const canvas = root.querySelector(selector) as HTMLCanvasElement;\n\n if (!canvas) {\n throw new View360Error(ERROR.MESSAGES.CANVAS_NOT_FOUND, ERROR.CODES.CANVAS_NOT_FOUND);\n }\n\n return canvas;\n};\n\nexport const range = (end: number): number[] => {\n if (!end || end <= 0) {\n return [];\n }\n\n return Array.apply(0, Array(end)).map((undef, idx) => idx);\n};\n\nexport const clamp = (x: number, min: number, max: number) => Math.max(Math.min(x, max), min);\n\n// Linear interpolation between a and b\nexport const lerp = (a: number, b: number, t: number) => {\n return a * (1 - t) + b * t;\n};\n\nexport const circulate = (val: number, min: number, max: number) => {\n const size = Math.abs(max - min);\n\n if (val < min) {\n const offset = (min - val) % size;\n val = max - offset;\n } else if (val > max) {\n const offset = (val - max) % size;\n val = min + offset;\n }\n\n return val;\n};\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport const merge = (target: object, ...srcs: object[]): object => {\n srcs.forEach(source => {\n Object.keys(source).forEach(key => {\n const value = source[key];\n if (Array.isArray(target[key]) && Array.isArray(value)) {\n target[key] = [...target[key], ...value];\n } else {\n target[key] = value;\n }\n });\n });\n\n return target;\n};\n\nexport const findIndex = <T>(array: T[], checker: (val: T) => boolean): number => {\n for (let idx = 0; idx < array.length; idx++) {\n if (checker(array[idx])) {\n return idx;\n }\n }\n\n return -1;\n};\n\nexport const getObjectOption = <T extends boolean | Partial<object>>(val?: T): NoBoolean<T> => typeof val === \"object\" ? val : {} as any;\nexport const toVerticalFov = (fovRadian: number, aspect: number) => {\n return Math.atan(Math.tan(fovRadian * 0.5) / aspect) * 2;\n};\n\nexport const reorderCube = <T>(arr: T[], order: string, defaultOrder = \"RLUDFB\"): T[] => {\n return defaultOrder.split(\"\")\n .map(face => order.indexOf(face))\n .map(index => arr[index]);\n};\n\nexport const isFullscreen = () => {\n if (!document) return false;\n\n for (const key of BROWSER.FULLSCREEN_ELEMENT) {\n if (document[key]) return true;\n }\n\n return false;\n};\n\nexport const sensorCanBeEnabledIOS = () => {\n const hostname = window.location.hostname;\n const isSecure =\n window.location.protocol === \"https:\" ||\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"[::1]\";\n\n return isSecure && !!DeviceMotionEvent && \"requestPermission\" in DeviceMotionEvent;\n};\n\nexport const hfovToZoom = (baseFov: number, fov: number) => {\n const renderingWidth = Math.tan(DEG_TO_RAD * baseFov * 0.5);\n const zoomedWidth = Math.tan(DEG_TO_RAD * fov * 0.5);\n\n return renderingWidth / zoomedWidth;\n};\n\nexport const eulerToQuat = (out: quat, yaw: number, pitch: number, roll: number): quat => {\n quat.identity(out);\n\n const pitchThreshold = 0.01;\n const pitchClamped = clamp(pitch, -90 + pitchThreshold, 90 - pitchThreshold);\n\n quat.rotateY(out, out, yaw * DEG_TO_RAD);\n quat.rotateX(out, out, pitchClamped * DEG_TO_RAD);\n quat.rotateZ(out, out, roll * DEG_TO_RAD);\n\n return out;\n};\n\n/**\n * Extract euler angles from the quaternion, except roll(z-axis rotation)\n * @hidden\n */\nexport const quatToEuler = (quaternion: quat) => {\n const x = quaternion[0];\n const y = quaternion[1];\n const z = quaternion[2];\n const w = quaternion[3];\n const x2 = x * x;\n const y2 = y * y;\n const z2 = z * z;\n const w2 = w * w;\n\n const unit = x2 + y2 + z2 + w2;\n const test = x * w - y * z;\n\n let pitch: number, yaw: number;\n\n if (test > 0.499995 * unit) {\n // singularity at the north pole\n pitch = Math.PI / 2;\n yaw = 2 * Math.atan2(y, x);\n } else if (test < -0.499995 * unit) {\n // singularity at the south pole\n pitch = -Math.PI / 2;\n yaw = -2 * Math.atan2(y, x);\n } else {\n const view = vec3.fromValues(0, 0, 1);\n const up = vec3.fromValues(0, 1, 0);\n\n vec3.transformQuat(view, view, quaternion);\n vec3.transformQuat(up, up, quaternion);\n\n const viewXZ = Math.sqrt(view[0] * view[0] + view[2] * view[2]);\n\n pitch = Math.atan2(-view[1], viewXZ);\n yaw = Math.atan2(view[0], view[2]);\n }\n\n return {\n pitch: clamp(pitch * RAD_TO_DEG, -90, 90),\n yaw: circulate(yaw * RAD_TO_DEG, 0, 360)\n };\n};\n","/*\n * Copyright (c) 2020 NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\n\nimport { clamp, lerp, circulate } from \"../utils\";\nimport { Range } from \"../type/utils\";\nimport { DEFAULT_ANIMATION_DURATION, DEFAULT_EASING } from \"../const/internal\";\n\n/**\n * Interpolator between two values with duration\n * @ko 특정 시간동안 두 값을 보간해주는 보간기\n * @since 4.0.0\n */\nclass Motion {\n // Options\n private _duration: number;\n private _loop: boolean;\n private _range: Range;\n private _easing: (x: number) => number;\n\n // Internal states\n private _progress: number;\n private _val: number;\n private _start: number;\n private _end: number;\n private _activated: boolean;\n\n /**\n * Current interpolated value\n * @ko 현재 보간된 값\n * @since 4.0.0\n */\n public get val() { return this._val; }\n /**\n * Start(from) value of interpolation\n * @ko 보간 시작 값\n * @since 4.0.0\n */\n public get start() { return this._start; }\n /**\n * End(to) value of interpolation\n * @ko 보간 끝 값\n * @since 4.0.0\n */\n public get end() { return this._end; }\n /**\n * Interpolation progress value (0 ~ 1)\n * @ko 현재 보간 진행정도 (0 ~ 1)\n * @since 4.0.0\n */\n public get progress() { return this._progress; }\n /**\n * Whether the interpolation is in active state.\n * @ko 보간 진행중인지 여부. `true`일 경우 보간이 진행중입니다.\n * @since 4.0.0\n */\n public get activated() { return this._activated; }\n\n /**\n * Duration of the interpolation\n * @ko 보간할 시간\n * @since 4.0.0\n */\n public get duration() { return this._duration; }\n public set duration(val: number) { this._duration = val; }\n\n /**\n * Whether to loop interpolation on finish\n * @ko 보간이 끝난 이후에 다시 시작할지 여부\n * @since 4.0.0\n */\n public get loop() { return this._loop; }\n public set loop(val: boolean) { this._loop = val; }\n\n /**\n * Range of the interpolation\n * @ko 보간 범위\n * @since 4.0.0\n */\n public get range() { return this._range; }\n\n /**\n * Easing function of the interpolation\n * @ko 보간에 사용되는 easing function\n * @since 4.0.0\n */\n public get easing() { return this._easing; }\n public set easing(val: (x: number) => number) { this._easing = val; }\n\n /**\n * Create new instance.\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options Options {@ko 옵션들}\n * @param options.duration Duration of the interpolation {@ko 보간할 시간}\n * @param options.loop Whether to loop interpolation on finish {@ko 보간이 끝난 이후에 다시 시작할지 여부}\n * @param options.range Range of the interpolation {@ko 보간 범위}\n * @param options.loop Easing function of the interpolation {@ko 보간에 사용되는 easing function}\n */\n public constructor({\n duration = DEFAULT_ANIMATION_DURATION,\n loop = false,\n range = { min: 0, max: 1 },\n easing = DEFAULT_EASING\n } = {}) {\n this._duration = duration;\n this._loop = loop;\n this._range = range;\n this._easing = easing;\n this._activated = false;\n this.reset(0);\n }\n\n /**\n * Update motion and progress it by given deltaTime\n * @ko 주어진 deltaTime만큼 보간을 진행합니다.\n * @param deltaTime - number of milisec to update motion {@ko 보간을 진행할 시간, 밀리초 단위}\n * @returns Difference(delta) of the value from the last update. {@ko 지난 업데이트 이후의 값 변화량}\n * @since 4.0.0\n */\n public update(deltaTime: number): number {\n if (!this._activated) {\n this._val = this._end;\n return 0;\n }\n\n const start = this._start;\n const end = this._end;\n const duration = this._duration;\n const prev = this._val;\n const loop = this._loop;\n\n const nextProgress = this._progress + deltaTime / duration;\n\n this._progress = loop\n ? circulate(nextProgress, 0, 1)\n : clamp(nextProgress, 0, 1);\n\n const easedProgress = this._easing(this._progress);\n this._val = lerp(start, end, easedProgress);\n\n if (!loop && this._progress >= 1) {\n this._activated = false;\n }\n\n return this._val - prev;\n }\n\n /**\n * Set `start`, `end` to the given value and set `progress` to 0.\n * @ko 주어진 값으로 시작 지점, 끝 지점을 초기화하고 progress를 0으로 세팅합니다.\n * @param defaultVal - Value to reset {@ko 초기화할 값}\n * @since 4.0.0\n */\n public reset(defaultVal: number): void {\n const range = this._range;\n const val = clamp(defaultVal, range.min, range.max);\n this._start = val;\n this._end = val;\n this._val = val;\n this._progress = 0;\n this._activated = false;\n }\n\n /**\n * Add delta to start & end and current value.\n * @ko 현재 & 끝 및 현재 값에 주어진 값을 더합니다.\n * @param delta - Delta value to add {@ko 추가할 값}\n */\n public add(delta: number) {\n const range = this._range;\n\n this._start = clamp(this._start + delta, range.min, range.max);\n this._end = clamp(this._end + delta, range.min, range.max);\n this._val = clamp(this._val + delta, range.min, range.max);\n }\n\n /**\n * Set current value to start, and end to current value + delta, then reset progress to 0.\n * @ko 현재 값을 시작 지점으로, 그에서 delta만큼 추가된 값을 끝점으로 하고 progress를 0으로 갱신합니다.\n * @param delta - Delta value to add {@ko 추가할 값}\n */\n public setNewEndByDelta(delta: number): void {\n const range = this._range;\n\n this._start = this._val;\n this._end = clamp(this._end + delta, range.min, range.max);\n this._progress = 0;\n this._activated = true;\n }\n\n /**\n * Set new range of the interpolation.\n * @ko 보간의 범위를 변경합니다.\n * @param min - New minimum range {@ko 변경할 범위의 최소값}\n * @param max - New maximum range {@ko 변경할 범위의 최대값}\n */\n public setRange(min: number, max: number) {\n this._start = clamp(this._start, min, max);\n this._end = clamp(this._end, min, max);\n this._range = { min, max };\n }\n}\n\nexport default Motion;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport { quat } from \"gl-matrix\";\nimport Camera from \"./Camera\";\nimport Motion from \"./Motion\";\nimport { DEFAULT_ANIMATION_DURATION, DEFAULT_EASING } from \"../const/internal\";\nimport { lerp } from \"../utils\";\n\ntype CameraPose = {\n rotation: quat;\n zoom: number;\n}\n\n/**\n * Animation of the {@link Camera}\n * @internal\n * @ko {@link Camera}의 애니메이션\n * @since 4.0.0\n */\nclass CameraAnimation {\n // Options\n private _camera: Camera;\n private _from: CameraPose;\n private _to: CameraPose;\n\n // Internal values\n private _motion: Motion;\n private _finishPromise: Promise<void>;\n private _finish: () => void;\n\n /**\n * Duration of the animation\n * @ko 애니메이션 재생시간\n * @since 4.0.0\n */\n public get duration() { return this._motion.duration; }\n public set duration(val: number) { this._motion.duration = val; }\n /**\n * Easing function of the animation\n * @ko 애니메이션의 easing function\n * @since 4.0.0\n */\n public get easing() { return this._motion.easing; }\n public set easing(val: (x: number) => number) { this._motion.easing = val; }\n\n /**\n * Create new instance\n * @ko 새로운 인스턴스를 생성합니다.\n * @param camera - Camera to animate {@ko 애니메이션을 적용할 카메라}\n * @param from - Start pose {@ko 애니메이션이 시작 시점의 카메라의 회전 및 줌}\n * @param to - End pose {@ko 애니메이션이 끝났을 때 카메라의 회전 및 줌}\n * @param options - Options {@ko 옵션들}\n * @param options.duration - Animation duration {@ko 애니메이션 재생 시간}\n * @param options.easing - Animation easing function {@ko 애니메이션 easing function}\n */\n public constructor(camera: Camera, from: CameraPose, to: CameraPose, {\n duration = DEFAULT_ANIMATION_DURATION,\n easing = DEFAULT_EASING\n } = {}) {\n this._camera = camera;\n this._motion = new Motion({ duration, easing, range: { min: 0, max: 1 } });\n this._from = from;\n this._to = to;\n this._finishPromise = new Promise(resolve => {\n this._finish = resolve as () => void;\n });\n\n // Enable motion\n this._motion.setNewEndByDelta(1);\n }\n\n /**\n * Return a promise that resolved on animation end.\n * @ko 애니메이션 재생이 끝났을 때 resolve되는 Promise를 반환합니다.\n * @since 4.0.0\n */\n public getFinishPromise() {\n return this._finishPromise;\n }\n\n /**\n * Update animation by given deltaTime.\n * @ko 주어진 시간만큼 애니메이션을 업데이트합니다.\n * @param deltaTime Number of milisec to update {@ko 업데이트할 시간, 밀리초 단위}\n * @since 4.0.0\n */\n public update(deltaTime: number): void {\n const camera = this._camera;\n const from = this._from;\n const to = this._to;\n const motion = this._motion;\n motion.update(deltaTime);\n\n // Progress that easing is applied\n const progress = motion.val;\n const rotation = quat.create();\n const zoom = lerp(from.zoom, to.zoom, progress);\n\n quat.slerp(rotation, from.rotation, to.rotation, progress);\n camera.rotate(rotation, zoom);\n\n if (progress >= 1) {\n this._finish();\n }\n }\n}\n\nexport default CameraAnimation;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport { mat4, quat, vec3 } from \"gl-matrix\";\nimport CameraAnimation from \"./CameraAnimation\";\nimport {\n CAMERA_EVENTS,\n DEG_TO_RAD,\n INFINITE_RANGE,\n DEFAULT_PITCH_RANGE,\n RAD_TO_DEG,\n DEFAULT_ZOOM_RANGE,\n DEFAULT_EASING,\n EPSILON\n} from \"../const/internal\";\nimport {\n circulate,\n clamp,\n eulerToQuat,\n quatToEuler,\n toVerticalFov\n} from \"../utils\";\nimport { Range } from \"../type/utils\";\n\n/**\n * Events that {@link Camera} can trigger\n * @ko {@link Camera}가 트리거할 수 있는 이벤트들\n * @since 4.0.0\n */\nexport interface CameraEvents {\n /**\n * An event that fires when camera's animation stops\n * @ko 카메라 애니메이션이 멈췄을 때 트리거되는 이벤트\n * @eventName animationEnd\n * @eventOf Camera\n * @version 4.0.0\n */\n [CAMERA_EVENTS.ANIMATION_END]: {\n animation: CameraAnimation\n };\n}\n\n/**\n * Options for {@link Camera}\n * @ko {@link Camera}용 옵션들\n * @since 4.0.0\n */\nexport interface CameraOptions {\n /**\n * @copy View360#initialYaw\n */\n initialYaw: number;\n /**\n * @copy View360#initialPitch\n */\n initialPitch: number;\n /**\n * @copy View360#initialZoom\n */\n initialZoom: number;\n /**\n * @copy View360#yawRange\n */\n yawRange: Range | null;\n /**\n * @copy View360#pitchRange\n */\n pitchRange: Range | null;\n /**\n * @copy View360#zoomRange\n */\n zoomRange: Range | null;\n /**\n * @copy View360#fov\n */\n fov: number;\n}\n\n/**\n * Camera for View360\n * @ko View360용 카메라 구현체\n * @version 4.0.0\n */\nclass Camera extends Component<CameraEvents> {\n /**\n * Current yaw(y-axis rotation) value\n * @ko 현재 yaw(y축 회전) 값\n * @since 4.0.0\n */\n public yaw: number;\n /**\n * Current pitch(x-axis rotation) value\n * @ko 현재 pitch(x축 회전) 값\n * @since 4.0.0\n */\n public pitch: number;\n /**\n * Current zoom value\n * @ko 현재 줌 값\n * @since 4.0.0\n */\n public zoom: number;\n\n /**\n * @copy View360#initialYaw\n */\n public initialYaw: number;\n /**\n * @copy View360#initialPitch\n */\n public initialPitch: number;\n /**\n * @copy View360#initialPitch\n */\n public initialZoom: number;\n /**\n * @hidden\n * TODO: Please add comment for this when `rollOffset` is added\n */\n public rollOffset: number;\n\n /**\n * Current camera quaternion\n * @ko 현재 회전을 나타내는 quaternion 값\n * @since 4.0.0\n * @internal\n */\n public quaternion: quat;\n /**\n * Current camera position\n * @ko 현재 카메라 위치 좌표\n * @since 4.0.0\n * @internal\n */\n public position: vec3;\n /**\n * Active camera animation, `null` if there isn't.\n * @ko 현재 활성화된 카메라 애니메이션, 없을 경우 `null`값을 가집니다.\n * @since 4.0.0\n */\n public animation: CameraAnimation | null;\n /**\n * Camera's view matrix\n * @ko 카메라의 뷰 변환 행렬\n * @internal\n * @since 4.0.0\n */\n public viewMatrix: mat4;\n /**\n * Camera's projection matrix\n * @ko 카메라의 프로젝션 변환 행렬\n * @internal\n * @since 4.0.0\n */\n public projectionMatrix: mat4;\n\n /**\n * Camera's horizontal FOV(Field of View) value\n * @ko 카메라의 수평 FOV(Field of View) 값\n * @internal\n * @since 4.0.0\n */\n public fov: number;\n\n private _initialYawRange: Range | null;\n private _initialPitchRange: Range | null;\n private _initialZoomRange: Range | null;\n\n private _yawRange: Range | null;\n private _pitchRange: Range | null;\n private _zoomRange: Range | null;\n\n private _up: vec3;\n private _aspect: number;\n private _changed: boolean;\n private _maxRenderHeight: number;\n\n /**\n * Camera's width / height ratio\n * @ko 카메라의 가로 / 세로 비율\n * @readonly\n */\n public get aspect() { return this._aspect; }\n /**\n * Whether the camera's rotation changed from the last frame.\n * @ko 마지막 프레임 이후로 카메라의 회전값이 변경되었는지 나타내는 플래그.\n * @readonly\n */\n public get changed() { return this._changed; }\n /**\n * @copy View360#yawRange\n */\n public get yawRange() { return this._initialYawRange; }\n public set yawRange(val: Range | null) {\n this._initialYawRange = val;\n }\n /**\n * @copy View360#pitchRange\n */\n public get pitchRange() { return this._initialPitchRange; }\n public set pitchRange(val: Range | null) {\n this._initialPitchRange = val;\n }\n /**\n * @copy View360#zoomRange\n */\n public get zoomRange() { return this._initialZoomRange; }\n public set zoomRange(val: Range | null) {\n this._initialZoomRange = val;\n }\n\n /**\n * Create new instance of Camera\n * @param options - Camera options {@ko 카메라 옵션들}\n */\n public constructor({\n initialYaw,\n initialPitch,\n initialZoom,\n yawRange,\n pitchRange,\n zoomRange,\n fov\n }: CameraOptions) {\n super();\n\n this.yaw = initialYaw;\n this.pitch = initialPitch;\n this.zoom = initialZoom;\n this.rollOffset = 0;\n\n this.initialYaw = initialYaw;\n this.initialPitch = initialPitch;\n this.initialZoom = initialZoom;\n\n this.position = vec3.create();\n this.animation = null;\n\n this._up = vec3.fromValues(0, 1, 0);\n this._aspect = 1;\n\n this._initialYawRange = yawRange;\n this._initialPitchRange = pitchRange;\n this._initialZoomRange = zoomRange;\n\n this._yawRange = yawRange;\n this._pitchRange = pitchRange;\n this._zoomRange = zoomRange;\n\n this.quaternion = quat.create();\n this._updateQuaternion();\n\n this.viewMatrix = mat4.create();\n this.projectionMatrix = mat4.create();\n this.fov = fov;\n\n this._maxRenderHeight = -1;\n }\n\n /**\n * Destroy instance and detach all event listeners\n * @ko 인스턴스를 삭제하고 모든 이벤트 리스너를 삭제합니다.\n * @since 4.0.0\n */\n public destroy() {\n this.off();\n }\n\n /**\n * Refresh internal size value.\n * @ko 내부 크기값을 갱신합니다.\n * @param width - New width {@ko 변경된 너비값}\n * @param height - New height {@ko 변경된 높이값}\n * @since 4.0.0\n */\n public resize(width: number, height: number) {\n const prevAspect = this._aspect;\n\n this._aspect = width / height;\n\n if (this._aspect !== prevAspect) {\n this.updateMatrix();\n }\n }\n\n /**\n * Change camera's rotation with euler values.\n * @ko 카메라 회전을 오일러 각 방향으로 변경합니다.\n * @param rotation - Rotation values {@ko 회전 값}\n * @param rotation.yaw - yaw(y-axis rotation) to look at {@ko 바라볼 yaw(y축 회전) 값}\n * @param rotation.pitch - pitch(x-axis rotation) to look at {@ko 바라볼 pitch(x축 회전) 값}\n * @param rotation.zoom - zoom value to apply {@ko 적용할 카메라 줌 값}\n * @since 4.0.0\n */\n public lookAt({\n yaw = this.yaw,\n pitch = this.pitch,\n zoom = this.zoom\n }: Partial<{\n yaw: number;\n pitch: number;\n zoom: number;\n }>) {\n const prevQuaternion = quat.clone(this.quaternion);\n const prevZoom = this.zoom;\n\n this.yaw = circulate(yaw, 0, 360);\n this.pitch = clamp(pitch, -90, 90);\n this.zoom = zoom;\n\n this._updateQuaternion();\n\n const zoomDiff = Math.abs(zoom - prevZoom);\n\n if (\n !quat.equals(this.quaternion, prevQuaternion)\n || zoomDiff >= EPSILON * 10 // ignore small changes\n ) {\n this.updateMatrix();\n }\n }\n\n /**\n * Change camera's rotation with quaternion.\n * @ko 카메라 회전을 Quaternion을 이용해서 변경합니다.\n * @param rotation - Quaternion to apply {@ko 적용할 Quaternion}\n * @param zoom - zoom value to apply {@ko 적용할 카메라 줌 값}\n * @since 4.0.0\n */\n public rotate(rotation: quat, zoom: number = this.zoom) {\n const normalized = quat.normalize(quat.create(), rotation);\n const isSameRotation = quat.equals(this.quaternion, normalized);\n quat.copy(this.quaternion, normalized);\n\n const prevZoom = this.zoom;\n const { yaw, pitch } = quatToEuler(normalized);\n\n this.yaw = yaw;\n this.pitch = pitch;\n this.zoom = zoom;\n\n const zoomDiff = Math.abs(zoom - prevZoom);\n\n if (!isSameRotation || zoomDiff >= EPSILON * 10) {\n this.updateMatrix();\n }\n }\n\n /**\n * Change camera's rotation to given euler values by the given duration.\n * @ko 카메라를 주어진 방향으로 주어진 시간동안 서서히 이동시킵니다.\n * @param options - Animation parameters {@ko 애니메이션 패러미터}\n * @param options.yaw - yaw(y-axis rotation) to look at {@ko 바라볼 yaw(y축 회전) 값}\n * @param options.pitch - pitch(x-axis rotation) to look at {@ko 바라볼 pitch(x축 회전) 값}\n * @param options.zoom - zoom value to apply {@ko 적용할 카메라 줌 값}\n * @param options.duration - Duration of the animation {@ko 애니메이션 시간}\n * @param options.easing - Easing function for the animation {@ko 애니메이션에 적용할 easing function}\n */\n public async animateTo({\n yaw = this.yaw,\n pitch = this.pitch,\n zoom = this.zoom,\n duration = 0,\n easing = DEFAULT_EASING\n }: Partial<{\n yaw: number;\n pitch: number;\n zoom: number;\n duration: number;\n easing: (x: number) => number;\n }> = {}): Promise<void> {\n if (\n this.yaw === yaw\n && this.pitch === pitch\n && this.zoom === zoom\n ) return;\n\n const from = {\n rotation: quat.clone(this.quaternion),\n zoom: this.zoom\n };\n const to = {\n rotation: eulerToQuat(quat.create(), yaw, pitch, this.rollOffset),\n zoom\n };\n\n const animation = new CameraAnimation(this, from, to, {\n duration,\n easing\n });\n const finishPromise = animation.getFinishPromise();\n\n this.animation = animation;\n finishPromise.then(() => {\n this.animation = null;\n this.trigger(CAMERA_EVENTS.ANIMATION_END, { animation });\n });\n\n return finishPromise;\n }\n\n /**\n * @hidden\n */\n public restrictYawRange(min: number, max: number) {\n this._yawRange = { min, max };\n }\n\n /**\n * @hidden\n */\n public restrictPitchRange(min: number, max: number) {\n this._pitchRange = { min, max };\n }\n\n /**\n * @hidden\n */\n public restrictZoomRange(min: number, max: number) {\n this._zoomRange = { min, max };\n }\n\n /**\n * @hidden\n */\n public restrictRenderHeight(height: number) {\n this._maxRenderHeight = height;\n }\n\n /**\n * @hidden\n */\n public resetRange() {\n this._yawRange = this._initialYawRange;\n this._pitchRange = this._initialPitchRange;\n this._zoomRange = this._initialZoomRange;\n this._maxRenderHeight = -1;\n }\n\n /**\n * Get actual yaw range by the given zoom value.\n * @ko 주어진 zoom 값에 대한 실제 yaw 범위값을 반환합니다.\n * @since 4.0.0\n */\n public getYawRange(zoom: number) {\n const yawLimit = this._yawRange;\n const maxRenderHeight = this._maxRenderHeight;\n if (!yawLimit) return INFINITE_RANGE;\n\n const halfHFov = this.getHorizontalFov(zoom) * 0.5;\n let minYaw = yawLimit.min;\n let maxYaw = yawLimit.max;\n\n if (maxRenderHeight > 0) {\n const halfVFovRad = toVerticalFov(halfHFov * DEG_TO_RAD, this._aspect);\n const h = maxRenderHeight * 0.5;\n const t = Math.tan(halfVFovRad);\n const d = Math.sqrt((1 + h * h) / (1 + t * t));\n const theta = Math.atan(Math.tan(halfHFov * DEG_TO_RAD) * d) * RAD_TO_DEG;\n\n minYaw = yawLimit.min + theta;\n maxYaw = yawLimit.max - theta;\n }\n\n if (minYaw > maxYaw) {\n minYaw = 0;\n maxYaw = 0;\n }\n\n return {\n min: minYaw,\n max: maxYaw\n };\n }\n\n /**\n * Get actual pitch range by the given zoom value.\n * @ko 주어진 zoom 값에 대한 실제 pitch 범위값을 반환합니다.\n * @since 4.0.0\n */\n public getPitchRange(zoom: number) {\n const pitchLimit = this._pitchRange;\n const maxRenderHeight = this._maxRenderHeight;\n\n if (!pitchLimit) return DEFAULT_PITCH_RANGE;\n\n let minPitch = pitchLimit.min;\n let maxPitch = pitchLimit.max;\n\n if (maxRenderHeight > 0) {\n const halfVFov = this.getVerticalFov(zoom) * 0.5;\n\n minPitch = pitchLimit.min + halfVFov;\n maxPitch = pitchLimit.max - halfVFov;\n }\n\n if (minPitch > maxPitch) {\n minPitch = 0;\n maxPitch = 0;\n }\n\n return {\n min: Math.max(minPitch, -90),\n max: Math.min(maxPitch, 90)\n };\n }\n\n /**\n * Get actual zoom range in fov degrees.\n * @ko 실제 줌 범위를 fov각의 범위로 반환합니다.\n * @since 4.0.0\n */\n public getZoomRange() {\n const limit = this._zoomRange ?? DEFAULT_ZOOM_RANGE;\n\n // max (zoom in) -> minimum fov\n const minFov = this.getHorizontalFov(limit.max);\n const maxFov = this.getHorizontalFov(limit.min);\n const currentFov = this.getHorizontalFov(this.zoom);\n\n return {\n min: Math.max(minFov, 1),\n max: Math.min(maxFov, 180),\n current: currentFov\n };\n }\n\n /**\n * Return horizontal fov value when the given zoom is applied. (in degrees, °)\n * @ko 주어진 zoom 값이 적용되었을 때의 수평 fov값을 반환합니다. (도 단위, °)\n * @returns Zoomed horizontal FOV {@ko 줌이 적용된 수평 fov값}\n * @since 4.0.0\n */\n public getHorizontalFov(zoom = this.zoom) {\n return this._getZoomedHorizontalFov(zoom) * RAD_TO_DEG;\n }\n\n /**\n * Return vertical fov value when the given zoom is applied. (in degrees, °)\n * @ko 주어진 zoom 값이 적용되었을 때의 수직 fov값을 반환합니다. (도 단위, °)\n * @returns Zoomed vertical FOV {@ko 줌이 적용된 수직 fov값}\n * @since 4.0.0\n */\n public getVerticalFov(zoom = this.zoom) {\n const aspect = this._aspect;\n const hFov = this._getZoomedHorizontalFov(zoom); // In radians\n const vFov = toVerticalFov(hFov, aspect);\n\n return vFov * RAD_TO_DEG;\n }\n\n /**\n * Calculate zoom value for the given fov.\n * @ko 주어진 fov값을 zoom값으로 변환합니다.\n * @param fov horizontal fov (in degrees, °) {@ko 수평 fov 값 (도 단위, °)}\n * @since 4.0.0\n */\n public fovToZoom(fov: number) {\n const baseFov = this.fov;\n const renderingWidth = Math.tan(DEG_TO_RAD * baseFov * 0.5);\n const zoomedWidth = Math.tan(DEG_TO_RAD * fov * 0.5);\n\n return renderingWidth / zoomedWidth;\n }\n\n /**\n * Update inner matrixes.\n * @ko 내부 행렬들을 업데이트합니다.\n * @internal\n * @since 4.0.0\n */\n public updateMatrix() {\n const up = this._up;\n const aspect = this._aspect;\n const viewMatrix = this.viewMatrix;\n const projMatrix = this.projectionMatrix;\n const position = this.position;\n const rotation = this.quaternion;\n\n const upDir = vec3.create();\n const viewDir = vec3.fromValues(0, 0, -1);\n vec3.transformQuat(viewDir, viewDir, rotation);\n vec3.transformQuat(upDir, up, rotation);\n\n const hFov = this._getZoomedHorizontalFov(); // In radians\n const vFov = toVerticalFov(hFov, aspect);\n\n mat4.lookAt(viewMatrix, position, viewDir, upDir);\n mat4.perspective(projMatrix, vFov, aspect, 0.1, 100);\n\n this._changed = true;\n }\n\n /**\n * @hidden\n */\n public onFrameRender() {\n this._changed = false;\n }\n\n private _updateQuaternion() {\n eulerToQuat(this.quaternion, this.yaw, this.pitch, this.rollOffset);\n }\n\n /**\n * @param zoom Current zoom value\n * @returns horizontal fov including zoom, in radian\n */\n private _getZoomedHorizontalFov(zoom = this.zoom) {\n return 2 * Math.atan(Math.tan(DEG_TO_RAD * this.fov * 0.5) / zoom);\n }\n}\n\nexport default Camera;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport * as BROWSER from \"../../const/browser\";\nimport { CONTROL_EVENTS } from \"../../const/internal\";\nimport { InputEvents } from \"../../type/internal\";\n\nclass MouseInput extends Component<InputEvents<{ x: number, y: number }, MouseEvent>> {\n private _el: HTMLElement | null;\n private _prevPos: [number, number];\n\n public constructor() {\n super();\n\n this._el = null;\n this._prevPos = [0, 0];\n }\n\n public enable(element: HTMLElement) {\n if (this._el) return;\n\n element.addEventListener(BROWSER.EVENTS.MOUSE_DOWN, this._onMouseDown);\n\n this._el = element;\n }\n\n public disable() {\n const element = this._el;\n if (!element) return;\n\n element.removeEventListener(BROWSER.EVENTS.MOUSE_DOWN, this._onMouseDown);\n window.removeEventListener(BROWSER.EVENTS.MOUSE_MOVE, this._onMouseMove, false);\n window.removeEventListener(BROWSER.EVENTS.MOUSE_UP, this._onMouseUp, false);\n\n this._el = null;\n }\n\n private _onMouseDown = (evt: MouseEvent) => {\n const el = this._el;\n if (!el || evt.button !== BROWSER.MOUSE_BUTTON.LEFT) return;\n\n evt.preventDefault();\n\n if (el.focus) {\n el.focus();\n } else {\n window.focus();\n }\n\n this._prevPos[0] = evt.clientX;\n this._prevPos[1] = evt.clientY;\n\n window.addEventListener(BROWSER.EVENTS.MOUSE_MOVE, this._onMouseMove, false);\n window.addEventListener(BROWSER.EVENTS.MOUSE_UP, this._onMouseUp, false);\n\n this.trigger(CONTROL_EVENTS.INPUT_START, {\n srcEvent: evt,\n isTouch: false,\n isKeyboard: false\n });\n }\n\n private _onMouseMove = (evt: MouseEvent) => {\n evt.preventDefault();\n\n const x = evt.clientX;\n const y = evt.clientY;\n const prevPos = this._prevPos;\n const deltaX = x - prevPos[0];\n const deltaY = y - prevPos[1];\n\n this.trigger(CONTROL_EVENTS.CHANGE, {\n delta: {\n x: deltaX,\n y: deltaY\n },\n isTouch: false,\n isKeyboard: false\n });\n\n prevPos[0] = x;\n prevPos[1] = y;\n }\n\n private _onMouseUp = () => {\n this._prevPos[0] = 0;\n this._prevPos[1] = 0;\n\n window.removeEventListener(BROWSER.EVENTS.MOUSE_MOVE, this._onMouseMove, false);\n window.removeEventListener(BROWSER.EVENTS.MOUSE_UP, this._onMouseUp, false);\n\n this.trigger(CONTROL_EVENTS.INPUT_END, {\n isTouch: false,\n isKeyboard: false,\n scrolling: false\n });\n }\n}\n\nexport default MouseInput;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport * as BROWSER from \"../../const/browser\";\nimport { CONTROL_EVENTS } from \"../../const/internal\";\nimport { InputEvents } from \"../../type/internal\";\nimport { isFullscreen } from \"../../utils\";\n\nclass TouchInput extends Component<InputEvents<{ x: number, y: number }, TouchEvent>> {\n private _el: HTMLElement | null;\n private _prevPos: [number, number];\n private _isFirstTouch: boolean;\n private _scrolling: boolean;\n private _scrollable: boolean;\n\n public get scrollable() { return this._scrollable; }\n public set scrollable(val: boolean) { this._scrollable = val; }\n\n public constructor() {\n super();\n\n this._el = null;\n this._prevPos = [0, 0];\n this._isFirstTouch = false;\n this._scrolling = false;\n this._scrollable = false;\n }\n\n public enable(element: HTMLElement) {\n if (this._el) return;\n\n element.addEventListener(BROWSER.EVENTS.TOUCH_START, this._onTouchStart, { passive: false });\n element.addEventListener(BROWSER.EVENTS.TOUCH_MOVE, this._onTouchMove, { passive: false });\n element.addEventListener(BROWSER.EVENTS.TOUCH_END, this._onTouchEnd);\n\n this._el = element;\n }\n\n public disable() {\n const element = this._el;\n if (!element) return;\n\n element.removeEventListener(BROWSER.EVENTS.TOUCH_START, this._onTouchStart);\n element.removeEventListener(BROWSER.EVENTS.TOUCH_MOVE, this._onTouchMove);\n element.removeEventListener(BROWSER.EVENTS.TOUCH_END, this._onTouchEnd);\n\n this._el = null;\n }\n\n private _onTouchStart = (evt: TouchEvent) => {\n if (evt.touches.length > 1 || this._scrolling) return;\n\n const touch = evt.touches[0];\n\n this._isFirstTouch = true;\n this._prevPos[0] = touch.clientX;\n this._prevPos[1] = touch.clientY;\n\n this.trigger(CONTROL_EVENTS.INPUT_START, {\n srcEvent: evt,\n isTouch: true,\n isKeyboard: false\n });\n };\n\n private _onTouchMove = (evt: TouchEvent) => {\n // Only the one finger motion should be considered\n if (evt.touches.length > 1 || this._scrolling) return;\n\n const touch = evt.touches[0];\n const scrollable = this._scrollable;\n const prevPos = this._prevPos;\n\n const x = touch.clientX;\n const y = touch.clientY;\n const deltaX = x - prevPos[0];\n const deltaY = y - prevPos[1];\n\n if (this._isFirstTouch) {\n if (scrollable && !isFullscreen()) {\n if (Math.abs(deltaY) > Math.abs(deltaX)) {\n // Assume Scrolling\n this._scrolling = true;\n return;\n }\n }\n\n this._isFirstTouch = false;\n }\n\n if (evt.cancelable !== false) {\n evt.preventDefault();\n }\n\n this.trigger(CONTROL_EVENTS.CHANGE, {\n delta: {\n x: deltaX,\n y: deltaY\n },\n isTouch: true,\n isKeyboard: false\n });\n\n prevPos[0] = x;\n prevPos[1] = y;\n };\n\n private _onTouchEnd = (evt: TouchEvent) => {\n if (evt.touches.length !== 0) return;\n\n const touch = evt.touches[0];\n const prevPos = this._prevPos;\n\n if (touch) {\n prevPos[0] = touch.clientX;\n prevPos[1] = touch.clientY;\n } else {\n prevPos[0] = 0;\n prevPos[1] = 0;\n\n this.trigger(CONTROL_EVENTS.INPUT_END, {\n isTouch: true,\n isKeyboard: false,\n scrolling: this._scrolling\n });\n }\n\n if (evt.cancelable !== false) {\n evt.preventDefault();\n }\n\n this._scrolling = false;\n };\n}\n\nexport default TouchInput;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport * as BROWSER from \"../../const/browser\";\nimport { CONTROL_EVENTS } from \"../../const/internal\";\nimport { InputEvents } from \"../../type/internal\";\n\nclass KeyboardInput extends Component<InputEvents<{ x: number, y: number }, KeyboardEvent>> {\n private _el: HTMLElement | null;\n private _pressed: {\n LEFT: boolean;\n UP: boolean;\n RIGHT: boolean;\n DOWN: boolean;\n };\n\n public get active() {\n const pressed = this._pressed;\n return pressed.LEFT || pressed.UP || pressed.RIGHT || pressed.DOWN;\n }\n\n public constructor() {\n super();\n\n this._el = null;\n this._clearPressedKeys();\n }\n\n public enable(element: HTMLElement) {\n if (this._el) return;\n\n element.addEventListener(BROWSER.EVENTS.KEY_DOWN, this._onKeyDown);\n element.addEventListener(BROWSER.EVENTS.KEY_UP, this._onKeyUp);\n\n this._el = element;\n this._clearPressedKeys();\n }\n\n public disable() {\n const element = this._el;\n if (!element) return;\n\n element.removeEventListener(BROWSER.EVENTS.KEY_DOWN, this._onKeyDown);\n element.removeEventListener(BROWSER.EVENTS.KEY_UP, this._onKeyUp);\n\n this._el = null;\n this._clearPressedKeys();\n }\n\n public update() {\n const delta = this._getDeltaByPressedKeys();\n\n if (delta.x !== 0 || delta.y !== 0) {\n this.trigger(CONTROL_EVENTS.CHANGE, {\n delta,\n isTouch: false,\n isKeyboard: true\n });\n }\n }\n\n private _clearPressedKeys() {\n this._pressed = BROWSER.KEY_DIRECTION.reduce((obj, keyName) => {\n return {\n ...obj,\n [keyName]: false\n };\n }, {} as KeyboardInput[\"_pressed\"]);\n }\n\n private _updateKeyPress(event: KeyboardEvent, isEnable: boolean): void {\n const pressed = this._pressed;\n const keyToUpdate = event.keyCode != null\n ? BROWSER.DIRECTION_KEY_CODE[event.keyCode]\n : BROWSER.DIRECTION_KEY_NAME[event.key];\n\n if (!keyToUpdate) return;\n\n pressed[keyToUpdate] = isEnable;\n }\n\n private _getPressedKeyCount() {\n return BROWSER.KEY_DIRECTION.filter(key => this._pressed[key]).length;\n }\n\n private _getDeltaByPressedKeys() {\n const pressed = this._pressed;\n let x = 0;\n let y = 0;\n\n if (pressed.LEFT) {\n x += 1;\n }\n\n if (pressed.RIGHT) {\n x -= 1;\n }\n\n if (pressed.UP) {\n y += 1;\n }\n\n if (pressed.DOWN) {\n y -= 1;\n }\n\n return {\n x, y\n };\n }\n\n private _onKeyDown = (evt: KeyboardEvent) => {\n // Ignore all other keypress except main arrow keys\n if (evt.location !== KeyboardEvent.DOM_KEY_LOCATION_STANDARD) return;\n\n this._updateKeyPress(evt, true);\n\n const pressedCount = this._getPressedKeyCount();\n if (pressedCount <= 0) return;\n\n evt.preventDefault();\n if (pressedCount === 1 && !evt.repeat) {\n // On first keydown\n this.trigger(CONTROL_EVENTS.INPUT_START, {\n srcEvent: evt,\n isTouch: false,\n isKeyboard: true\n });\n }\n };\n\n private _onKeyUp = (evt: KeyboardEvent) => {\n // Ignore all other keypress except main arrow keys\n if (evt.location !== KeyboardEvent.DOM_KEY_LOCATION_STANDARD) return;\n\n this._updateKeyPress(evt, false);\n\n const pressedCount = this._getPressedKeyCount();\n if (pressedCount > 0) return;\n\n this.trigger(CONTROL_EVENTS.INPUT_END, {\n isTouch: false,\n isKeyboard: true,\n scrolling: false\n });\n };\n}\n\nexport default KeyboardInput;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport CameraControl from \"./CameraControl\";\nimport MouseInput from \"./input/MouseInput\";\nimport TouchInput from \"./input/TouchInput\";\nimport KeyboardInput from \"./input/KeyboardInput\";\nimport Camera from \"../core/Camera\";\nimport Motion from \"../core/Motion\";\nimport { CONTROL_EVENTS, INFINITE_RANGE, DEFAULT_PITCH_RANGE, DEFAULT_ANIMATION_DURATION, DEFAULT_EASING, DEG_TO_RAD, RAD_TO_DEG } from \"../const/internal\";\nimport { toVerticalFov } from \"../utils\";\nimport { ControlEvents, InputEvents } from \"../type/internal\";\n\n/**\n * Options for {@link RotateControl}\n * @ko {@link RotateControl}용 옵션들\n * @since 4.0.0\n */\nexport interface RotateControlOptions {\n /**\n * @copy RotateControl#pointerScale\n */\n pointerScale: [number, number];\n /**\n * @copy RotateControl#keyboardScale\n */\n keyboardScale: [number, number];\n /**\n * @copy RotateControl#duration\n */\n duration: number;\n /**\n * @copy RotateControl#easing\n */\n easing: (x: number) => number;\n /**\n * @copy RotateControl#disablePitch\n */\n disablePitch: boolean;\n /**\n * @copy RotateControl#disableYaw\n */\n disableYaw: boolean;\n /**\n * @copy RotateControl#disableKeyboard\n */\n disableKeyboard: boolean;\n}\n\ntype RotateDeltaType = { x: number; y: number; };\nexport type RotateControlEvents = ControlEvents<RotateDeltaType>;\n\n/**\n * Camera's rotation control\n * @ko 카메라의 회전을 담당하는 컨트롤\n * @since 4.0.0\n */\nclass RotateControl extends Component<RotateControlEvents> implements CameraControl {\n // Options\n private _pointerScale: RotateControlOptions[\"pointerScale\"];\n private _keyboardScale: RotateControlOptions[\"keyboardScale\"];\n private _duration: RotateControlOptions[\"duration\"];\n private _easing: RotateControlOptions[\"easing\"];\n private _disablePitch: RotateControlOptions[\"disablePitch\"];\n private _disableYaw: RotateControlOptions[\"disableYaw\"];\n private _disableKeyboard: RotateControlOptions[\"disableKeyboard\"];\n\n // Internal values\n private _controlEl: HTMLElement;\n private _enableBlocked: boolean;\n private _mouseInput: MouseInput;\n private _touchInput: TouchInput;\n private _keyboardInput: KeyboardInput;\n private _xMotion: Motion;\n private _yMotion: Motion;\n private _screenScale: [number, number];\n private _zoomScale: number;\n private _enabled: boolean;\n private _changedWhileDragging: boolean;\n\n /**\n * @copy CameraControl#enabled\n */\n public get enabled() { return this._enabled; }\n /**\n * @hidden\n */\n public get enableBlocked() { return this._enableBlocked; }\n /**\n * @copy CameraControl#animating\n */\n public get animating() {\n return this._keyboardInput.active\n || this._xMotion.activated\n || this._yMotion.activated;\n }\n /**\n * Current yaw value\n * @ko 현재 yaw 값\n * @readonly\n * @since 4.0.0\n */\n public get yaw() { return this._xMotion; }\n /**\n * Current pitch value\n * @ko 현재 pitch 값\n * @readonly\n * @since 4.0.0\n */\n public get pitch() { return this._yMotion; }\n /**\n * @copy View360#scrollable\n */\n public get scrollable() { return this._touchInput.scrollable; }\n public set scrollable(val: boolean) {\n this._touchInput.scrollable = val;\n }\n\n /**\n * Scale factor for mouse/touch rotation\n * @ko 마우스/터치를 통한 회전 배율\n * @default [1, 1]\n * @since 4.0.0\n */\n public get pointerScale() { return this._pointerScale; }\n public set pointerScale(val: RotateControlOptions[\"pointerScale\"]) {\n this._pointerScale = val;\n }\n\n /**\n * Scale factor for keyboard rotation\n * @ko 키보드를 통한 회전 배율\n * @default [1, 1]\n * @since 4.0.0\n */\n public get keyboardScale() { return this._keyboardScale; }\n public set keyboardScale(val: RotateControlOptions[\"keyboardScale\"]) {\n this._keyboardScale = val;\n }\n\n /**\n * Duration of the input animation (ms)\n * @ko 회전 애니메이션의 시간 (ms)\n * @default 300\n */\n public get duration() { return this._duration; }\n public set duration(val: RotateControlOptions[\"duration\"]) {\n this._duration = val;\n this._xMotion.duration = val;\n this._yMotion.duration = val;\n }\n\n /**\n * Easing function of the animation\n * @ko 회전 애니메이션에 적용할 easing 함수\n * @default EASING.EASE_OUT_CUBIC\n * @see EASING\n */\n public get easing() { return this._easing; }\n public set easing(val: RotateControlOptions[\"easing\"]) {\n this._easing = val;\n this._xMotion.easing = val;\n this._yMotion.easing = val;\n }\n\n /**\n * Disable X-axis(pitch) rotation.\n * @ko x축 회전(pitch)을 비활성화합니다.\n * @default false\n */\n public get disablePitch() { return this._disablePitch; }\n public set disablePitch(val: RotateControlOptions[\"disablePitch\"]) { this._disablePitch = val; }\n\n /**\n * Disable Y-axis(yaw) rotation.\n * @ko y축 회전(yaw)을 비활성화합니다.\n * @default false\n */\n public get disableYaw() { return this._disableYaw; }\n public set disableYaw(val: RotateControlOptions[\"disableYaw\"]) { this._disableYaw = val; }\n\n /**\n * Disable rotation by keyboard.\n * @ko 키보드를 이용한 회전을 비활성화합니다.\n * @default false\n */\n public get disableKeyboard() { return this._disableKeyboard; }\n public set disableKeyboard(val: RotateControlOptions[\"disableKeyboard\"]) { this._disableKeyboard = val; }\n\n /**\n * Create new RotateControl instance\n * @ko RotateControl의 인스턴스를 생성합니다.\n * @param controlEl - Element to attach handlers {@ko 입력을 받을 엘리먼트}\n * @param enableBlocked - Whether to disable control on init {@ko 초기화 과정에서 컨트롤 활성화 여부}\n * @param options - Options for control {@ko 컨트롤 옵션들}\n */\n public constructor(controlEl: HTMLElement, enableBlocked: boolean, {\n duration = DEFAULT_ANIMATION_DURATION,\n easing = DEFAULT_EASING,\n pointerScale = [1, 1],\n keyboardScale = [1, 1],\n disablePitch = false,\n disableYaw = false,\n disableKeyboard = false\n }: Partial<RotateControlOptions> = {}) {\n super();\n\n this._controlEl = controlEl;\n this._pointerScale = pointerScale;\n this._keyboardScale = keyboardScale;\n this._duration = duration;\n this._easing = easing;\n this._disablePitch = disablePitch;\n this._disableYaw = disableYaw;\n this._disableKeyboard = disableKeyboard;\n\n this._enableBlocked = enableBlocked;\n this._mouseInput = new MouseInput();\n this._touchInput = new TouchInput();\n this._keyboardInput = new KeyboardInput();\n this._xMotion = new Motion({ duration, range: INFINITE_RANGE, easing });\n this._yMotion = new Motion({ duration, range: DEFAULT_PITCH_RANGE, easing });\n this._screenScale = [1, 1];\n this._zoomScale = 1;\n this._enabled = false;\n this._changedWhileDragging = false;\n this._bindInputs();\n }\n\n public destroy(): void {\n this.disable();\n this._mouseInput.off();\n this._touchInput.off();\n this._keyboardInput.off();\n this.off();\n this._changedWhileDragging = false;\n }\n\n /**\n * @hidden\n */\n public update(delta: number): void {\n if (!this._enabled) return;\n\n const xMotion = this._xMotion;\n const yMotion = this._yMotion;\n const keyboardInput = this._keyboardInput;\n\n if (!this._disableKeyboard) {\n keyboardInput.update();\n }\n\n if (!this._disablePitch) {\n yMotion.update(delta);\n }\n\n if (!this._disableYaw) {\n xMotion.update(delta);\n }\n }\n\n /**\n * @hidden\n */\n public updateByCameraPath(delta: number): void {\n this._xMotion.update(delta);\n this._yMotion.update(delta);\n }\n\n /**\n * @hidden\n */\n public updateRange(camera: Camera, zoom: number) {\n const yawRange = camera.getYawRange(zoom);\n const pitchRange = camera.getPitchRange(zoom);\n\n this._xMotion.setRange(yawRange.min, yawRange.max);\n this._yMotion.setRange(pitchRange.min, pitchRange.max);\n }\n\n /**\n * @hidden\n */\n public setZoomScale(val: number) {\n this._zoomScale = val;\n }\n\n /**\n * Resize control to match target size.\n * @ko 컨트롤의 내부 크기를 갱신합니다.\n * @param hfov - Camera horizontal fov in degrees {@ko 카메라의 수평방향 fov값 (도 단위)}\n * @param aspect - Camera aspect {@ko 카메라 가로/세로 비율}\n * @param width - New width {@ko 갱신된 너비}\n * @param height - New height {@ko 갱신된 높이}\n */\n public resize(hfov: number, aspect: number, width: number, height: number) {\n const vfov = toVerticalFov(hfov * DEG_TO_RAD, aspect) * RAD_TO_DEG;\n\n this._screenScale[0] = hfov / width;\n this._screenScale[1] = vfov / height;\n }\n\n public enable(): void {\n if (this._enabled) return;\n\n const element = this._controlEl;\n\n this._mouseInput.enable(element);\n this._touchInput.enable(element);\n this._keyboardInput.enable(element);\n\n this._enabled = true;\n this._enableBlocked = false;\n\n this.trigger(CONTROL_EVENTS.ENABLE, { control: this, updateCursor: true });\n }\n\n public disable(): void {\n if (!this._enabled) return;\n\n this._mouseInput.disable();\n this._touchInput.disable();\n this._keyboardInput.disable();\n\n this._enabled = false;\n\n this.trigger(CONTROL_EVENTS.DISABLE, { updateCursor: true });\n }\n\n public sync(camera: Camera): void {\n this.updateRange(camera, camera.zoom);\n\n this._xMotion.reset(camera.yaw);\n this._yMotion.reset(camera.pitch);\n }\n\n private _bindInputs() {\n const mouseInput = this._mouseInput;\n const touchInput = this._touchInput;\n const keyboardInput = this._keyboardInput;\n\n mouseInput.on(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n mouseInput.on(CONTROL_EVENTS.CHANGE, this._onChange);\n mouseInput.on(CONTROL_EVENTS.INPUT_END, this._onInputEnd);\n\n touchInput.on(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n touchInput.on(CONTROL_EVENTS.CHANGE, this._onChange);\n touchInput.on(CONTROL_EVENTS.INPUT_END, this._onInputEnd);\n\n keyboardInput.on(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n keyboardInput.on(CONTROL_EVENTS.CHANGE, this._onChange);\n keyboardInput.on(CONTROL_EVENTS.INPUT_END, this._onInputEnd);\n }\n\n private _onInputStart = (evt: InputEvents<RotateDeltaType>[typeof CONTROL_EVENTS.INPUT_START]) => {\n this._changedWhileDragging = false;\n this.trigger(CONTROL_EVENTS.INPUT_START, {\n ...evt,\n inputType: \"rotate\"\n });\n };\n\n private _onChange = (evt: InputEvents<RotateDeltaType>[typeof CONTROL_EVENTS.CHANGE]) => {\n const delta = evt.delta;\n const invZoomScale = 1 / this._zoomScale; // Reduce speed on zoom\n const screenScale = this._screenScale;\n const keyboardScale = this._keyboardScale;\n const pointerScale = this._pointerScale;\n\n let scale: [number, number];\n\n if (evt.isKeyboard) {\n scale = [\n keyboardScale[0] * invZoomScale,\n keyboardScale[1] * invZoomScale\n ];\n } else {\n scale = [\n pointerScale[0] * screenScale[0] * invZoomScale,\n pointerScale[1] * screenScale[1] * invZoomScale\n ];\n }\n\n const scaledX = delta.x * scale[0];\n const scaledY = delta.y * scale[1];\n\n this._xMotion.setNewEndByDelta(scaledX);\n this._yMotion.setNewEndByDelta(scaledY);\n\n this._changedWhileDragging = true;\n }\n\n private _onInputEnd = (evt: InputEvents<RotateDeltaType>[typeof CONTROL_EVENTS.INPUT_END]) => {\n this.trigger(CONTROL_EVENTS.INPUT_END, {\n ...evt,\n inputType: \"rotate\"\n });\n\n if (!this._changedWhileDragging && !evt.isKeyboard && !evt.scrolling) {\n this.trigger(CONTROL_EVENTS.STATIC_CLICK, {\n isTouch: evt.isTouch\n });\n }\n\n this._changedWhileDragging = false;\n };\n}\n\nexport default RotateControl;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport * as BROWSER from \"../../const/browser\";\nimport { CONTROL_EVENTS, DEFAULT_ANIMATION_DURATION } from \"../../const/internal\";\nimport { InputEvents } from \"../../type/internal\";\n\nclass WheelInput extends Component<InputEvents<number, WheelEvent>> {\n private _el: HTMLElement | null;\n private _scrollable: boolean;\n private _baseScale: number;\n private _inputTimer: number;\n\n public get scrollable() { return this._scrollable; }\n public set scrollable(val: boolean) { this._scrollable = val; }\n\n public constructor() {\n super();\n\n this._el = null;\n this._baseScale = 0.04;\n this._scrollable = false;\n this._inputTimer = -1;\n }\n\n public enable(element: HTMLElement) {\n if (this._el) return;\n\n element.addEventListener(BROWSER.EVENTS.WHEEL, this._onWheel, { passive: false, capture: false });\n\n this._el = element;\n this._clearTimer();\n }\n\n public disable() {\n const element = this._el;\n if (!element) return;\n\n element.removeEventListener(BROWSER.EVENTS.WHEEL, this._onWheel, false);\n\n this._el = null;\n this._clearTimer();\n }\n\n private _onWheel = (evt: WheelEvent) => {\n const scrollable = this._scrollable;\n\n if (evt.deltaY === 0 || scrollable) return;\n\n evt.preventDefault();\n evt.stopPropagation();\n\n if (this._inputTimer < 0) {\n this.trigger(CONTROL_EVENTS.INPUT_START, {\n srcEvent: evt,\n isTouch: false,\n isKeyboard: false\n });\n } else {\n this._clearTimer();\n }\n\n const delta = this._baseScale * evt.deltaY;\n\n this.trigger(CONTROL_EVENTS.CHANGE, {\n delta,\n isTouch: false,\n isKeyboard: false\n });\n\n this._inputTimer = window.setTimeout(() => {\n this.trigger(CONTROL_EVENTS.INPUT_END, {\n isTouch: false,\n isKeyboard: false,\n scrolling: false\n });\n this._inputTimer = -1;\n }, DEFAULT_ANIMATION_DURATION);\n };\n\n private _clearTimer() {\n window.clearTimeout(this._inputTimer);\n this._inputTimer = -1;\n }\n}\n\nexport default WheelInput;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport * as BROWSER from \"../../const/browser\";\nimport { CONTROL_EVENTS } from \"../../const/internal\";\nimport { InputEvents } from \"../../type/internal\";\n\nclass PinchInput extends Component<InputEvents<number, TouchEvent>> {\n private _el: HTMLElement | null;\n private _baseScale: number;\n private _prevDistance: number;\n private _isFirstTouch: boolean;\n\n public constructor() {\n super();\n\n this._el = null;\n this._baseScale = -0.2;\n this._prevDistance = -1;\n this._isFirstTouch = true;\n }\n\n public enable(element: HTMLElement) {\n if (this._el) return;\n\n element.addEventListener(BROWSER.EVENTS.TOUCH_MOVE, this._onTouchMove, { passive: false, capture: false });\n element.addEventListener(BROWSER.EVENTS.TOUCH_END, this._onTouchEnd);\n\n this._el = element;\n this._prevDistance = -1;\n this._isFirstTouch = true;\n }\n\n public disable() {\n const element = this._el;\n if (!element) return;\n\n element.removeEventListener(BROWSER.EVENTS.TOUCH_MOVE, this._onTouchMove, false);\n element.removeEventListener(BROWSER.EVENTS.TOUCH_END, this._onTouchEnd);\n\n this._el = null;\n }\n\n private _onTouchMove = (evt: TouchEvent) => {\n const touches = evt.touches;\n if (touches.length !== 2) return;\n\n if (!evt.cancelable) return;\n\n evt.preventDefault();\n evt.stopPropagation();\n\n const prevDistance = this._prevDistance;\n\n const diff = [\n touches[0].pageX - touches[1].pageX,\n touches[0].pageY - touches[1].pageY\n ];\n\n const distance = Math.sqrt(diff[0] * diff[0] + diff[1] * diff[1]) * this._baseScale;\n const delta = this._isFirstTouch\n ? 0\n : distance - prevDistance;\n\n if (this._isFirstTouch) {\n this.trigger(CONTROL_EVENTS.INPUT_START, {\n srcEvent: evt,\n isTouch: true,\n isKeyboard: false\n });\n }\n\n this._prevDistance = distance;\n this._isFirstTouch = false;\n\n this.trigger(CONTROL_EVENTS.CHANGE, {\n delta,\n isTouch: true,\n isKeyboard: false\n });\n };\n\n private _onTouchEnd = (evt: TouchEvent) => {\n if (evt.touches.length !== 0) return;\n\n if (!this._isFirstTouch) {\n this.trigger(CONTROL_EVENTS.INPUT_END, {\n isTouch: true,\n isKeyboard: false,\n scrolling: false\n });\n }\n\n this._prevDistance = -1;\n this._isFirstTouch = true;\n };\n}\n\nexport default PinchInput;\n","/*\n* Copyright (c) 2023-present NAVER Corp.\n* egjs projects are licensed under the MIT license\n*/\nimport Component from \"@egjs/component\";\nimport CameraControl from \"./CameraControl\";\nimport WheelInput from \"./input/WheelInput\";\nimport PinchInput from \"./input/PinchInput\";\nimport Camera from \"../core/Camera\";\nimport Motion from \"../core/Motion\";\nimport {\n CONTROL_EVENTS,\n DEFAULT_ANIMATION_DURATION,\n DEFAULT_EASING,\n INFINITE_RANGE\n} from \"../const/internal\";\nimport { ControlEvents, InputEvents } from \"../type/internal\";\n\n/**\n * Options for {@link ZoomControl}\n * @ko {@link ZoomControl}용 옵션들\n * @since 4.0.0\n */\nexport interface ZoomControlOptions {\n /**\n * @copy ZoomControl#scale\n */\n scale: number;\n /**\n * @copy ZoomControl#duration\n */\n duration: number;\n /**\n * @copy ZoomControl#easing\n */\n easing: (x: number) => number;\n}\n\ntype ZoomControlEvents = ControlEvents<number>;\n\n/**\n * Camera's zoom control\n * @ko 카메라의 줌 값을 담당하는 컨트롤\n * @since 4.0.0\n */\nclass ZoomControl extends Component<ZoomControlEvents> implements CameraControl {\n // Options\n private _scale: ZoomControlOptions[\"scale\"];\n\n // Internal values\n private _controlEl: HTMLElement;\n private _enableBlocked: boolean;\n private _wheelInput: WheelInput;\n private _pinchInput: PinchInput;\n private _motion: Motion;\n private _enabled: boolean;\n\n /**\n * Create new ZoomControl instance\n * @ko ZoomControl의 인스턴스를 생성합니다.\n * @param controlEl - Element to attach handlers {@ko 입력을 받을 엘리먼트}\n * @param enableBlocked - Whether to disable control on init {@ko 초기화 과정에서 컨트롤 활성화 여부}\n * @param options - Options for control {@ko 컨트롤 옵션들}\n */\n public constructor(controlEl: HTMLElement, enableBlocked: boolean, {\n scale = 1,\n duration = DEFAULT_ANIMATION_DURATION,\n easing = DEFAULT_EASING\n }: Partial<ZoomControlOptions> = {}) {\n super();\n\n this._scale = scale;\n\n this._controlEl = controlEl;\n this._enableBlocked = enableBlocked;\n this._wheelInput = new WheelInput();\n this._pinchInput = new PinchInput();\n this._motion = new Motion({\n duration,\n easing,\n range: INFINITE_RANGE\n });\n this._enabled = false;\n\n this._bindInputs();\n }\n\n /**\n * @copy CameraControl#enabled\n */\n public get enabled() { return this._enabled; }\n /**\n * @hidden\n */\n public get enableBlocked() { return this._enableBlocked; }\n /**\n * @copy CameraControl#animating\n */\n public get animating() { return this._motion.activated; }\n /**\n * Current zoom value\n * @ko 현재 줌 값\n * @since 4.0.0\n * @readonly\n */\n public get zoom() { return this._motion.val; }\n /**\n * @hidden\n */\n public get end() { return this._motion.end; }\n /**\n * @copy View360#wheelScrollable\n */\n public get scrollable() { return this._wheelInput.scrollable; }\n public set scrollable(val: boolean) {\n this._wheelInput.scrollable = val;\n }\n /**\n * @hidden\n */\n public get range() { return this._motion.range; }\n\n /**\n * @hidden\n */\n public setNewEndByDelta(delta: number): void {\n this._motion.setNewEndByDelta(delta);\n }\n\n /**\n * @hidden\n */\n public reset(val: number): void {\n this._motion.reset(val);\n }\n\n /**\n * Scale factor of the zoom\n * @ko 입력에 의한 줌 배율\n * @default 1\n * @since 4.0.0\n */\n public get scale() { return this._scale; }\n public set scale(val: ZoomControlOptions[\"scale\"]) { this._scale = val; }\n\n /**\n * Duration of the input animation (ms)\n * @ko 회전 애니메이션의 시간 (ms)\n * @default 300\n * @since 4.0.0\n */\n public get duration() { return this._motion.duration; }\n\n /**\n * Easing function of the animation\n * @ko 회전 애니메이션에 적용할 easing 함수\n * @default EASING.EASE_OUT_CUBIC\n * @see EASING\n * @since 4.0.0\n */\n public get easing() { return this._motion.easing; }\n\n public destroy(): void {\n this.disable();\n this._wheelInput.off();\n this._pinchInput.off();\n this.off();\n }\n\n /**\n * @hidden\n */\n public update(delta: number): void {\n if (!this._enabled) return;\n\n const motion = this._motion;\n motion.update(delta);\n }\n\n /**\n * @hidden\n */\n public updateByCameraPath(delta: number): void {\n this._motion.update(delta);\n }\n\n public enable(): void {\n if (this._enabled) return;\n\n const element = this._controlEl;\n this._wheelInput.enable(element);\n this._pinchInput.enable(element);\n\n this._enabled = true;\n this._enableBlocked = false;\n\n this.trigger(CONTROL_EVENTS.ENABLE, { control: this, updateCursor: false });\n }\n\n public disable(): void {\n if (!this._enabled) return;\n\n this._wheelInput.disable();\n this._pinchInput.disable();\n\n this._enabled = false;\n\n this.trigger(CONTROL_EVENTS.DISABLE, { updateCursor: false });\n }\n\n public sync(camera: Camera): void {\n const motion = this._motion;\n const range = camera.getZoomRange();\n\n motion.setRange(range.min, range.max);\n motion.reset(range.current);\n }\n\n private _bindInputs() {\n const wheelInput = this._wheelInput;\n const pinchInput = this._pinchInput;\n\n wheelInput.on(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n wheelInput.on(CONTROL_EVENTS.CHANGE, this._onChange);\n wheelInput.on(CONTROL_EVENTS.INPUT_END, this._onInputEnd);\n\n pinchInput.on(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n pinchInput.on(CONTROL_EVENTS.CHANGE, this._onChange);\n pinchInput.on(CONTROL_EVENTS.INPUT_END, this._onInputEnd);\n }\n\n private _onInputStart = (evt: InputEvents<number>[typeof CONTROL_EVENTS.INPUT_START]) => {\n this.trigger(CONTROL_EVENTS.INPUT_START, {\n ...evt,\n inputType: \"zoom\"\n });\n };\n\n private _onChange = ({ delta }: InputEvents<number>[typeof CONTROL_EVENTS.CHANGE]) => {\n const scale = this._scale;\n const scaledDelta = delta * scale;\n\n this._motion.setNewEndByDelta(scaledDelta);\n };\n\n private _onInputEnd = (evt: InputEvents<number>[typeof CONTROL_EVENTS.INPUT_END]) => {\n this.trigger(CONTROL_EVENTS.INPUT_END, {\n ...evt,\n inputType: \"zoom\"\n });\n };\n}\n\nexport default ZoomControl;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport { quat, vec3 } from \"gl-matrix\";\nimport * as BROWSER from \"../../const/browser\";\nimport { DEG_TO_RAD, RAD_TO_DEG } from \"../../const/internal\";\nimport { InputEvents } from \"../../type/internal\";\nimport { quatToEuler } from \"../../utils\";\n\nexport const ROTATE_CONSTANT = {\n PITCH_DELTA: 1,\n YAW_DELTA_BY_ROLL: 2,\n YAW_DELTA_BY_YAW: 3\n} as const;\n\nROTATE_CONSTANT[ROTATE_CONSTANT.PITCH_DELTA] = {\n targetAxis: [0, 1, 0],\n meshPoint: [0, 0, 1]\n};\nROTATE_CONSTANT[ROTATE_CONSTANT.YAW_DELTA_BY_ROLL] = {\n targetAxis: [0, 1, 0],\n meshPoint: [1, 0, 0]\n};\nROTATE_CONSTANT[ROTATE_CONSTANT.YAW_DELTA_BY_YAW] = {\n targetAxis: [1, 0, 0],\n meshPoint: [0, 0, 1]\n};\n\nclass GyroInput extends Component<InputEvents<{ x: number, y: number, z: number }, MouseEvent>> {\n public quaternion: quat;\n\n private _ignoreRoll: boolean;\n\n private _yawOrigin: number;\n private _yawOffset: number;\n private _orientation: {\n alpha: number;\n beta: number;\n gamma: number;\n }\n private _orientationUpdated: boolean;\n private _needsCalibrate: boolean;\n private _screenOrientation: number;\n private _enabled: boolean;\n\n public get enabled() { return this._enabled; }\n public get orientationUpdated() { return this._orientationUpdated; }\n public get ignoreRoll() { return this._ignoreRoll; }\n public set ignoreRoll(val: boolean) { this._ignoreRoll = val; }\n\n public constructor() {\n super();\n\n this.quaternion = quat.create();\n\n this._orientation = {\n alpha: 0,\n beta: 90,\n gamma: 0\n };\n this._yawOrigin = 0;\n this._yawOffset = 0;\n this._orientationUpdated = false;\n this._screenOrientation = 0;\n this._needsCalibrate = true;\n this._enabled = false;\n }\n\n public enable() {\n if (this._enabled) return;\n\n window.addEventListener(BROWSER.EVENTS.DEVICE_ORIENTATION, this._onDeviceOrientation);\n window.addEventListener(BROWSER.EVENTS.ORIENTATION_CHANGE, this._updateScreenOrientation);\n\n this._updateScreenOrientation();\n this._orientationUpdated = false;\n this._needsCalibrate = true;\n this._enabled = true;\n }\n\n public disable() {\n if (!this._enabled) return;\n\n window.removeEventListener(BROWSER.EVENTS.DEVICE_ORIENTATION, this._onDeviceOrientation);\n window.removeEventListener(BROWSER.EVENTS.ORIENTATION_CHANGE, this._updateScreenOrientation);\n\n this._enabled = false;\n }\n\n public update() {\n this._updateRotation();\n this._orientationUpdated = false;\n }\n\n public collectDelta() {\n if (!this._orientationUpdated) {\n return {\n pitch: 0,\n yaw: 0\n };\n }\n\n const prevRotation = quat.clone(this.quaternion);\n\n this._updateRotation();\n this._orientationUpdated = false;\n\n return this._toEulerDelta(prevRotation, this.quaternion);\n }\n\n public setInitialRotation(yaw: number) {\n this._yawOrigin = yaw;\n }\n\n private _onDeviceOrientation = (evt: DeviceOrientationEvent) => {\n const prevOrientation = this._orientation;\n const { alpha, beta, gamma } = evt;\n\n if (\n alpha == null\n || beta == null\n || gamma == null\n ) return;\n\n prevOrientation.alpha = alpha;\n prevOrientation.beta = beta;\n prevOrientation.gamma = gamma;\n\n this._orientationUpdated = true;\n\n if (this._needsCalibrate) {\n this._needsCalibrate = false;\n this._calibrateSensor();\n }\n };\n\n private _calibrateSensor() {\n const yawOrigin = this._yawOrigin;\n const rotation = this.quaternion;\n\n this._yawOffset = 0;\n this._updateRotation();\n\n const { yaw: sensorYaw } = quatToEuler(rotation);\n this._yawOffset = sensorYaw - yawOrigin;\n this._updateRotation();\n\n this._needsCalibrate = false;\n }\n\n private _updateRotation() {\n const rotation = this.quaternion;\n const { alpha, beta, gamma } = this._orientation;\n\n quat.identity(rotation);\n quat.rotateY(rotation, rotation, (alpha - this._yawOffset) * DEG_TO_RAD);\n quat.rotateX(rotation, rotation, beta * DEG_TO_RAD);\n quat.rotateZ(rotation, rotation, -gamma * DEG_TO_RAD);\n\n const screen = quat.create();\n const screenAngle = -this._screenOrientation * 0.5 * DEG_TO_RAD;\n const world = quat.fromValues(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));\n\n quat.set(screen, 0, Math.sin(screenAngle), 0, Math.cos(screenAngle));\n quat.multiply(rotation, rotation, screen);\n quat.multiply(rotation, rotation, world);\n\n quat.normalize(rotation, rotation);\n }\n\n private _updateScreenOrientation = () => {\n if (window.screen && window.screen.orientation && window.screen.orientation.angle !== undefined) {\n this._screenOrientation = screen.orientation.angle;\n } else if (window.orientation !== undefined) {\n this._screenOrientation = window.orientation >= 0 ?\n window.orientation : 360 + window.orientation;\n } else {\n this._screenOrientation = 0;\n }\n }\n\n private _toEulerDelta(prevQuat: quat, currentQuat: quat) {\n return {\n yaw: this._getDeltaYaw(prevQuat, currentQuat),\n pitch: this._getDeltaPitch(prevQuat, currentQuat),\n };\n }\n\n private _getDeltaYaw(prvQ: quat, curQ: quat): number {\n const yawDeltaByYaw = this._getRotationDelta(prvQ, curQ, ROTATE_CONSTANT.YAW_DELTA_BY_YAW);\n const yawDeltaByRoll = this._getRotationDelta(prvQ, curQ, ROTATE_CONSTANT.YAW_DELTA_BY_ROLL)\n * Math.sin(this._extractPitchFromQuat(curQ));\n\n return yawDeltaByRoll + yawDeltaByYaw;\n }\n\n private _getDeltaPitch(prvQ: quat, curQ: quat): number {\n return this._getRotationDelta(prvQ, curQ, ROTATE_CONSTANT.PITCH_DELTA);\n }\n\n private _getRotationDelta(prevQ: quat, curQ: quat, rotateKind: typeof ROTATE_CONSTANT[keyof typeof ROTATE_CONSTANT]) {\n const targetAxis = vec3.fromValues(\n ROTATE_CONSTANT[rotateKind].targetAxis[0],\n ROTATE_CONSTANT[rotateKind].targetAxis[1],\n ROTATE_CONSTANT[rotateKind].targetAxis[2]\n );\n const meshPoint = ROTATE_CONSTANT[rotateKind].meshPoint;\n\n const prevQuaternion = quat.clone(prevQ);\n const curQuaternion = quat.clone(curQ);\n\n quat.normalize(prevQuaternion, prevQuaternion);\n quat.normalize(curQuaternion, curQuaternion);\n\n let prevPoint = vec3.fromValues(0, 0, 1);\n let curPoint = vec3.fromValues(0, 0, 1);\n\n vec3.transformQuat(prevPoint, prevPoint, prevQuaternion);\n vec3.transformQuat(curPoint, curPoint, curQuaternion);\n vec3.transformQuat(targetAxis, targetAxis, curQuaternion);\n\n const rotateDistance = vec3.dot(targetAxis, vec3.cross(vec3.create(), prevPoint, curPoint));\n const rotateDirection = rotateDistance > 0 ? 1 : -1;\n\n // when counter clock wise, use vec3.fromValues(0,1,0)\n // when clock wise, use vec3.fromValues(0,-1,0)\n // const meshPoint1 = vec3.fromValues(0, 0, 0);\n const meshPoint2 = vec3.fromValues(meshPoint[0], meshPoint[1], meshPoint[2]);\n\n let meshPoint3;\n\n if (rotateKind !== ROTATE_CONSTANT.YAW_DELTA_BY_YAW) {\n meshPoint3 = vec3.fromValues(0, rotateDirection, 0);\n } else {\n meshPoint3 = vec3.fromValues(rotateDirection, 0, 0);\n }\n\n vec3.transformQuat(meshPoint2, meshPoint2, curQuaternion);\n vec3.transformQuat(meshPoint3, meshPoint3, curQuaternion);\n\n const vecU = meshPoint2;\n const vecV = meshPoint3;\n const vecN = vec3.create();\n\n vec3.cross(vecN, vecU, vecV);\n vec3.normalize(vecN, vecN);\n\n const coefficientA = vecN[0];\n const coefficientB = vecN[1];\n const coefficientC = vecN[2];\n\n // a point on the plane\n curPoint = vec3.fromValues(meshPoint[0], meshPoint[1], meshPoint[2]);\n vec3.transformQuat(curPoint, curPoint, curQuaternion);\n\n // a point should project on the plane\n prevPoint = vec3.fromValues(meshPoint[0], meshPoint[1], meshPoint[2]);\n vec3.transformQuat(prevPoint, prevPoint, prevQuaternion);\n\n // distance between prevPoint and the plane\n let distance = Math.abs(\n prevPoint[0] * coefficientA +\n prevPoint[1] * coefficientB +\n prevPoint[2] * coefficientC\n );\n\n const projectedPrevPoint = vec3.create();\n\n vec3.subtract(projectedPrevPoint, prevPoint, vec3.scale(vec3.create(), vecN, distance));\n\n let trigonometricRatio =\n (projectedPrevPoint[0] * curPoint[0] +\n projectedPrevPoint[1] * curPoint[1] +\n projectedPrevPoint[2] * curPoint[2]) /\n (vec3.length(projectedPrevPoint) * vec3.length(curPoint));\n\n // defensive block\n if (trigonometricRatio > 1) {\n trigonometricRatio = 1;\n }\n\n const theta = Math.acos(trigonometricRatio);\n\n const crossVec = vec3.cross(vec3.create(), curPoint, projectedPrevPoint);\n\n distance = coefficientA * crossVec[0]\n + coefficientB * crossVec[1]\n + coefficientC * crossVec[2];\n\n let thetaDirection: number;\n\n if (rotateKind !== ROTATE_CONSTANT.YAW_DELTA_BY_YAW) {\n thetaDirection = distance > 0 ? 1 : -1;\n } else {\n thetaDirection = distance < 0 ? 1 : -1;\n }\n\n const deltaRadian = theta * thetaDirection * rotateDirection;\n\n return deltaRadian * RAD_TO_DEG;\n }\n\n private _extractPitchFromQuat(quaternion: quat) {\n const baseV = vec3.fromValues(0, 0, 1);\n vec3.transformQuat(baseV, baseV, quaternion);\n\n return -1 * Math.atan2(\n baseV[1],\n Math.sqrt(Math.pow(baseV[0], 2) + Math.pow(baseV[2], 2)));\n }\n}\n\nexport default GyroInput;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport CameraControl from \"./CameraControl\";\nimport GyroInput from \"./input/GyroInput\";\nimport Motion from \"../core/Motion\";\nimport Camera from \"../core/Camera\";\nimport * as BROWSER from \"../const/browser\";\nimport { CONTROL_EVENTS } from \"../const/internal\";\nimport { ControlEvents } from \"../type/internal\";\nimport { sensorCanBeEnabledIOS } from \"../utils\";\n\n/**\n * Options for {@link GyroControl}\n * @ko {@link GyroControl}용 옵션들\n * @since 4.0.0\n */\nexport interface GyroControlOptions {\n /**\n * @copy GyroControl#ignoreRoll\n */\n ignoreRoll: boolean;\n}\n\nexport type GyroControlEvents = ControlEvents<void>;\n\n/**\n * Camera's rotation control by gyroscope\n * @ko 자이로스코프를 이용한 회전 컨트롤\n * @since 4.0.0\n */\nclass GyroControl extends Component<GyroControlEvents> implements CameraControl {\n // Options\n private _ignoreRoll: GyroControlOptions[\"ignoreRoll\"];\n\n // Internal values\n private _enableBlocked: boolean;\n private _input: GyroInput;\n\n /**\n * @copy CameraControl#enabled\n */\n public get enabled() { return this._input.enabled; }\n /**\n * @hidden\n */\n public get enableBlocked() { return this._enableBlocked; }\n /**\n * @copy CameraControl#animating\n */\n public get animating() {\n return this._input.enabled && this._input.orientationUpdated;\n }\n\n /**\n * When `true`, ignore gyroscope's roll(z-axis rotation) value.\n * :::caution\n * Setting `false` will ignore camera's range limit.\n * Options like {@link View360Options#yawRange}, {@link View360Options#pitchRange} are ignored, and {@link CylinderProjection} also can't force it's camera range limit.\n * :::\n * @ko `true`일 경우 자이로스코프 입력의 roll(z축 회전)값을 무시합니다.\n * :::caution\n * 이 값을 `false`로 설정할 경우 카메라 범위 제약을 무시합니다.\n * {@link View360Options#yawRange}, {@link View360Options#pitchRange}와 같은 값은 무시되며, {@link CylinderProjection} 사용시에도 범위를 벗어날 수 있습니다.\n * :::\n * @default true\n * @since 4.0.0\n */\n public get ignoreRoll() { return this._ignoreRoll; }\n public set ignoreRoll(val: GyroControlOptions[\"ignoreRoll\"]) { this._ignoreRoll = val; }\n\n /**\n * Return availability of the gyroscope.\n * :::caution\n * This will always return false until user permission under environments like iOS which requires user permission when using gyroscope.\n * :::\n * @ko 자이로스코프 사용 가능 여부를 반환합니다.\n * :::caution\n * iOS와 같이 GyroScope 사용시 사용자 Permission을 요구하는 환경에서는 사용자 Permission을 받기 전까지 항상 `false`입니다.\n * :::\n * @example\n * ```ts\n * const gyroAvailable = await GyroControl.isAvailable();\n * ```\n */\n public static async isAvailable(): Promise<boolean> {\n if (!DeviceMotionEvent) {\n return false;\n }\n\n let onDeviceMotionChange: (evt: DeviceMotionEvent) => void;\n\n const listenDeviceMotion = () => new Promise(res => {\n onDeviceMotionChange = (evt: DeviceMotionEvent) => {\n res(evt.rotationRate && evt.rotationRate.alpha != null);\n };\n\n window.addEventListener(BROWSER.EVENTS.DEVICE_MOTION, onDeviceMotionChange);\n });\n\n const timeout = () => new Promise(res => {\n setTimeout(() => res(false), 1000);\n });\n\n return Promise.race([listenDeviceMotion(), timeout()])\n .then((available: boolean) => {\n window.removeEventListener(BROWSER.EVENTS.DEVICE_MOTION, onDeviceMotionChange);\n\n return available;\n });\n }\n\n /**\n * Request user permission for gyroscope sensor.\n * This can be used in environments like iOS which requires user permission when using gyroscope sensors.\n * @ko 사용자의 sensor permission 취득을 요청합니다.\n * iOS와 같이 gyroscope 사용시 사용자 Permission을 요구하는 환경에서 사용 가능합니다.\n * @returns Whether the permission is granted {@ko 사용자 permission 취득 여부}\n */\n public static async requestSensorPermission(): Promise<boolean> {\n // Request sensor permission, on iOS13+\n if (sensorCanBeEnabledIOS()) {\n return (DeviceMotionEvent as typeof DeviceMotionEvent & {\n requestPermission: () => Promise<string>;\n }).requestPermission().then(permissionState => {\n return permissionState === \"granted\";\n }).catch(() => false);\n }\n\n return true;\n }\n\n /**\n * Create new GyroControl instance\n * @ko GyroControl의 인스턴스를 생성합니다.\n * @param enableBlocked - Whether to disable control on init {@ko 초기화 과정에서 컨트롤 활성화 여부}\n * @param options - Options for control {@ko 컨트롤 옵션들}\n */\n public constructor(enableBlocked: boolean, {\n ignoreRoll = true\n }: Partial<GyroControlOptions> = {}) {\n super();\n\n this._enableBlocked = enableBlocked;\n this._ignoreRoll = ignoreRoll;\n this._input = new GyroInput();\n }\n\n /**\n * @copy CameraControl#destroy\n */\n public destroy(): void {\n this.disable();\n this._input.off();\n this.off();\n }\n\n /**\n * @hidden\n */\n public update(camera: Camera, yaw: Motion, pitch: Motion, zoom: number) {\n if (!this._ignoreRoll) {\n this._updateQuaternion(camera, zoom);\n } else {\n this._updateYawPitch(camera, yaw, pitch, zoom);\n }\n }\n\n /**\n * @copy CameraControl#enable\n */\n public enable(): void {\n if (this._input.enabled) return;\n\n this._input.enable();\n this._enableBlocked = false;\n this.trigger(CONTROL_EVENTS.ENABLE, { control: this, updateCursor: false });\n }\n\n /**\n * @copy CameraControl#disable\n */\n public disable(): void {\n if (!this._input.enabled) return;\n\n this._input.disable();\n this.trigger(CONTROL_EVENTS.DISABLE, { updateCursor: false });\n }\n\n /**\n * @copy CameraControl#sync\n */\n public sync(): void {} // eslint-disable-line @typescript-eslint/no-empty-function\n\n private _updateYawPitch(camera: Camera, yaw: Motion, pitch: Motion, zoom: number) {\n const input = this._input;\n if (!input.enabled) return;\n\n const {\n yaw: yawDelta,\n pitch: pitchDelta\n } = input.collectDelta();\n\n yaw.add(yawDelta);\n pitch.add(pitchDelta);\n\n camera.lookAt({\n yaw: yaw.val,\n pitch: pitch.val,\n zoom\n });\n }\n\n private _updateQuaternion(camera: Camera, zoom: number) {\n const input = this._input;\n if (!input.enabled) return;\n\n input.update();\n camera.rotate(input.quaternion, zoom);\n }\n}\n\nexport default GyroControl;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport CameraControl from \"./CameraControl\";\nimport RotateControl, { RotateControlEvents, RotateControlOptions } from \"./RotateControl\";\nimport ZoomControl, { ZoomControlOptions } from \"./ZoomControl\";\nimport GyroControl, { GyroControlOptions } from \"./GyroControl\";\nimport Camera from \"../core/Camera\";\nimport CameraAnimation from \"../core/CameraAnimation\";\nimport * as BROWSER from \"../const/browser\";\nimport { CAMERA_EVENTS, CONTROL_EVENTS } from \"../const/internal\";\nimport { ValueOf } from \"../type/utils\";\nimport { getObjectOption, hfovToZoom } from \"../utils\";\n\n/**\n * Options for {@link PanoControl}\n * @ko {@link PanoControl}용 옵션들\n * @since 4.0.0\n */\nexport interface PanoControlOptions {\n /**\n * @copy View360#useGrabCursor\n */\n useGrabCursor: boolean;\n /**\n * @copy View360#scrollable\n */\n scrollable: boolean;\n /**\n * @copy View360#wheelScrollable\n */\n wheelScrollable: boolean;\n /**\n * @copy View360#disableContextMenu\n */\n disableContextMenu: boolean;\n /**\n * Options for {@link RotateControl}.\n * `false` to disable rotation.\n * @ko {@link RotateControl}용 옵션들.\n * `false`일 경우 회전이 비활성화됩니다.\n * @since 4.0.0\n */\n rotate: boolean | Partial<RotateControlOptions>;\n /**\n * Options for {@link ZoomControl}.\n * `false` to disable zoom.\n * @ko {@link ZoomControl}용 옵션들.\n * `false`일 경우 줌이 비활성화됩니다.\n * @since 4.0.0\n */\n zoom: boolean | Partial<ZoomControlOptions>;\n /**\n * Options for {@link GyroControl}.\n * `false` to disable gyroscope control.\n * @ko {@link GyroControl}용 옵션들.\n * `false`일 경우 자이로스코프를 통한 컨트롤이 비활성화됩니다.\n * @since 4.0.0\n */\n gyro: boolean | Partial<GyroControlOptions>;\n}\n\n/**\n * Panorama control for View360\n * @ko View360용 파노라마 컨트롤\n * @since 4.0.0\n */\nclass PanoControl {\n // Options\n private _useGrabCursor: PanoControlOptions[\"useGrabCursor\"];\n private _disableContextMenu: PanoControlOptions[\"disableContextMenu\"];\n\n // Internal Values\n private _camera: Camera;\n private _controlEl: HTMLElement;\n private _rotateControl: RotateControl;\n private _zoomControl: ZoomControl;\n private _gyroControl: GyroControl;\n private _ignoreZoomScale: boolean;\n private _enabled: boolean;\n\n /**\n * @copy View360#useGrabCursor\n */\n public get useGrabCursor() { return this._useGrabCursor; }\n public set useGrabCursor(val: PanoControlOptions[\"useGrabCursor\"]) {\n if (val === this._useGrabCursor) return;\n\n this._useGrabCursor = val;\n\n if (val && this._enabled) {\n this._setCursor(BROWSER.CURSOR.GRAB);\n } else if (!val) {\n this._setCursor(BROWSER.CURSOR.NONE);\n }\n }\n\n /**\n * @copy View360#disableContextMenu\n */\n public get disableContextMenu() { return this._disableContextMenu; }\n public set disableContextMenu(val: PanoControlOptions[\"disableContextMenu\"]) {\n if (val === this._disableContextMenu) return;\n\n this._disableContextMenu = val;\n\n if (val && this._enabled) {\n this._blockContextMenu();\n } else if (!val) {\n this._restoreContextMenu();\n }\n }\n\n /**\n * @copy View360#disableContextMenu\n */\n public get scrollable() { return this._rotateControl.scrollable; }\n public set scrollable(val: PanoControlOptions[\"scrollable\"]) { this._rotateControl.scrollable = val; }\n /**\n * @copy View360#disableContextMenu\n */\n public get wheelScrollable() { return this._zoomControl.scrollable; }\n public set wheelScrollable(val: PanoControlOptions[\"wheelScrollable\"]) { this._zoomControl.scrollable = val; }\n /**\n * When `true`, disables rotation slow-down by zoom-value.\n * @ko `true`일 경우 줌 된 정도에 따라 회전속도를 늦추는 동작을 비활성화합니다.\n * @since 4.0.0\n */\n public get ignoreZoomScale() { return this._ignoreZoomScale; }\n public set ignoreZoomScale(val: boolean) { this._ignoreZoomScale = val; }\n\n /**\n * Whether the control is enabled or not\n * @ko 컨트롤 활성화 여부를 가리키는 값\n * @readonly\n * @since 4.0.0\n */\n public get enabled() { return this._enabled; }\n /**\n * @copy View360#rotate\n */\n public get rotate() { return this._rotateControl; }\n /**\n * @copy View360#zoom\n */\n public get zoom() { return this._zoomControl; }\n /**\n * @copy View360#gyro\n */\n public get gyro() { return this._gyroControl; }\n\n /**\n * Whether one of the controls is animating at the moment\n * @ko 현재 컨트롤 중 하나라도 동작중인지 여부를 나타내는 값\n * @readonly\n * @since 4.0.0\n */\n public get animating() {\n return this._rotateControl.animating\n || this._zoomControl.animating\n || this._gyroControl.animating;\n }\n\n /**\n * Create new instance.\n * @ko 새 인스턴스를 생성합니다.\n * @param element - Canvas element {@ko 캔버스 엘리먼트}\n * @param camera - Camera instance {@ko Camera 인스턴스}\n * @param options - Options for PanoControl {@ko PanoControl 옵션들}\n */\n public constructor(element: HTMLElement, camera: Camera, {\n useGrabCursor,\n scrollable,\n wheelScrollable,\n disableContextMenu,\n rotate,\n zoom,\n gyro\n }: PanoControlOptions) {\n // Bind Options\n this._useGrabCursor = useGrabCursor;\n this._disableContextMenu = disableContextMenu;\n\n // Set internal values\n this._camera = camera;\n this._controlEl = element;\n this._ignoreZoomScale = false;\n this._enabled = false;\n\n this._rotateControl = new RotateControl(element, !rotate, getObjectOption(rotate));\n this._zoomControl = new ZoomControl(element, !zoom, getObjectOption(zoom));\n this._gyroControl = new GyroControl(!gyro, getObjectOption(gyro));\n\n this._rotateControl.scrollable = scrollable;\n this._zoomControl.scrollable = wheelScrollable;\n\n this._bindEvents();\n }\n\n /**\n * Destroy the instance and remove all event listeners attached.\n * This also will reset CSS cursor to initial.\n * @ko 인스턴스를 삭제하고 부착된 모든 이벤트 리스너를 제거합니다.\n * 또한, 캔버스에 적용된 CSS cursor도 제거합니다.\n * @since 4.0.0\n */\n public destroy(): void {\n this.disable();\n this._rotateControl.destroy();\n this._zoomControl.destroy();\n this._setCursor(BROWSER.CURSOR.NONE);\n }\n\n /**\n * Resize control to match target size.\n * @ko 컨트롤이 내부에 캐시하고 있는 크기값을 갱신합니다.\n * @param width New width {@ko 변경된 너비}\n * @param height New height {@ko 변경된 높이}\n * @since 4.0.0\n */\n public resize(width: number, height: number): void {\n const camera = this._camera;\n\n this._rotateControl.resize(camera.fov, camera.aspect, width, height);\n }\n\n /**\n * Enable this control and add event listeners.\n * @ko 컨트롤을 활성화하고 이벤트 리스너들을 추가합니다.\n * @since 4.0.0\n */\n public async enable(): Promise<void> {\n if (this._enabled) return;\n\n if (!this._rotateControl.enableBlocked) {\n this._rotateControl.enable();\n }\n\n if (!this._zoomControl.enableBlocked) {\n this._zoomControl.enable();\n }\n\n if (!this._gyroControl.enableBlocked) {\n if (await GyroControl.isAvailable()) {\n this._gyroControl.enable();\n }\n }\n\n this.sync();\n\n if (this._disableContextMenu) {\n this._blockContextMenu();\n }\n\n this._enabled = true;\n }\n\n /**\n * Disable this control and remove all event listeners\n * @ko 컨트롤을 비활성화하고 모든 이벤트 리스너들을 제거합니다.\n * @since 4.0.0\n */\n public disable(): void {\n if (!this._enabled) return;\n\n this._rotateControl.disable();\n this._zoomControl.disable();\n this._gyroControl.disable();\n\n this._restoreContextMenu();\n\n this._enabled = false;\n }\n\n /**\n * Update control by given deltaTime\n * @ko 컨트롤을 주어진 시간만큼 업데이트합니다.\n * @param delta Number of milisec to update {@ko 업데이트할 시간, 밀리초 단위}\n * @since 4.0.0\n * @internal\n */\n public update(delta: number): void {\n const camera = this._camera;\n const rotateControl = this._rotateControl;\n const zoomControl = this._zoomControl;\n const gyroControl = this._gyroControl;\n\n zoomControl.update(delta);\n const zoom = hfovToZoom(camera.fov, zoomControl.zoom);\n\n // Slow down rotation on zoom-in\n const zoomScale = this._ignoreZoomScale ? 1 : Math.max(zoom, 1);\n rotateControl.setZoomScale(zoomScale);\n rotateControl.updateRange(camera, zoom);\n rotateControl.update(delta);\n\n const yaw = rotateControl.yaw;\n const pitch = rotateControl.pitch;\n\n if (gyroControl.enabled) {\n gyroControl.update(camera, yaw, pitch, zoom);\n } else {\n camera.lookAt({\n yaw: yaw.val,\n pitch: pitch.val,\n zoom\n });\n }\n }\n\n /**\n * @hidden\n */\n public updateByCameraPath(delta: number): void {\n const camera = this._camera;\n const rotateControl = this._rotateControl;\n const zoomControl = this._zoomControl;\n const gyroControl = this._gyroControl;\n\n zoomControl.updateByCameraPath(delta);\n const zoom = hfovToZoom(camera.fov, zoomControl.zoom);\n\n const zoomScale = this._ignoreZoomScale ? 1 : Math.max(zoom, 1);\n rotateControl.setZoomScale(zoomScale);\n rotateControl.updateRange(camera, zoom);\n rotateControl.updateByCameraPath(delta);\n\n const yaw = rotateControl.yaw;\n const pitch = rotateControl.pitch;\n\n if (gyroControl.enabled) {\n gyroControl.update(camera, yaw, pitch, zoom);\n } else {\n camera.lookAt({\n yaw: yaw.val,\n pitch: pitch.val,\n zoom\n });\n }\n }\n\n /**\n * Synchronize this control's state to current camera state\n * @ko 컨트롤을 카메라의 현재 상태와 동기화합니다.\n * @since 4.0.0\n */\n public sync(): void {\n const camera = this._camera;\n\n this._zoomControl.sync(camera);\n this._rotateControl.sync(camera);\n }\n\n private _blockContextMenu() {\n const el = this._controlEl;\n\n el.addEventListener(BROWSER.EVENTS.CONTEXT_MENU, this._preventContextMenu);\n }\n\n private _restoreContextMenu() {\n const el = this._controlEl;\n\n el.removeEventListener(BROWSER.EVENTS.CONTEXT_MENU, this._preventContextMenu);\n }\n\n private _preventContextMenu = (evt: MouseEvent) => {\n evt.preventDefault();\n };\n\n private _setCursor(newCursor: ValueOf<typeof BROWSER.CURSOR>) {\n if (!this._useGrabCursor && newCursor !== BROWSER.CURSOR.NONE) return;\n\n const targetEl = this._controlEl;\n targetEl.style.cursor = newCursor;\n }\n\n private _bindEvents() {\n const rotateControl = this._rotateControl;\n const zoomControl = this._zoomControl;\n\n rotateControl.on(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n rotateControl.on(CONTROL_EVENTS.INPUT_END, this._onInputEnd);\n rotateControl.on(CONTROL_EVENTS.ENABLE, this._onEnable);\n rotateControl.on(CONTROL_EVENTS.DISABLE, this._onDisable);\n zoomControl.on(CONTROL_EVENTS.ENABLE, this._onEnable);\n zoomControl.on(CONTROL_EVENTS.DISABLE, this._onDisable);\n this._camera.on(CAMERA_EVENTS.ANIMATION_END, this._onCameraAnimationEnd);\n }\n\n private _onInputStart = (evt: RotateControlEvents[typeof CONTROL_EVENTS.INPUT_START]) => {\n if (this._useGrabCursor && !evt.isKeyboard) {\n this._setCursor(BROWSER.CURSOR.GRABBING);\n }\n };\n\n private _onInputEnd = (evt: RotateControlEvents[typeof CONTROL_EVENTS.INPUT_END]) => {\n if (this._useGrabCursor && !evt.isKeyboard) {\n this._setCursor(BROWSER.CURSOR.GRAB);\n }\n };\n\n private _onEnable = ({\n control,\n updateCursor\n }: {\n control: CameraControl;\n updateCursor: boolean;\n }) => {\n if (updateCursor && this._useGrabCursor) {\n this._setCursor(BROWSER.CURSOR.GRAB);\n }\n\n control.sync(this._camera);\n };\n\n private _onDisable = ({\n updateCursor\n }: {\n updateCursor: boolean\n }) => {\n if (updateCursor) {\n this._setCursor(BROWSER.CURSOR.NONE);\n }\n };\n\n private _onCameraAnimationEnd = ({ animation }: { animation: CameraAnimation }) => {\n animation.getFinishPromise().then(() => {\n this.sync();\n });\n };\n}\n\nexport default PanoControl;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport TextureVideo from \"./TextureVideo\";\nimport TextureCube from \"./TextureCube\";\n\n/**\n * @hidden\n */\nabstract class Texture {\n public width: number;\n public height: number;\n public flipY: boolean;\n public wrapS: number;\n public wrapT: number;\n\n public constructor({\n width,\n height,\n flipY\n }: {\n width: number;\n height: number;\n flipY: boolean;\n }) {\n this.width = width;\n this.height = height;\n this.flipY = flipY;\n this.wrapS = WebGLRenderingContext.CLAMP_TO_EDGE;\n this.wrapT = WebGLRenderingContext.CLAMP_TO_EDGE;\n }\n\n public destroy() {\n // DO_NOTHING\n }\n\n public isVideo(): this is TextureVideo {\n return false;\n }\n\n public isCube(): this is TextureCube {\n return false;\n }\n}\n\nexport default Texture;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Texture from \"./Texture\";\n\n/**\n * @hidden\n */\nclass Texture2D extends Texture {\n public source: Exclude<TexImageSource, ImageData>;\n\n public constructor({\n source,\n width,\n height,\n flipY\n }: {\n source: Exclude<TexImageSource, ImageData>;\n width: number;\n height: number;\n flipY: boolean;\n }) {\n super({\n width,\n height,\n flipY\n });\n\n this.source = source;\n }\n}\n\nexport default Texture2D;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Texture2D from \"./Texture2D\";\nimport type Hls from \"hls.js\";\n\n/**\n * @hidden\n */\nclass TextureVideo extends Texture2D {\n public source: HTMLVideoElement;\n public hls: Hls | null = null;\n\n public destroy() {\n const video = this.source;\n\n if (this.hls) {\n this.hls.destroy();\n this.hls = null;\n }\n\n video.pause();\n video.removeAttribute(\"src\");\n video.load();\n }\n\n public isVideo(): this is TextureVideo { return true; }\n\n public isPaused() {\n const video = this.source;\n\n return video.paused || video.ended || video.readyState <= 2;\n }\n\n public hasAudio() {\n const video = this.source as any;\n\n if (video.audioTracks) {\n return video.audioTracks.length > 0;\n }\n\n if (video.webkitAudioDecodedByteCount != null) {\n return video.webkitAudioDecodedByteCount > 0;\n }\n\n if (video.mozHasAudio != null) {\n return video.mozHasAudio;\n }\n\n // We don't know whether the video has audio or not, return true\n return true;\n }\n}\n\nexport default TextureVideo;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Texture from \"./Texture\";\n\n/**\n * @hidden\n */\nclass TextureCube extends Texture {\n public sources: TexImageSource[];\n\n public constructor({\n sources,\n width,\n height,\n flipY\n }: {\n sources: TexImageSource[];\n width: number;\n height: number;\n flipY: boolean;\n }) {\n super({\n width,\n height,\n flipY\n });\n\n this.sources = sources;\n }\n\n public isCube(): this is TextureCube { return true; }\n}\n\nexport default TextureCube;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ImReady from \"@egjs/imready\";\nimport Texture from \"../texture/Texture\";\nimport Texture2D from \"../texture/Texture2D\";\nimport TextureVideo from \"../texture/TextureVideo\";\nimport TextureCube from \"../texture/TextureCube\";\nimport { getObjectOption, isString } from \"../utils\";\nimport { VideoConfig } from \"../type/external\";\nimport { ProjectionOptions } from \"../projection/Projection\";\nimport Hls from \"hls.js\";\n\ntype HlsConstructor = (new (config?: Hls.Config) => Hls) & { isSupported: () => boolean };\n\nconst getHls = (): HlsConstructor | null => {\n // hls.js 通过静态 import 加载,检查是否可用\n if (Hls && typeof Hls.isSupported === \"function\") {\n return Hls as unknown as HlsConstructor;\n }\n return null;\n};\n\n/**\n * @hidden\n */\nclass TextureLoader {\n private _loadChecker: ImReady;\n private _debug: boolean;\n public pendingHls: Hls | null = null;\n\n constructor(debug: boolean = false) {\n this._loadChecker = new ImReady();\n this._debug = debug;\n }\n\n public async load(src: ProjectionOptions[\"src\"], video: ProjectionOptions[\"video\"]): Promise<Texture> {\n if (video) {\n return this.loadVideo(src, getObjectOption(video));\n } else {\n if (Array.isArray(src) && src.length > 1) {\n return this.loadCubeImage(src);\n } else {\n const imgSrc = Array.isArray(src) ? src[0] : src;\n return this.loadImage(imgSrc);\n }\n }\n }\n\n public async loadImage(src: string | HTMLElement): Promise<Texture2D> {\n const images = this._toImageArray(src);\n\n return this._load(images, resolve => {\n const image = images[0];\n\n resolve(new Texture2D({\n source: image,\n width: image.naturalWidth,\n height: image.naturalHeight,\n flipY: true\n }));\n });\n }\n\n public async loadCubeImage(src: Array<string | HTMLElement>): Promise<TextureCube> {\n const images = this._toImageArray(src);\n\n return this._load(images, resolve => {\n resolve(new TextureCube({\n sources: images,\n width: images[0].naturalWidth,\n height: images[0].naturalHeight,\n flipY: false\n }));\n });\n }\n\n public async loadVideo(src: ProjectionOptions[\"src\"], videoConfig: Partial<VideoConfig>): Promise<TextureVideo> {\n const config: VideoConfig = {\n autoplay: true,\n muted: true,\n loop: false,\n volume: 1,\n ...videoConfig,\n };\n const hlsConfig = config.hlsConfig;\n const hlsEnabled = !!hlsConfig?.enabled;\n const hlsForce = !!hlsConfig?.force;\n const hlsSource = hlsEnabled ? this._getHlsSource(src) : null;\n const shouldUseHls = hlsEnabled && (hlsForce || this._isM3u8Source(hlsSource));\n const hlsModule = shouldUseHls ? getHls() : null;\n const hasHlsSupport = !!hlsModule && typeof hlsModule.isSupported === \"function\";\n const useHlsJs = shouldUseHls && hasHlsSupport && hlsModule.isSupported();\n const useExistingVideo = src instanceof HTMLVideoElement;\n const video = this._toVideoElement(src, config, useHlsJs);\n this._attachVideoDebugListeners(video);\n let hls: Hls | null = null;\n\n if (shouldUseHls) {\n if (!hlsSource) {\n if (this._debug) {\n console.info(\"[View360][TextureLoader] HLS enabled but no source URL provided.\");\n }\n } else if (useHlsJs && hlsModule) {\n hls = new hlsModule(hlsConfig?.config);\n this.pendingHls = hls;\n hls.loadSource(hlsSource);\n hls.attachMedia(video);\n } else if (!hasHlsSupport && this._debug) {\n console.info(\"[View360][TextureLoader] HLS enabled but hls.js is unavailable.\");\n } else if (video.canPlayType(\"application/vnd.apple.mpegurl\")) {\n video.src = hlsSource;\n } else if (this._debug) {\n console.info(\"[View360][TextureLoader] HLS source provided but not supported by this browser.\");\n }\n }\n\n return this._load([video], resolve => {\n const { autoplay, muted } = config;\n\n if (!useExistingVideo) {\n this._logVideoState(video, \"ready-before-reset\");\n video.currentTime = 0;\n this._logVideoState(video, \"ready-after-reset\");\n }\n if (autoplay && muted) {\n const playPromise = video.play();\n\n if (playPromise && typeof playPromise.catch === \"function\") {\n playPromise.catch(err => {\n if (this._debug) {\n console.info(\"[View360][TextureLoader] autoplay rejected:\", err);\n this._logVideoState(video, \"autoplay-rejected\");\n }\n });\n }\n }\n\n const texture = new TextureVideo({\n source: video,\n width: video.videoWidth,\n height: video.videoHeight,\n flipY: true\n });\n texture.hls = hls;\n resolve(texture);\n });\n }\n\n private _load<T>(content: HTMLElement[], onLoad: (resolve: (value: T) => void) => void): Promise<T> {\n const loader = this._loadChecker;\n\n return new Promise((resolve, reject) => {\n loader.once(\"ready\", evt => {\n if (evt.errorCount > 0) return;\n\n onLoad(resolve);\n });\n\n loader.once(\"error\", reject);\n loader.check(content);\n });\n }\n\n private _toImageArray(src: ProjectionOptions[\"src\"]): HTMLImageElement[] {\n const srcs = Array.isArray(src) ? src : [src];\n\n return srcs.map(source => {\n if (isString(source)) {\n const imgEl = new Image();\n\n imgEl.crossOrigin = \"anonymous\";\n imgEl.src = source;\n\n return imgEl;\n } else {\n return source as HTMLImageElement;\n }\n });\n }\n\n private _toVideoElement(src: ProjectionOptions[\"src\"], {\n muted,\n loop,\n volume\n }: VideoConfig, skipSource: boolean = false): HTMLVideoElement {\n if (src instanceof HTMLVideoElement) {\n return src;\n }\n\n const video = document.createElement(\"video\");\n\n video.crossOrigin = \"anonymous\";\n video.playsInline = true;\n video.setAttribute(\"webkit-playsinline\", \"\");\n video.muted = muted;\n video.volume = volume;\n video.loop = loop;\n\n if (!skipSource) {\n if (Array.isArray(src)) {\n src.forEach(source => this._appendSourceElement(video, source));\n } else {\n this._appendSourceElement(video, src);\n }\n }\n\n if (!skipSource) {\n const sourceCount = video.querySelectorAll(\"source\").length;\n if (sourceCount > 0 && video.readyState < 1) {\n video.load();\n }\n }\n\n return video;\n }\n\n private _attachVideoDebugListeners(video: HTMLVideoElement): void {\n if (!this._debug) return;\n\n const once = (event: string) => {\n const handler = () => {\n this._logVideoState(video, `event:${event}`);\n video.removeEventListener(event, handler);\n };\n\n video.addEventListener(event, handler);\n };\n\n [\"loadedmetadata\", \"seeking\", \"seeked\", \"timeupdate\", \"play\", \"pause\"].forEach(once);\n }\n\n private _logVideoState(video: HTMLVideoElement, label: string): void {\n if (!this._debug) return;\n\n let seekableStart: number | null = null;\n let seekableEnd: number | null = null;\n\n if (video.seekable && video.seekable.length > 0) {\n seekableStart = video.seekable.start(0);\n seekableEnd = video.seekable.end(0);\n }\n\n console.info(\"[View360][TextureLoader]\", label, {\n currentTime: video.currentTime,\n duration: video.duration,\n readyState: video.readyState,\n paused: video.paused,\n ended: video.ended,\n seekableStart,\n seekableEnd,\n currentSrc: video.currentSrc || video.src\n });\n }\n\n private _getHlsSource(src: ProjectionOptions[\"src\"]): string | null {\n if (isString(src)) {\n return src;\n }\n\n if (Array.isArray(src)) {\n for (const source of src) {\n if (isString(source)) {\n return source;\n }\n if (source instanceof HTMLSourceElement) {\n return source.src;\n }\n }\n return null;\n }\n\n if (src instanceof HTMLSourceElement) {\n return src.src;\n }\n\n if (src instanceof HTMLVideoElement) {\n const sourceEl = src.querySelector(\"source\");\n return src.currentSrc || src.src || (sourceEl ? sourceEl.src : null);\n }\n\n return null;\n }\n\n private _isM3u8Source(src: string | null): boolean {\n if (!src) return false;\n\n return /\\.m3u8($|[?#])/i.test(src);\n }\n\n private _appendSourceElement(video: HTMLMediaElement, src: string | HTMLElement) {\n if (src instanceof HTMLSourceElement) {\n return src;\n }\n\n const sourceEl = document.createElement(\"source\");\n sourceEl.src = src as string;\n video.appendChild(sourceEl);\n }\n}\n\nexport default TextureLoader;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\n\n/**\n * @internal\n */\nclass FrameAnimator {\n public maxDeltaTime: number;\n\n private _context: Window | XRSession;\n private _rafId: number;\n private _rafTimer: number;\n private _lastUpdateTime: number;\n\n /** */\n public constructor(maxDeltaTime: number, context: Window | XRSession = window) {\n this.maxDeltaTime = maxDeltaTime;\n\n this._context = context;\n this._rafId = -1;\n this._rafTimer = -1;\n this._lastUpdateTime = -1;\n }\n\n public start(callback: (delta: number, ...args: any[]) => any) {\n const context = this._context;\n\n // No context / callback set\n if (!context || !callback) return;\n\n // Animation already started\n if (this._rafId >= 0 || this._rafTimer >= 0) return;\n\n const loop = (_time: number, frame?: XRFrame) => {\n const time = Date.now();\n const delta = Math.min(time - this._lastUpdateTime, this.maxDeltaTime * 1000);\n\n callback(delta, frame);\n\n this._lastUpdateTime = time;\n this._rafId = context.requestAnimationFrame(loop);\n };\n\n this._lastUpdateTime = Date.now();\n this._rafId = context.requestAnimationFrame(loop);\n }\n\n public stop() {\n if (this._rafId >= 0) {\n this._context.cancelAnimationFrame(this._rafId);\n }\n\n if (this._rafTimer >= 0) {\n clearTimeout(this._rafTimer);\n }\n\n this._rafId = -1;\n this._rafTimer = -1;\n }\n\n public changeContext(context: Window | XRSession) {\n this.stop();\n this._context = context;\n }\n}\n\nexport default FrameAnimator;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport * as BROWSER from \"../const/browser\";\n\n/**\n * Automatic resizer that uses both ResizeObserver and window resize event\n */\nclass AutoResizer {\n private _enabled: boolean;\n private _resizeObserver: ResizeObserver | null;\n private _useResizeObserver: boolean;\n private _onResize: () => any;\n\n public get useResizeObserver() { return this._useResizeObserver; }\n\n /**\n * Returns whether AutoResizer is enabled\n */\n public get enabled() { return this._enabled; }\n\n /** */\n public constructor(useResizeObserver: boolean, onResize: () => any) {\n this._useResizeObserver = useResizeObserver;\n\n this._enabled = false;\n this._resizeObserver = null;\n this._onResize = onResize;\n }\n\n /**\n * Enable resizer\n */\n public enable(element: HTMLElement): this {\n if (this._enabled) {\n this.disable();\n }\n\n if (this._useResizeObserver && !!window.ResizeObserver) {\n const bbox = element.getBoundingClientRect();\n const resizeImmediate = bbox.width !== 0 || bbox.height !== 0;\n\n const resizeObserver = new ResizeObserver(resizeImmediate ? this._skipFirstResize : this._onResize);\n\n resizeObserver.observe(element);\n\n this._resizeObserver = resizeObserver;\n } else {\n window.addEventListener(BROWSER.EVENTS.RESIZE, this._onResize);\n }\n\n this._enabled = true;\n\n return this;\n }\n\n /**\n * Disable resizer\n */\n public disable(): this {\n if (!this._enabled) return this;\n\n const resizeObserver = this._resizeObserver;\n if (resizeObserver) {\n resizeObserver.disconnect();\n this._resizeObserver = null;\n } else {\n window.removeEventListener(BROWSER.EVENTS.RESIZE, this._onResize);\n }\n\n this._enabled = false;\n\n return this;\n }\n\n // eslint-disable-next-line @typescript-eslint/member-ordering\n private _skipFirstResize = (() => {\n let isFirstResize = true;\n\n return (() => {\n if (isFirstResize) {\n isFirstResize = false;\n\n return;\n }\n this._onResize();\n });\n })();\n}\n\nexport default AutoResizer;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Camera from \"./Camera\";\nimport PanoControl from \"../control/PanoControl\";\nimport View360 from \"../View360\";\nimport * as BROWSER from \"../const/browser\";\nimport { CONTROL_EVENTS } from \"../const/internal\";\nimport { circulate, getObjectOption } from \"../utils\";\n\n/**\n * Options for {@link Autoplay}\n * @ko {@link Autoplay}용 옵션들\n * @since 4.0.0\n */\nexport interface AutoplayOptions {\n /**\n * @copy Autoplay#delay\n */\n delay: number;\n /**\n * @copy Autoplay#delayOnMouseLeave\n */\n delayOnMouseLeave: number;\n /**\n * @copy Autoplay#speed\n */\n speed: number;\n /**\n * @copy Autoplay#pauseOnHover\n */\n pauseOnHover: boolean;\n /**\n * @copy Autoplay#canInterrupt\n */\n canInterrupt: boolean;\n /**\n * @copy Autoplay#disableOnInterrupt\n */\n disableOnInterrupt: boolean;\n}\n\n/**\n * A manager class for autoplay feature.\n * @ko Autoplay 기능의 매니저 클래스.\n * @since 4.0.0\n */\nclass Autoplay {\n // Options\n private _delay: number;\n private _delayOnMouseLeave: number;\n private _speed: number;\n private _pauseOnHover: boolean;\n private _canInterrupt: boolean;\n private _disableOnInterrupt: boolean;\n\n // Internal values\n private _enableBlocked: boolean;\n private _camera: Camera;\n private _control: PanoControl;\n private _element: HTMLElement;\n private _enabled: boolean;\n private _interrupted: boolean;\n private _interruptionTimer: number;\n private _hovering: boolean;\n\n /**\n * Whether autoplay is enabled or not\n * @ko 자동재생 활성화 여부를 나타내는 값\n * @readonly\n * @since 4.0.0\n */\n public get enabled() { return this._enabled; }\n /**\n * @hidden\n */\n public get enableBlocked() { return this._enableBlocked; }\n /**\n * Whether autoplay is updating the camera at the moment\n * @ko 현재 자동재생이 동작중인지 여부를 나타내는 값\n * @readonly\n * @since 4.0.0\n */\n public get playing() {\n return this._enabled && !this._interrupted;\n }\n\n /**\n * Reactivation delay after mouse input in milisecond.\n * @ko 재활성화되기까지의 시간 (밀리초 단위)\n * @default 2000\n * @since 4.0.0\n */\n public get delay() { return this._delay; }\n public set delay(val: number) { this._delay = val; }\n\n /**\n * Reactivation delay after mouse leave when using {@link AutoplayOptions#pauseOnHover}\n * @ko {@link AutoplayOptions#pauseOnHover} 사용시 마우스가 캔버스 영역을 떠난 뒤 자동재생이 다시 활성화되기까지의 시간\n * @default 0\n * @since 4.0.0\n */\n public get delayOnMouseLeave() { return this._delayOnMouseLeave; }\n public set delayOnMouseLeave(val: number) { this._delayOnMouseLeave = val; }\n\n /**\n * Y-axis(yaw) rotation speed\n * @ko Y-축 회전(yaw)의 속도\n * @default 1\n * @since 4.0.0\n */\n public get speed() { return this._speed; }\n public set speed(val: number) { this._speed = val; }\n\n /**\n * Whether to pause rotation on mouse hover\n * @ko 마우스가 캔버스 영역에 들어왔을 때 자동재생을 정지할지 여부\n * @default false\n * @since 4.0.0\n */\n public get pauseOnHover() { return this._pauseOnHover; }\n public set pauseOnHover(val: boolean) { this._pauseOnHover = val; }\n\n /**\n * Whether user can interrupt the rotation with click/wheel input\n * @ko 클릭이나 휠같은 사용자 인터랙션시 자동재생을 멈출지 여부\n * @default true\n * @since 4.0.0\n */\n public get canInterrupt() { return this._canInterrupt; }\n public set canInterrupt(val: boolean) { this._canInterrupt = val; }\n\n /**\n * Whether to disable autoplay on user interrupt\n * @ko 사용자 동작에 의해 자동재생이 정지할 때, {@link Autoplay#disable}을 호출하여 자동재생을 영구히 정지할지 여부\n * @default false\n * @since 4.0.0\n */\n public get disableOnInterrupt() { return this._disableOnInterrupt; }\n public set disableOnInterrupt(val: boolean) { this._disableOnInterrupt = val; }\n\n /**\n * Create new AutoPlayer instance\n * @param camera - Instance of the {@link Camera} {@ko Camera의 인스턴스}\n * @param element - Canvas element {@ko 캔버스 엘리먼트}\n * @param options - Autoplay options {@ko 자동재생 옵션들}\n * @since 4.0.0\n */\n public constructor(viewer: View360, element: HTMLElement, options: boolean | Partial<AutoplayOptions>) {\n this._camera = viewer.camera;\n this._control = viewer.control;\n this._element = element;\n\n this._enabled = false;\n this._interrupted = false;\n this._interruptionTimer = -1;\n this._hovering = false;\n\n const {\n delay = 2000,\n delayOnMouseLeave = 0,\n speed = 1,\n pauseOnHover = false,\n canInterrupt = true,\n disableOnInterrupt = false\n } = getObjectOption(options);\n\n this._enableBlocked = !options;\n this._delay = delay;\n this._delayOnMouseLeave = delayOnMouseLeave;\n this._speed = speed;\n this._pauseOnHover = pauseOnHover;\n this._canInterrupt = canInterrupt;\n this._disableOnInterrupt = disableOnInterrupt;\n }\n\n /**\n * Destroy the instance and remove all event listeners attached\n * @ko 인스턴스를 제거하고 연결된 모든 이벤트 핸들러를 삭제합니다.\n * @since 4.0.0\n */\n public destroy(): void {\n this.disable();\n }\n\n /**\n * Rotate camera by given deltaTime\n * @ko 주어진 deltaTime만큼 카메라를 회전시킵니다.\n * @param deltaTime - Number of milisec to update {@ko 업데이트할 시간, 밀리초 단위}\n * @since 4.0.0\n */\n public update(deltaTime: number): void {\n if (!this._enabled) return;\n if (this._interrupted) {\n if (this._disableOnInterrupt) {\n this.disable();\n }\n\n return;\n }\n\n const camera = this._camera;\n const delta = -this._speed * deltaTime / 100;\n\n camera.yaw = circulate(camera.yaw + delta, 0, 360);\n }\n\n /**\n * Enable autoplay and add event listeners.\n * @ko 자동재생을 활성화하고 이벤트리스너들을 추가합니다.\n * @since 4.0.0\n */\n public enable(): void {\n const control = this._control;\n const element = this._element;\n\n if (this._enabled || control.gyro.enabled) return;\n\n control.rotate.on(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n control.rotate.on(CONTROL_EVENTS.INPUT_END, this._onInputEnd);\n\n control.zoom.on(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n control.zoom.on(CONTROL_EVENTS.INPUT_END, this._onInputEnd);\n\n control.gyro.on(CONTROL_EVENTS.ENABLE, this._onGyroEnable);\n\n element.addEventListener(BROWSER.EVENTS.MOUSE_ENTER, this._onMouseEnter, false);\n element.addEventListener(BROWSER.EVENTS.MOUSE_LEAVE, this._onMouseLeave, false);\n\n this._enabled = true;\n this._enableBlocked = false;\n }\n\n /**\n * Enable autoplay after current `delay` value.\n * @ko 현재의 `delay`값만큼 시간이 지난 다음에 자동재생을 활성화합니다.\n * @since 4.0.0\n */\n public enableAfterDelay() {\n this.enable();\n this._interrupted = true;\n this._setUninterruptedAfterDelay(this._delay);\n }\n\n /**\n * Disable autoplay and remove all event handlers.\n * @ko 자동재생을 비활성화하고 모든 이벤트 핸들러를 제거합니다.\n * @since 4.0.0\n */\n public disable(): void {\n if (!this._enabled) return;\n\n const control = this._control;\n const element = this._element;\n\n control.rotate.off(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n control.rotate.off(CONTROL_EVENTS.INPUT_END, this._onInputEnd);\n\n control.zoom.off(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n control.zoom.off(CONTROL_EVENTS.INPUT_END, this._onInputEnd);\n\n control.gyro.off(CONTROL_EVENTS.ENABLE, this._onGyroEnable);\n\n element.removeEventListener(BROWSER.EVENTS.MOUSE_ENTER, this._onMouseEnter, false);\n element.removeEventListener(BROWSER.EVENTS.MOUSE_LEAVE, this._onMouseLeave, false);\n\n this._enabled = false;\n this._interrupted = false;\n this._hovering = false;\n\n this._clearTimeout();\n }\n\n private _onInputStart = () => {\n if (!this._canInterrupt) return;\n\n this._interrupted = true;\n this._clearTimeout();\n };\n\n private _onInputEnd = () => {\n this._setUninterruptedAfterDelay(this._delay);\n };\n\n private _onGyroEnable = () => {\n this.disable();\n };\n\n private _onMouseEnter = () => {\n if (!this._pauseOnHover) return;\n this._interrupted = true;\n this._hovering = true;\n };\n\n private _onMouseLeave = () => {\n if (!this._pauseOnHover) return;\n this._hovering = false;\n this._setUninterruptedAfterDelay(this._delayOnMouseLeave);\n };\n\n private _setUninterruptedAfterDelay(delay: number): void {\n if (this._hovering) return;\n\n this._clearTimeout();\n\n if (delay > 0) {\n this._interruptionTimer = window.setTimeout(() => {\n this._interrupted = false;\n this._interruptionTimer = -1;\n }, delay);\n } else {\n this._interrupted = false;\n this._interruptionTimer = -1;\n }\n }\n\n private _clearTimeout(): void {\n if (this._interruptionTimer >= 0) {\n window.clearTimeout(this._interruptionTimer);\n this._interruptionTimer = -1;\n }\n }\n}\n\nexport default Autoplay;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Camera from \"./Camera\";\nimport PanoControl from \"../control/PanoControl\";\nimport View360 from \"../View360\";\nimport { CONTROL_EVENTS } from \"../const/internal\";\n\ntype VideoFrameCallbackMetadata = {\n mediaTime: number;\n};\n\ntype VideoFrameCallback = (now: number, metadata: VideoFrameCallbackMetadata) => void;\n\nconst isVideoFrameCallbackSupported = (video: HTMLVideoElement): boolean => {\n return typeof (video as any).requestVideoFrameCallback === \"function\";\n};\n\nconst clampFrameIndex = (index: number, maxIndex: number) => {\n if (index < 0) return 0;\n if (index > maxIndex) return maxIndex;\n return index;\n};\n\nconst lerp = (from: number, to: number, t: number) => from + (to - from) * t;\n\nconst lerpYaw = (from: number, to: number, t: number) => {\n let diff = to - from;\n if (diff > 180) diff -= 360;\n if (diff < -180) diff += 360;\n return from + diff * t;\n};\n\nexport interface CameraFrame {\n yaw: number;\n pitch: number;\n zoom: number;\n}\n\nexport interface CameraPathOptions {\n fps: number;\n canInterrupt: boolean;\n disableOnInterrupt: boolean;\n smoothing?: number;\n}\n\n/**\n * A controller that updates camera by precomputed frame data.\n * @ko 미리 계산된 프레임 데이터로 카메라를 업데이트하는 컨트롤러.\n * @since 4.0.0\n */\nclass CameraPath {\n private _fps: number;\n private _canInterrupt: boolean;\n private _disableOnInterrupt: boolean;\n private _smoothing: number;\n\n private _frames: Float32Array | null;\n private _frameCount: number;\n private _lastFrameIndex: number;\n private _enabled: boolean;\n private _timeOffset: number;\n\n private _control: PanoControl;\n private _video: HTMLVideoElement | null;\n private _videoFrameCallbackId: number;\n private _lastMediaTime: number;\n\n /**\n * Whether camera path is enabled or not\n * @ko 자동 운경 활성화 여부를 나타내는 값\n * @readonly\n * @since 4.0.0\n */\n public get enabled() { return this._enabled; }\n /**\n * Frames per second of the provided data\n * @ko 제공된 데이터의 FPS 값\n * @since 4.0.0\n */\n public get fps() { return this._fps; }\n public set fps(val: number) {\n if (val > 0) this._fps = val;\n }\n /**\n * Whether user input can interrupt the camera path\n * @ko 사용자 입력으로 자동 운경이 중단될 수 있는지 여부\n * @since 4.0.0\n */\n public get canInterrupt() { return this._canInterrupt; }\n public set canInterrupt(val: boolean) { this._canInterrupt = val; }\n /**\n * Whether to disable camera path on user interrupt\n * @ko 사용자 입력 시 자동 운경을 비활성화할지 여부\n * @since 4.0.0\n */\n public get disableOnInterrupt() { return this._disableOnInterrupt; }\n public set disableOnInterrupt(val: boolean) { this._disableOnInterrupt = val; }\n /**\n * Smoothing factor for the camera path. 0 disables extra smoothing\n * and follows the same Motion interpolation as manual input.\n * Value should be between 0 and 1.\n * @ko 카메라 경로의 보간 계수. 0이면 추가 보간 없이 Motion 경로만 사용합니다.\n * @since 4.0.0\n */\n public get smoothing() { return this._smoothing; }\n public set smoothing(val: number) {\n if (!Number.isFinite(val)) return;\n // Clamp between 0 and 1 to prevent overshoot or NaN issues\n this._smoothing = Math.max(0, Math.min(1, val));\n }\n /**\n * Whether any frame data is present\n * @ko 프레임 데이터가 존재하는지 여부\n * @since 4.0.0\n */\n public get hasFrames() { return this._frameCount > 0; }\n\n public constructor(viewer: View360, options: Partial<CameraPathOptions> = {}) {\n const {\n fps = 30,\n canInterrupt = true,\n disableOnInterrupt = true,\n smoothing = 0\n } = options;\n\n this._fps = fps;\n this._canInterrupt = canInterrupt;\n this._disableOnInterrupt = disableOnInterrupt;\n // Use setter for validation\n this.smoothing = smoothing;\n\n this._frames = null;\n this._frameCount = 0;\n this._lastFrameIndex = -1;\n this._enabled = false;\n this._timeOffset = 0;\n\n this._control = viewer.control;\n this._video = null;\n this._videoFrameCallbackId = -1;\n this._lastMediaTime = -1;\n }\n\n /**\n * Set precomputed frame data\n * @ko 미리 계산된 프레임 데이터를 설정합니다.\n * @param frames - Precomputed frames (yaw, pitch, zoom)\n * @param fps - Frames per second of the data\n * @since 4.0.0\n */\n public setFrames(frames: CameraFrame[] | Float32Array, fps: number = this._fps): void {\n const prevIndex = this._lastFrameIndex;\n\n if (frames instanceof Float32Array) {\n this._frames = frames;\n this._frameCount = Math.floor(frames.length / 3);\n } else {\n const count = frames.length;\n const data = new Float32Array(count * 3);\n\n for (let i = 0; i < count; i++) {\n const base = i * 3;\n const frame = frames[i];\n\n data[base] = frame.yaw;\n data[base + 1] = frame.pitch;\n data[base + 2] = frame.zoom;\n }\n\n this._frames = data;\n this._frameCount = count;\n }\n\n if (fps > 0) this._fps = fps;\n\n // 增量追加场景(HLS 分片):新数据是旧数据的超集,当前帧索引仍然有效,\n // 不重置 _lastFrameIndex,避免触发 forceInstant 打断 Motion 平滑插值。\n // 仅在全量替换或首次加载时才重置。\n const newCount = this._frameCount;\n if (prevIndex < 0 || prevIndex >= newCount) {\n this._lastFrameIndex = -1;\n }\n }\n\n /**\n * Set time offset in seconds to align video time to data time.\n * @ko 비디오 시간과 데이터 시간을 맞추기 위한 시간 오프셋(초, 음수 가능)\n * @since 4.0.0\n */\n public setTimeOffset(offset: number): void {\n if (!Number.isFinite(offset)) return;\n this._timeOffset = offset;\n this._lastFrameIndex = -1;\n }\n\n /**\n * Reset time offset to zero.\n * @ko 시간 오프셋을 0으로 초기화합니다.\n * @since 4.0.0\n */\n public resetTimeOffset(): void {\n this._timeOffset = 0;\n this._lastFrameIndex = -1;\n }\n\n /**\n * Clear frame data\n * @ko 프레임 데이터를 제거합니다.\n * @since 4.0.0\n */\n public clear(): void {\n this._frames = null;\n this._frameCount = 0;\n this._lastFrameIndex = -1;\n }\n\n /**\n * Enable camera path and add event listeners.\n * @ko 자동 운경을 활성화하고 이벤트 리스너를 추가합니다.\n * @since 4.0.0\n */\n public enable(): void {\n if (this._enabled) return;\n\n if (this._canInterrupt) {\n this._control.rotate.on(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n this._control.zoom.on(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n }\n\n this._control.sync();\n this._enabled = true;\n this._lastFrameIndex = -1;\n }\n\n /**\n * Disable camera path and remove event listeners.\n * @ko 자동 운경을 비활성화하고 이벤트 리스너를 제거합니다.\n * @since 4.0.0\n */\n public disable(): void {\n if (!this._enabled) return;\n\n this._control.rotate.off(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n this._control.zoom.off(CONTROL_EVENTS.INPUT_START, this._onInputStart);\n this._stopVideoFrameCallback();\n\n this._enabled = false;\n }\n\n /**\n * Update camera by given time.\n * @ko 주어진 시간 값으로 카메라를 업데이트합니다.\n * @param time - Current time in seconds\n * @param camera - Camera instance to update\n * @since 4.0.0\n */\n public updateByTime(time: number, camera: Camera): boolean {\n if (!this._enabled || !this._frames || this._frameCount <= 0) return false;\n if (!Number.isFinite(time) || this._fps <= 0) return false;\n const maxIndex = this._frameCount - 1;\n const adjustedTime = Math.max(0, time - this._timeOffset);\n const rawIndex = adjustedTime * this._fps;\n const frameIndex = clampFrameIndex(Math.floor(rawIndex), maxIndex);\n\n let forceInstant = false;\n const prevIndex = this._lastFrameIndex;\n const frameJumpThreshold = Math.max(this._fps * 2, 30);\n\n if (prevIndex < 0) {\n forceInstant = true;\n } else if (Math.abs(rawIndex - prevIndex) > frameJumpThreshold) {\n forceInstant = true;\n }\n\n const nextIndex = frameIndex < maxIndex ? frameIndex + 1 : frameIndex;\n const ratio = nextIndex === frameIndex\n ? 0\n : Math.max(0, Math.min(1, rawIndex - frameIndex));\n\n const base = frameIndex * 3;\n const nextBase = nextIndex * 3;\n const fromYaw = this._frames[base];\n const fromPitch = this._frames[base + 1];\n const fromZoom = this._frames[base + 2];\n\n const targetYaw = ratio > 0\n ? lerpYaw(fromYaw, this._frames[nextBase], ratio)\n : fromYaw;\n const targetPitch = ratio > 0\n ? lerp(fromPitch, this._frames[nextBase + 1], ratio)\n : fromPitch;\n const targetZoom = ratio > 0\n ? lerp(fromZoom, this._frames[nextBase + 2], ratio)\n : fromZoom;\n\n return this._applyTarget(frameIndex, targetYaw, targetPitch, targetZoom, camera, forceInstant);\n }\n\n /**\n * Update camera by video time source.\n * @ko 비디오 시간 기준으로 카메라를 업데이트합니다.\n * @since 4.0.0\n */\n public updateFromVideo(video: HTMLVideoElement, camera: Camera): boolean {\n if (!this._enabled || !this._frames || this._frameCount <= 0) return false;\n\n this._ensureVideoFrameCallback(video);\n\n const time = this._getVideoTime(video);\n return this.updateByTime(time, camera);\n }\n\n public destroy(): void {\n this.disable();\n this.clear();\n }\n\n private _getVideoTime(video: HTMLVideoElement): number {\n const currentTime = video.currentTime;\n\n if (video.paused || video.ended || this._lastMediaTime < 0) {\n return currentTime;\n }\n\n const diff = Math.abs(currentTime - this._lastMediaTime);\n const maxDrift = (1 / this._fps) * 2;\n\n if (diff <= maxDrift) {\n return this._lastMediaTime;\n }\n\n // currentTime went backwards (HLS segment transition artifact) — hold at lastMediaTime\n if (currentTime < this._lastMediaTime) {\n return this._lastMediaTime;\n }\n\n return currentTime;\n }\n\n private _ensureVideoFrameCallback(video: HTMLVideoElement) {\n if (!isVideoFrameCallbackSupported(video)) return;\n\n if (this._video && this._video !== video) {\n this._stopVideoFrameCallback();\n }\n\n this._video = video;\n\n if (this._videoFrameCallbackId >= 0) return;\n\n const request = (video as any).requestVideoFrameCallback as (cb: VideoFrameCallback) => number;\n this._videoFrameCallbackId = request.call(video, this._onVideoFrame);\n }\n\n private _stopVideoFrameCallback() {\n const video = this._video as any;\n\n if (video && this._videoFrameCallbackId >= 0 && typeof video.cancelVideoFrameCallback === \"function\") {\n video.cancelVideoFrameCallback(this._videoFrameCallbackId);\n }\n\n this._videoFrameCallbackId = -1;\n this._lastMediaTime = -1;\n this._video = null;\n }\n\n private _onVideoFrame = (_now: number, metadata: VideoFrameCallbackMetadata) => {\n this._lastMediaTime = metadata.mediaTime;\n\n if (!this._enabled || !this._video) {\n this._videoFrameCallbackId = -1;\n return;\n }\n\n const video = this._video as any;\n if (typeof video.requestVideoFrameCallback !== \"function\") {\n this._videoFrameCallbackId = -1;\n return;\n }\n\n this._videoFrameCallbackId = video.requestVideoFrameCallback(this._onVideoFrame);\n };\n\n private _applyTarget(\n frameIndex: number,\n targetYaw: number,\n targetPitch: number,\n targetZoom: number,\n camera: Camera,\n forceInstant: boolean\n ): boolean {\n const targetChanged = frameIndex !== this._lastFrameIndex;\n const rotateControl = this._control.rotate;\n const zoomControl = this._control.zoom;\n const yawMotion = rotateControl.yaw;\n const pitchMotion = rotateControl.pitch;\n const targetFov = camera.getHorizontalFov(targetZoom);\n const smoothing = this._smoothing;\n\n if (forceInstant) {\n // ── 诊断:非首帧的 forceInstant 会打断 Motion 平滑插值 ──\n const prevYaw = yawMotion.val;\n const yawJump = targetYaw - prevYaw;\n console.warn(\n `%c[CameraPath] forceInstant! frame=${frameIndex} prevFrame=${this._lastFrameIndex}` +\n ` | yaw: ${prevYaw.toFixed(2)}→${targetYaw.toFixed(2)} (jump=${yawJump.toFixed(2)})` +\n ` | pitch: ${pitchMotion.val.toFixed(2)}→${targetPitch.toFixed(2)}`,\n \"color: #ff9800\"\n );\n\n yawMotion.reset(targetYaw);\n pitchMotion.reset(targetPitch);\n zoomControl.reset(targetFov);\n this._lastFrameIndex = frameIndex;\n return true;\n }\n\n let yawDiff = targetYaw - yawMotion.end;\n const yawRange = yawMotion.range;\n if (!Number.isFinite(yawRange.min) && !Number.isFinite(yawRange.max)) {\n if (yawDiff > 180) yawDiff -= 360;\n if (yawDiff < -180) yawDiff += 360;\n }\n\n const pitchDiff = targetPitch - pitchMotion.end;\n const zoomDiff = targetFov - zoomControl.end;\n const epsilon = 1e-4;\n const hasDiff = Math.abs(yawDiff) > epsilon\n || Math.abs(pitchDiff) > epsilon\n || Math.abs(zoomDiff) > epsilon;\n\n if (!targetChanged && !hasDiff) return false;\n\n const scale = smoothing > 0 ? smoothing : 1;\n\n if (Math.abs(yawDiff) > epsilon) yawMotion.setNewEndByDelta(yawDiff * scale);\n if (Math.abs(pitchDiff) > epsilon) pitchMotion.setNewEndByDelta(pitchDiff * scale);\n if (Math.abs(zoomDiff) > epsilon) zoomControl.setNewEndByDelta(zoomDiff * scale);\n\n this._lastFrameIndex = frameIndex;\n return true;\n }\n\n private _onInputStart = () => {\n if (!this._canInterrupt) return;\n if (!this._disableOnInterrupt) return;\n\n this.disable();\n };\n}\n\nexport default CameraPath;\n","import { mat4 } from \"gl-matrix\";\nimport Component from \"@egjs/component\";\nimport WebGLContext from \"./WebGLContext\";\nimport GyroControl from \"../control/GyroControl\";\nimport * as BROWSER from \"../const/browser\";\nimport { SESSION_VR, XR_REFERENCE_SPACE } from \"../const/internal\";\nimport { EVENTS } from \"../const/external\";\n\ninterface XRSessionOptions extends XRSessionInit {\n [key: string]: any;\n}\n\n/**\n * WebXR manager class\n * @ko WebXR 매니저 클래스\n * @since 4.0.0\n */\nclass XRManager extends Component<{\n /**\n * An event that fires on entering VR session\n * @ko VR 세션 진입시에 트리거되는 이벤트\n * @eventName vrStart\n * @eventOf XRManager\n * @version 4.0.0\n */\n [EVENTS.VR_START]: {\n session: XRSession;\n };\n /**\n * An event that fires on exiting VR session\n * @ko VR 세션에서 나갈 때 트리거되는 이벤트\n * @eventName vrEnd\n * @eventOf XRManager\n * @version 4.0.0\n */\n [EVENTS.VR_END]: void;\n}> {\n private _ctx: WebGLContext;\n private _xrSession: XRSession | null;\n private _xrRefSpace: XRReferenceSpace | null;\n private _options: XRSessionOptions;\n\n /**\n * Create new instance.\n * 새 인스턴스를 생성합니다.\n * @param ctx - Instance of WebGL context helper {@ko WebGL 콘텍스트 헬퍼의 인스턴스}\n * @param options - Options {@ko 옵션들}\n */\n public constructor(ctx: WebGLContext, options: XRSessionOptions = {}) {\n super();\n\n this._xrSession = null;\n this._xrRefSpace = null;\n this._ctx = ctx;\n this._options = options;\n }\n\n /**\n * Destroy instance and end XR session if there was any.\n * @ko 인스턴스를 제거하고, XR 세션이 존재할 경우 종료합니다.\n * @since 4.0.0\n */\n public destroy = () => {\n this.exit();\n this.off();\n };\n\n /**\n * Returns WebXR availability.\n * @ko WebXR 사용 가능 여부를 반환합니다.\n * @since 4.0.0\n */\n public async isAvailable(): Promise<boolean> {\n // eslint-disable-next-line compat/compat\n const xr = window.navigator.xr;\n if (!xr) return false;\n\n return xr.isSessionSupported(SESSION_VR)\n .then(available => {\n return available;\n }).catch(() => {\n return false;\n });\n }\n\n /**\n * Enter VR session\n * @ko VR 세션에 진입합니다.\n * @since 4.0.0\n */\n public async enter() {\n const ctx = this._ctx;\n\n // eslint-disable-next-line compat/compat\n const xr = window.navigator.xr;\n if (!xr) return;\n\n await GyroControl.requestSensorPermission();\n\n const options = {\n ...{\n requiredFeatures: [XR_REFERENCE_SPACE]\n },\n ...this._options\n };\n\n await ctx.makeXRCompatible();\n\n const session = await xr.requestSession(SESSION_VR, options);\n ctx.bindXRLayer(session);\n\n const refSpace = await session.requestReferenceSpace(XR_REFERENCE_SPACE);\n\n this._setSession(session, refSpace);\n\n this.trigger(EVENTS.VR_START, {\n session\n });\n }\n\n /**\n * Exit VR session\n * @ko VR 세션에서 나갑니다.\n * @since 4.0.0\n */\n public exit() {\n const xrSession = this._xrSession;\n\n if (xrSession) {\n xrSession.end()\n .catch(() => void 0);\n }\n\n this._xrSession = null;\n this._xrRefSpace = null;\n }\n\n /**\n * @hidden\n */\n public canRender(frame: XRFrame) {\n const refSpace = this._xrRefSpace;\n\n if (!refSpace) return false;\n\n const pose = frame.getViewerPose(refSpace);\n\n return !!pose;\n }\n\n /**\n * @hidden\n */\n public getEyeParams(frame: XRFrame): Array<{\n viewport: XRViewport;\n vMatrix: mat4;\n pMatrix: mat4;\n }> | null {\n const session = frame.session;\n const pose = frame.getViewerPose(this._xrRefSpace!);\n\n if (!pose) return null;\n\n const glLayer = session.renderState.baseLayer;\n\n if (!glLayer) return null;\n\n return pose.views.map(view => {\n const viewport = glLayer.getViewport(view)!;\n const vMatrix = view.transform.inverse.matrix;\n\n return {\n viewport,\n vMatrix,\n pMatrix: view.projectionMatrix\n };\n });\n }\n\n private _setSession(session: XRSession, refSpace: XRReferenceSpace) {\n this._xrSession = session;\n this._xrRefSpace = refSpace;\n\n session.addEventListener(BROWSER.EVENTS.XR_END, this._onSessionEnd);\n }\n\n private _onSessionEnd = () => {\n this.exit();\n this.trigger(EVENTS.VR_END);\n }\n}\n\nexport default XRManager;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport { vec3 } from \"gl-matrix\";\n\n/**\n * Hotspot data\n * @ko 핫스팟 데이터\n * @since 4.0.0\n */\nclass Hotspot {\n /**\n * HTMLElement of the hotspot\n * @ko 핫스팟의 HTMLElement\n * @since 4.0.0\n */\n public readonly element: HTMLElement;\n /**\n * Position to render hotspot\n * @ko 핫스팟을 렌더링할 위치\n * @since 4.0.0\n */\n public readonly position: vec3;\n\n public constructor(element: HTMLElement, position: vec3) {\n this.element = element;\n this.position = position;\n }\n}\n\nexport default Hotspot;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport { vec2, vec3 } from \"gl-matrix\";\nimport Hotspot from \"./Hotspot\";\nimport Camera from \"../core/Camera\";\nimport WebGLRenderer from \"../core/WebGLRenderer\";\nimport View360Error from \"../core/View360Error\";\nimport { getNullableElement } from \"../utils\";\nimport ERROR from \"../const/error\";\nimport { DEFAULT_CLASS } from \"../const/external\";\nimport { DEG_TO_RAD } from \"../const/internal\";\n\n/**\n * Options for {@link HotspotRenderer}\n * @ko {@link HotspotRenderer}용 옵션들\n * @since 4.0.0\n */\nexport interface HotspotOptions {\n /**\n * Apply scale for hotspots, makes their size sync with background panorama image.\n * @ko 핫스팟에 스케일을 적용해서 배경 파노라마 이미지의 크기 변화와 동일하게 크기를 조절합니다.\n * @since 4.0.0\n */\n zoom: boolean;\n}\n\n/**\n * Hotspot renderer\n * @ko Hotspot 렌더러\n * @since 4.0.0\n */\nclass HotspotRenderer {\n // Options\n private _zoom: HotspotOptions[\"zoom\"];\n\n // Internal properties\n private _containerEl: HTMLElement | null;\n private _renderer: WebGLRenderer;\n private _hotspots: Hotspot[];\n\n /**\n * Create new instance\n * @ko 새 인스턴스를 생성합니다.\n * @param rootEl - Container element for hotspots {@ko 핫스팟들의 컨테이너 엘리먼트}\n * @param renderer - instance of WebGLRenderer {@ko WebGLRenderer의 인스턴스}\n * @param options - Hotspot options {@ko Hotspot 옵션들 }\n */\n public constructor(rootEl: HTMLElement, renderer: WebGLRenderer, {\n zoom = false\n }: Partial<HotspotOptions>) {\n this._containerEl = getNullableElement(`.${DEFAULT_CLASS.HOTSPOT_CONTAINER}`, rootEl);\n this._renderer = renderer;\n this._hotspots = [];\n\n this._zoom = zoom;\n }\n\n /**\n * Refresh hotspots by collecting hotspot elements from current hotspot root element\n * @ko 현재 핫스팟 루트 엘리먼트 내에서 핫스팟 엘리먼트들을 수집하여 갱신합니다.\n * @throws {ERROR_CODES.INSUFFICIENT_ARGS} if data-position doesn't include all x, y, z values {@ko data-position이 x, y, z좌표를 전부 포함하고 있지 않을 때}\n */\n public refresh() {\n const container = this._containerEl;\n if (!container) return;\n\n const hotspotEls = [].slice.apply(container.querySelectorAll(`.${DEFAULT_CLASS.HOTSPOT}`)) as HTMLElement[];\n this._hotspots = hotspotEls.map(el => this._parseHotspot(el));\n }\n\n /**\n * Render hotspots\n * @ko 핫스팟들을 렌더링합니다.\n * @param camera - Instance of Camera {@ko Camera의 인스턴스}\n */\n public render(camera: Camera) {\n const hotspots = this._hotspots;\n const halfWidth = this._renderer.width * 0.5;\n const halfHeight = this._renderer.height * 0.5;\n const zoom = camera.zoom;\n const centerTransform = \"translate(-50%, -50%)\";\n const zoomTransform = this._zoom ? `scale(${zoom})` : \"\";\n\n hotspots.forEach(hotspot => {\n const position = hotspot.position;\n const relPos = vec3.create();\n\n vec3.copy(relPos, position);\n vec3.transformMat4(relPos, relPos, camera.viewMatrix);\n vec3.transformMat4(relPos, relPos, camera.projectionMatrix);\n\n if (relPos[2] > 1 || relPos[2] < 0) {\n hotspot.element.classList.remove(DEFAULT_CLASS.HOTSPOT_VISIBLE);\n return;\n }\n\n const screenPos = vec2.fromValues(\n relPos[0] * halfWidth + halfWidth,\n -relPos[1] * halfHeight + halfHeight\n );\n\n hotspot.element.classList.add(DEFAULT_CLASS.HOTSPOT_VISIBLE);\n hotspot.element.style.transform = [\n centerTransform,\n `translate(${screenPos[0]}px, ${screenPos[1]}px)`,\n zoomTransform\n ].join(\" \");\n });\n }\n\n private _parseHotspot(element: HTMLElement): Hotspot {\n const yawStr = element.dataset.yaw;\n const pitchStr = element.dataset.pitch;\n const positionStr = element.dataset.position;\n\n if (yawStr || pitchStr) {\n const yaw = yawStr ? parseFloat(yawStr) : 0;\n const pitch = pitchStr ? parseFloat(pitchStr) : 0;\n\n const position = this._yawPitchToVec3(yaw, pitch);\n\n return new Hotspot(element, position);\n } else if (positionStr) {\n const pos: number[] = positionStr.split(\" \").map(val => parseFloat(val));\n if (pos.length < 3) {\n throw new View360Error(ERROR.MESSAGES.INSUFFICIENT_ARGS(positionStr, \"hotspot attribute \\\"data-position\\\"\"), ERROR.CODES.INSUFFICIENT_ARGS);\n }\n\n return new Hotspot(element, vec3.fromValues(pos[0], pos[1], pos[2]));\n } else {\n // Place hotspot at yaw: 0, pitch: 0\n const defaultPos = vec3.fromValues(0, 0, -1);\n\n return new Hotspot(element, defaultPos);\n }\n }\n\n private _yawPitchToVec3(yaw: number, pitch: number) {\n const yawRad = yaw * DEG_TO_RAD;\n const pitchRad = pitch * DEG_TO_RAD;\n const position = vec3.create();\n\n position[1] = Math.sin(pitchRad);\n position[2] = Math.cos(pitchRad);\n\n position[0] = position[2] * Math.sin(-yawRad);\n position[2] = -position[2] * Math.cos(-yawRad);\n\n return position;\n }\n}\n\nexport default HotspotRenderer;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Geometry from \"../geometry/Geometry\";\nimport { VAO } from \"../type/internal\";\n\n/**\n * @hidden\n */\nclass VertexArrayObject {\n public readonly obj: VAO | null;\n public readonly geometry: Geometry;\n public readonly buffers: {\n indicies: WebGLBuffer;\n position: WebGLBuffer;\n uv: WebGLBuffer;\n }\n\n public get count() { return this.geometry.indicies.count; }\n\n constructor(obj: VAO | null, geometry: Geometry, buffers: VertexArrayObject[\"buffers\"]) {\n this.obj = obj;\n this.geometry = geometry;\n this.buffers = buffers;\n }\n}\n\nexport default VertexArrayObject;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport { mat4 } from \"gl-matrix\";\nimport Uniform from \"../uniform/Uniform\";\nimport Camera from \"./Camera\";\nimport Object3D from \"./Object3D\";\nimport ShaderProgram from \"./ShaderProgram\";\nimport View360Error from \"./View360Error\";\nimport VertexArrayObject from \"./VertexArrayObject\";\nimport VertexData from \"./VertexData\";\nimport Texture from \"../texture/Texture\";\nimport Geometry from \"../geometry/Geometry\";\nimport * as BROWSER from \"../const/browser\";\nimport ERROR from \"../const/error\";\nimport { DEFAULT_CLASS } from \"../const/external\";\nimport { UniformLocations } from \"../type/internal\";\n\n/**\n * @hidden\n */\nclass WebGLContext {\n private _canvas: HTMLCanvasElement;\n private _gl: WebGLRenderingContext | WebGL2RenderingContext;\n private _contextLost: boolean;\n private _maxTextureSize: number;\n private _isWebGL2: boolean;\n private _debug: boolean;\n private _extensions: {\n vao: OES_vertex_array_object | null;\n loseContext: WEBGL_lose_context | null;\n };\n\n public get canvas() { return this._canvas; }\n public get gl() { return this._gl; }\n public get maxTextureSize() { return this._maxTextureSize; }\n public get isWebGL2() { return this._isWebGL2; }\n public get supportVAO() { return this._isWebGL2 || !!this._extensions.vao; }\n public get lost() { return this._contextLost; }\n public get debug() { return this._debug; }\n\n public constructor(canvas: HTMLCanvasElement, debug: boolean) {\n this._canvas = canvas;\n this._contextLost = false;\n this._debug = debug;\n this._extensions = {\n vao: null,\n loseContext: null\n };\n }\n\n public init() {\n const canvas = this._canvas;\n\n const { gl, isWebGL2 } = this._getContext(canvas);\n\n this._gl = gl;\n this._maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);\n this._isWebGL2 = isWebGL2;\n\n if (!this._isWebGL2) {\n this._extensions.vao = gl.getExtension(\"OES_vertex_array_object\");\n }\n\n this._extensions.loseContext = gl.getExtension(\"WEBGL_lose_context\");\n\n canvas.addEventListener(BROWSER.EVENTS.CONTEXT_LOST, this._onContextLost);\n canvas.addEventListener(BROWSER.EVENTS.CONTEXT_RESTORED, this._onContextRestore);\n\n // gl.enable(gl.DEPTH_TEST);\n }\n\n public destroy() {\n const gl = this._gl;\n const canvas = this._canvas;\n\n if (gl) {\n // gl is not defined when destroy is called before init\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n }\n\n canvas.removeEventListener(BROWSER.EVENTS.CONTEXT_LOST, this._onContextLost);\n canvas.removeEventListener(BROWSER.EVENTS.CONTEXT_RESTORED, this._onContextRestore);\n }\n\n public forceLoseContext() {\n const extension = this._extensions.loseContext;\n\n if (!extension) return;\n\n extension.loseContext();\n }\n\n public forceRestoreContext() {\n const extension = this._extensions.loseContext;\n\n if (!extension) return;\n\n extension.restoreContext();\n }\n\n public clear() {\n const gl = this._gl;\n\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n\n public resize() {\n const gl = this._gl;\n\n gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n }\n\n public viewport(x: number, y: number, width: number, height: number) {\n const gl = this._gl;\n\n gl.viewport(x, y, width, height);\n }\n\n public createVAO(geometry: Geometry, shaderProgram: ShaderProgram) {\n const nativeVAO = this._createNativeVAO();\n\n const vao = new VertexArrayObject(nativeVAO, geometry, {\n indicies: this._createBuffer(),\n position: this._createBuffer(),\n uv: this._createBuffer()\n });\n\n if (nativeVAO) {\n this._bindNativeVAO(nativeVAO);\n this._supplyGeometryData(vao, shaderProgram);\n this._bindNativeVAO(null);\n this._unbindBuffers();\n }\n\n return vao;\n }\n\n public draw(vao: VertexArrayObject, shaderProgram: ShaderProgram) {\n const gl = this._gl;\n\n if (vao.obj) {\n this._bindNativeVAO(vao.obj);\n } else {\n this._supplyGeometryData(vao, shaderProgram);\n }\n\n gl.drawElements(gl.TRIANGLES, vao.count, gl.UNSIGNED_SHORT, 0);\n\n if (vao.obj) {\n this._bindNativeVAO(null);\n } else {\n this._unbindBuffers();\n }\n }\n\n public releaseVAO(vao: VertexArrayObject) {\n if (vao.obj) {\n this._deleteNativeVAO(vao.obj);\n }\n\n this._deleteBuffer(vao.buffers.indicies);\n this._deleteBuffer(vao.buffers.position);\n this._deleteBuffer(vao.buffers.uv);\n }\n\n public getUniformLocations<T extends Record<string, Uniform>>(program: WebGLProgram, uniforms: T): UniformLocations<T> {\n const gl = this._gl;\n\n const uniformLocations = Object.keys(uniforms).reduce((locations, key) => {\n locations[key as keyof T] = gl.getUniformLocation(program, key)!;\n\n return locations;\n }, {} as UniformLocations<T>);\n\n return {\n ...this._getCommonUniformLocations(program),\n ...uniformLocations\n };\n }\n\n public updateCommonUniforms(entity: Object3D, camera: Camera, shaderProgram: ShaderProgram) {\n const gl = this._gl;\n\n const uniformLocations = shaderProgram.uniformLocations;\n\n // We're using \"matrix\"(=local matrix) here for efficiency\n // As projection doesn't require world matrix, as it doesn't have any parent or child\n const matrix = entity.matrix;\n const mvMatrix = mat4.create();\n mat4.multiply(mvMatrix, camera.viewMatrix, matrix);\n\n gl.uniformMatrix4fv(uniformLocations.uMVMatrix, false, mvMatrix);\n gl.uniformMatrix4fv(uniformLocations.uPMatrix, false, camera.projectionMatrix);\n }\n\n public updateVRUniforms(shaderProgram: ShaderProgram, mvMatrix: mat4, pMatrix: mat4, eyeIndex: number) {\n const gl = this._gl;\n\n const uniformLocations = shaderProgram.uniformLocations;\n\n gl.uniformMatrix4fv(uniformLocations.uMVMatrix, false, mvMatrix);\n gl.uniformMatrix4fv(uniformLocations.uPMatrix, false, pMatrix);\n\n if (uniformLocations.uEye) {\n gl.uniform1f(uniformLocations.uEye, eyeIndex);\n }\n }\n\n public updateUniforms(shaderProgram: ShaderProgram) {\n const gl = this._gl;\n\n const uniforms = shaderProgram.uniforms;\n const uniformLocations = shaderProgram.uniformLocations;\n\n for (const key in uniforms) {\n const uniform = uniforms[key];\n const location = uniformLocations[key];\n\n if (!uniform) continue;\n\n if (uniform.needsUpdate) {\n uniform.update(gl, location, this._isWebGL2);\n }\n }\n }\n\n public releaseShaderResources(shaderProgram: ShaderProgram) {\n const gl = this._gl;\n\n const uniforms = shaderProgram.uniforms;\n\n for (const key in uniforms) {\n const uniform = uniforms[key];\n\n if (!uniform) continue;\n\n if (uniform.needsUpdate) {\n uniform.destroy(gl);\n }\n }\n\n gl.deleteProgram(shaderProgram.program);\n }\n\n public useProgram(shaderProgram: ShaderProgram) {\n const gl = this._gl;\n\n gl.useProgram(shaderProgram.program);\n }\n\n public createProgram(vertexShader: string, fragmentShader: string) {\n const gl = this._gl;\n const program = gl.createProgram()!;\n\n const vs = this._compileShader(gl.VERTEX_SHADER, vertexShader);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fragmentShader);\n\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.bindAttribLocation(program, 0, \"position\");\n gl.bindAttribLocation(program, 1, \"uv\");\n gl.linkProgram(program);\n\n if (this._debug && !gl.getProgramParameter(program, gl.LINK_STATUS)) {\n let shaderLog: string | null = null;\n\n if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {\n shaderLog = gl.getShaderInfoLog(vs);\n } else if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {\n shaderLog = gl.getShaderInfoLog(fs);\n }\n\n throw new View360Error(ERROR.MESSAGES.FAILED_LINKING_PROGRAM(gl.getProgramInfoLog(program), shaderLog), ERROR.CODES.FAILED_LINKING_PROGRAM);\n }\n\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return program;\n }\n\n public createWebGLTexture(texData: Texture): WebGLTexture {\n const gl = this._gl;\n const texture = gl.createTexture()!;\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, texData.wrapS);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, texData.wrapT);\n\n if (!texData.isVideo() && this._isWebGL2) {\n const gl2 = gl as WebGL2RenderingContext;\n\n gl2.texStorage2D(gl2.TEXTURE_2D, 1, gl2.RGBA8, texData.width, texData.height);\n }\n\n return texture;\n }\n\n public createWebGLCubeTexture(texData: Texture, size: number): WebGLTexture {\n const gl = this._gl;\n const texture = gl.createTexture()!;\n\n gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);\n gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, texData.wrapS);\n gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, texData.wrapT);\n\n if (this._isWebGL2) {\n const gl2 = gl as WebGL2RenderingContext;\n\n gl2.texStorage2D(gl2.TEXTURE_CUBE_MAP, 1, gl2.RGBA8, size, size);\n }\n\n return texture;\n }\n\n public async makeXRCompatible() {\n const gl = this._gl;\n const attributes = gl.getContextAttributes();\n\n if (attributes && attributes.xrCompatible !== true) {\n await gl.makeXRCompatible();\n }\n }\n\n public bindXRLayer(session: XRSession) {\n const gl = this._gl;\n const xrLayer = new XRWebGLLayer(session, gl);\n session.updateRenderState({ baseLayer: xrLayer });\n }\n\n public bindXRFrame(frame: XRFrame) {\n const gl = this._gl;\n const session = frame.session;\n const baseLayer = session.renderState.baseLayer!;\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, baseLayer.framebuffer);\n }\n\n public useDefaultFrameBuffer() {\n const gl = this._gl;\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n }\n\n /**\n * 创建 Framebuffer 及其颜色附件纹理\n * @param width - 纹理宽度\n * @param height - 纹理高度\n * @returns FBO 对象,包含 framebuffer 和 texture\n */\n public createFramebuffer(width: number, height: number): {\n framebuffer: WebGLFramebuffer;\n texture: WebGLTexture;\n } {\n const gl = this._gl;\n const framebuffer = gl.createFramebuffer();\n const texture = gl.createTexture();\n\n if (!framebuffer || !texture) {\n throw new View360Error(\"无法创建 Framebuffer\", ERROR.CODES.FAILED_LINKING_PROGRAM);\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);\n\n // 检查 FBO 完整性\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new View360Error(\"Framebuffer 不完整: \" + status, ERROR.CODES.FAILED_LINKING_PROGRAM);\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return { framebuffer, texture };\n }\n\n /**\n * 绑定指定的 Framebuffer\n * @param framebuffer - 要绑定的 FBO,传 null 恢复默认\n */\n public bindFramebuffer(framebuffer: WebGLFramebuffer | null) {\n this._gl.bindFramebuffer(this._gl.FRAMEBUFFER, framebuffer);\n }\n\n /**\n * 删除 Framebuffer 及其附件纹理\n * @param fbo - 要删除的 FBO 对象\n */\n public deleteFramebuffer(fbo: { framebuffer: WebGLFramebuffer; texture: WebGLTexture }) {\n const gl = this._gl;\n gl.deleteFramebuffer(fbo.framebuffer);\n gl.deleteTexture(fbo.texture);\n }\n\n private _createBuffer(): WebGLBuffer {\n return this._gl.createBuffer()!;\n }\n\n private _deleteBuffer(buffer: WebGLBuffer) {\n return this._gl.deleteBuffer(buffer);\n }\n\n private _createNativeVAO() {\n const gl = this._gl;\n\n if (this._isWebGL2) {\n return (gl as WebGL2RenderingContext).createVertexArray()!;\n } else {\n const ext = this._extensions.vao;\n\n return ext?.createVertexArrayOES() || null;\n }\n }\n\n private _bindNativeVAO(vao: WebGLVertexArrayObject | null) {\n const gl = this._gl;\n\n if (this._isWebGL2) {\n (gl as WebGL2RenderingContext).bindVertexArray(vao);\n } else {\n const ext = this._extensions.vao;\n\n ext?.bindVertexArrayOES(vao);\n }\n }\n\n private _deleteNativeVAO(vao: WebGLVertexArrayObject | null) {\n const gl = this._gl;\n\n if (this._isWebGL2) {\n (gl as WebGL2RenderingContext).deleteVertexArray(vao);\n } else {\n const ext = this._extensions.vao;\n\n ext?.deleteVertexArrayOES(vao);\n }\n }\n\n private _supplyGeometryData(vao: VertexArrayObject, shaderProgram: ShaderProgram) {\n const geometry = vao.geometry;\n\n this._supplyIndiciesData(geometry.indicies, vao.buffers.indicies);\n this._supplyAttributeData(geometry.vertices, shaderProgram.program, \"position\", vao.buffers.position);\n this._supplyAttributeData(geometry.uvs, shaderProgram.program, \"uv\", vao.buffers.uv);\n }\n\n private _unbindBuffers() {\n const gl = this._gl;\n\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n }\n\n private _supplyIndiciesData(indicies: VertexData<Uint16Array>, buffer: WebGLBuffer) {\n const gl = this._gl;\n\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indicies.data, gl.STATIC_DRAW);\n }\n\n private _supplyAttributeData(attribute: VertexData<Float32Array>, program: WebGLProgram, name: string, buffer: WebGLBuffer) {\n const gl = this._gl;\n const attribLocation = gl.getAttribLocation(program, name);\n\n // Attribute not used\n if (attribLocation < 0) return;\n\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n gl.bufferData(gl.ARRAY_BUFFER, attribute.data, gl.STATIC_DRAW);\n gl.vertexAttribPointer(attribLocation, attribute.itemSize, gl.FLOAT, false, 0, 0);\n gl.enableVertexAttribArray(attribLocation);\n }\n\n private _compileShader(type: number, src: string) {\n const gl = this._gl;\n const shader = gl.createShader(type)!;\n\n gl.shaderSource(shader, src);\n gl.compileShader(shader);\n\n return shader;\n }\n\n private _getCommonUniformLocations(program: WebGLProgram) {\n const gl = this._gl;\n\n return {\n uMVMatrix: gl.getUniformLocation(program, \"uMVMatrix\")!,\n uPMatrix: gl.getUniformLocation(program, \"uPMatrix\")!\n };\n }\n\n private _getContext(canvas: HTMLCanvasElement): {\n gl: WebGLRenderingContext | WebGL2RenderingContext;\n isWebGL2: boolean;\n } {\n const webglIdentifiers = [\"webgl2\", \"webgl\", \"experimental-webgl\", \"webkit-3d\", \"moz-webgl\"];\n let context: WebGLRenderingContext | null = null;\n let isWebGL2 = false;\n const contextAttributes = {\n preserveDrawingBuffer: false,\n antialias: false\n };\n\n const onWebglContextCreationError = e => e.statusMessage;\n\n canvas.addEventListener(BROWSER.EVENTS.CONTEXT_CREATE_ERROR, onWebglContextCreationError);\n\n for (const identifier of webglIdentifiers) {\n try {\n context = canvas.getContext(identifier, contextAttributes) as WebGLRenderingContext;\n isWebGL2 = identifier === \"webgl2\";\n } catch (t) {} // eslint-disable-line no-empty\n if (context) {\n break;\n }\n }\n\n canvas.removeEventListener(BROWSER.EVENTS.CONTEXT_CREATE_ERROR, onWebglContextCreationError);\n\n if (!context) {\n throw new View360Error(ERROR.MESSAGES.WEBGL_NOT_SUPPORTED, ERROR.CODES.WEBGL_NOT_SUPPORTED);\n }\n\n return {\n gl: context,\n isWebGL2\n };\n }\n\n private _onContextLost = () => {\n const canvas = this._canvas;\n canvas.classList.add(DEFAULT_CLASS.CTX_LOST);\n this._contextLost = true;\n };\n\n private _onContextRestore = () => {\n const canvas = this._canvas;\n canvas.classList.remove(DEFAULT_CLASS.CTX_LOST);\n this._contextLost = false;\n };\n}\n\nexport default WebGLContext;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport { mat4 } from \"gl-matrix\";\nimport Camera from \"./Camera\";\nimport WebGLContext from \"./WebGLContext\";\nimport XRManager from \"./XRManager\";\nimport TriangleMesh from \"./TriangleMesh\";\n\n/**\n * Projection renderer, based on WebGL\n * @ko WebGL 기반의 프로젝션 렌더러\n * @since 4.0.0\n */\nclass WebGLRenderer {\n private _canvas: HTMLCanvasElement;\n private _elementSize: { x: number, y: number };\n private _pixelRatio: number;\n private _renderSize: { width: number | null; height: number | null };\n\n public readonly ctx: WebGLContext;\n\n /**\n * Canvas element\n * @ko 캔버스 엘리먼트\n * @since 4.0.0\n */\n public get canvas() { return this._canvas; }\n /**\n * Canvas's width (`devicePixelRatio` is not applied)\n * @ko 캔버스의 보이는 너비 (`devicePixelRatio`가 적용되지 않은)\n * @since 4.0.0\n */\n public get width() { return this._elementSize.x; }\n /**\n * Canvas's height (`devicePixelRatio` is not applied)\n * @ko 캔버스의 높이 (`devicePixelRatio`가 적용되지 않은)\n * @since 4.0.0\n */\n public get height() { return this._elementSize.y; }\n /**\n * Current rendering pixel ratio (renderingWidth / CSS width).\n * @ko 현재 렌더링 픽셀 비율 (렌더링 너비 / CSS 너비).\n * @since 4.0.0\n * @example\n * ```js\n * cosnt renderingWidth = view360.renderer.width * view360.renderer.pixelRatio;\n * ```\n */\n public get pixelRatio() { return this._pixelRatio; }\n /**\n * Fixed rendering buffer width, if set.\n * @ko 고정 렌더링 버퍼 너비 (설정된 경우).\n * @since 4.0.0\n */\n public get renderWidth() { return this._renderSize.width; }\n /**\n * Fixed rendering buffer height, if set.\n * @ko 고정 렌더링 버퍼 높이 (설정된 경우).\n * @since 4.0.0\n */\n public get renderHeight() { return this._renderSize.height; }\n /**\n * Width / height ratio (= width / height)\n * @ko 너비 / 높이의 비율 (= width / height)\n * @since 4.0.0\n * @example\n * ```js\n * const aspect = view360.renderer.width / view360.renderer.pixelRatio;\n * assert(aspect === view360.renderer.aspect);\n * ```\n */\n public get aspect() { return this._elementSize.x / this._elementSize.y; }\n\n /**\n * Create new instance\n * @ko 새 인스턴스를 생성합니다.\n * @param canvas - Canvas element {@ko 캔버스 엘리먼트}\n * @param debug - Whether to enable WebGL debugging {@ko WebGL debug 활성화 여부 }\n */\n public constructor(canvas: HTMLCanvasElement, debug: boolean) {\n this._canvas = canvas;\n this._elementSize = { x: 0, y: 0 };\n this._pixelRatio = 1;\n this._renderSize = { width: null, height: null };\n this.ctx = new WebGLContext(canvas, debug);\n }\n\n /**\n * Destroy instance and release all resources.\n * @ko 인스턴스를 제거하고 사용된 리소스를 전부 해제합니다.\n * @since 4.0.0\n */\n public destroy() {\n const canvas = this._canvas;\n\n this.ctx.destroy();\n canvas.width = 1;\n canvas.height = 1;\n }\n\n /**\n * Resize canvas and renew inner size cache.\n * @ko 캔버스의 크기를 재계산해서 내부의 사이즈 캐시값을 갱신합니다.\n * @since 4.0.0\n */\n public resize() {\n const canvas = this._canvas;\n const canvasSize = this._elementSize;\n const devicePixelRatio = window.devicePixelRatio;\n\n canvasSize.x = canvas.clientWidth;\n canvasSize.y = canvas.clientHeight;\n\n const cssWidth = canvasSize.x || 1;\n const cssHeight = canvasSize.y || 1;\n const fixedWidth = this._renderSize.width;\n const fixedHeight = this._renderSize.height;\n let renderWidth: number;\n let renderHeight: number;\n\n if (fixedWidth != null && fixedHeight != null) {\n renderWidth = fixedWidth;\n renderHeight = fixedHeight;\n } else if (fixedWidth != null) {\n renderWidth = fixedWidth;\n renderHeight = Math.max(1, Math.round(renderWidth * cssHeight / cssWidth));\n } else if (fixedHeight != null) {\n renderHeight = fixedHeight;\n renderWidth = Math.max(1, Math.round(renderHeight * cssWidth / cssHeight));\n } else {\n renderWidth = Math.max(1, Math.round(cssWidth * devicePixelRatio));\n renderHeight = Math.max(1, Math.round(cssHeight * devicePixelRatio));\n }\n\n canvas.width = renderWidth;\n canvas.height = renderHeight;\n\n this._pixelRatio = renderWidth / cssWidth;\n this.ctx.resize();\n }\n\n public setRenderSize(width: number | null, height: number | null) {\n const normalizedWidth = width != null && width > 0 ? Math.round(width) : null;\n const normalizedHeight = height != null && height > 0 ? Math.round(height) : null;\n\n this._renderSize = {\n width: normalizedWidth,\n height: normalizedHeight\n };\n }\n\n /**\n * Render projection\n * @ko 프로젝션을 렌더링합니다.\n * @param projection - Projection to render {@ko 렌더링할 프로젝션}\n * @param cameraa - Camera instance {@ko 카메라의 인스턴스}\n * @since 4.0.0\n */\n public render(mesh: TriangleMesh, camera: Camera) {\n const ctx = this.ctx;\n if (ctx.lost) return;\n\n ctx.clear();\n ctx.useProgram(mesh.program);\n ctx.updateCommonUniforms(mesh, camera, mesh.program);\n mesh.update({ camera });\n ctx.updateUniforms(mesh.program);\n ctx.draw(mesh.vao, mesh.program);\n }\n\n /**\n * Render VR frame, only used for rendering frames inside VR sessions.\n * @ko VR 프레임을 렌더링합니다. VR 세션 진입 도중에만 사용됩니다.\n * @internal\n * @param mesh - Triangle mesh to render {@ko 렌더링할 메쉬}\n * @param vr - Instance of XRManager {@ko XRManager의 인스턴스}\n * @param frame - VR frame {@ko VR 프레임}\n * @since 4.0.0\n */\n public renderVR(mesh: TriangleMesh, vr: XRManager, frame: XRFrame) {\n const ctx = this.ctx;\n const eyeParams = vr.getEyeParams(frame);\n\n if (!eyeParams || !mesh) return;\n\n ctx.bindXRFrame(frame);\n ctx.useProgram(mesh.program);\n ctx.updateUniforms(mesh.program);\n\n eyeParams.forEach((eye, eyeIndex) => {\n const viewport = eye.viewport;\n // We're using \"mesh.matrix\"(=local matrix) here for efficiency\n // As projection doesn't require world matrix, as it doesn't have any parent or child\n const mvMatrix = mat4.multiply(mat4.create(), eye.vMatrix, mesh.matrix);\n\n ctx.viewport(viewport.x, viewport.y, viewport.width, viewport.height);\n ctx.updateVRUniforms(mesh.program, mvMatrix, eye.pMatrix, eyeIndex);\n ctx.draw(mesh.vao, mesh.program);\n });\n }\n}\n\nexport default WebGLRenderer;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport type Hls from \"hls.js\";\nimport Camera, { CameraOptions } from \"./core/Camera\";\nimport PanoControl, { PanoControlOptions } from \"./control/PanoControl\";\nimport TextureLoader from \"./core/TextureLoader\";\nimport FrameAnimator from \"./core/FrameAnimator\";\nimport AutoResizer from \"./core/AutoResizer\";\nimport Autoplay, { AutoplayOptions } from \"./core/Autoplay\";\nimport CameraPath from \"./core/CameraPath\";\nimport TriangleMesh from \"./core/TriangleMesh\";\nimport XRManager from \"./core/XRManager\";\nimport View360Error from \"./core/View360Error\";\nimport Projection from \"./projection/Projection\";\nimport HotspotRenderer, { HotspotOptions } from \"./hotspot/HotspotRenderer\";\nimport WebGLRenderer from \"./core/WebGLRenderer\";\nimport Texture from \"./texture/Texture\";\nimport View360Plugin from \"./plugin/View360Plugin\";\nimport ERROR from \"./const/error\";\nimport { CONTROL_EVENTS, VIDEO_TIME_CHANGE_EVENT } from \"./const/internal\";\nimport { DEFAULT_CLASS, EVENTS } from \"./const/external\";\nimport { findCanvas, getElement } from \"./utils\";\nimport * as EVENT_TYPES from \"./type/events\";\nimport { EventParams } from \"./type/utils\";\n\n/**\n * Events that {@link View360} can trigger\n * @ko {@link View360}가 트리거할 수 있는 이벤트들\n * @see [Detailed Example](/docs/events/ready)\n * @since 4.0.0\n */\nexport interface View360Events {\n [EVENTS.READY]: EVENT_TYPES.ReadyEvent;\n [EVENTS.LOAD_START]: EVENT_TYPES.LoadStartEvent;\n [EVENTS.LOAD]: EVENT_TYPES.LoadEvent;\n [EVENTS.PROJECTION_CHANGE]: EVENT_TYPES.ProjectionChangeEvent;\n [EVENTS.RESIZE]: EVENT_TYPES.ResizeEvent;\n [EVENTS.BEFORE_RENDER]: EVENT_TYPES.BeforeRenderEvent;\n [EVENTS.RENDER]: EVENT_TYPES.RenderEvent;\n [EVENTS.INPUT_START]: EVENT_TYPES.InputStartEvent;\n [EVENTS.INPUT_END]: EVENT_TYPES.InputEndEvent;\n [EVENTS.VIEW_CHANGE]: EVENT_TYPES.ViewChangeEvent;\n [EVENTS.STATIC_CLICK]: EVENT_TYPES.StaticClickEvent;\n [EVENTS.VR_START]: EVENT_TYPES.VRStartEvent;\n [EVENTS.VR_END]: EVENT_TYPES.VREndEvent;\n}\n\n/**\n * Options for {@link View360}\n * @ko {@link View360}용 옵션들\n * @see [Detailed Example](/docs/options)\n * @since 4.0.0\n */\nexport interface View360Options extends CameraOptions, PanoControlOptions {\n projection: Projection | null;\n hotspot: Partial<HotspotOptions>;\n autoplay: boolean | Partial<AutoplayOptions>;\n autoInit: boolean;\n autoResize: boolean;\n /**\n * Fixed rendering buffer width. When set, canvas rendering size is decoupled from CSS size.\n * @ko 고정 렌더링 버퍼 너비. 설정 시 캔버스 렌더링 크기가 CSS 크기와 분리됩니다.\n */\n renderWidth: number | null;\n /**\n * Fixed rendering buffer height. When set, canvas rendering size is decoupled from CSS size.\n * @ko 고정 렌더링 버퍼 높이. 설정 시 캔버스 렌더링 크기가 CSS 크기와 분리됩니다.\n */\n renderHeight: number | null;\n canvasSelector: string;\n useResizeObserver: boolean;\n tabIndex: number | null;\n on: Partial<{ [key in keyof View360Events]: (evt: View360Events[key]) => any }>;\n plugins: View360Plugin[];\n maxDeltaTime: number;\n debug: boolean;\n}\n\n/**\n * Panorama 360 image viewer\n * @ko 파노라마 360 이미지 뷰어\n * @since 4.0.0\n * @see View360Options\n * @see View360Events\n */\nclass View360 extends Component<View360Events> {\n /**\n * Current version string of the View360\n * @ko View360의 현재 버젼 문자열\n * @since 4.0.0\n * @readonly\n * @example\n * ```ts\n * // If the installed version of the View360 is v4.0.0, View360.VERSION is equal to \"4.0.0\"\n * console.log(View360.VERSION) // 4.0.0\n * ```\n */\n public static readonly VERSION = \"#__VERSION__#\";\n\n private _rootEl: HTMLElement;\n private _renderer: WebGLRenderer;\n private _camera: Camera;\n private _control: PanoControl;\n private _animator: FrameAnimator;\n private _autoplay: Autoplay;\n private _cameraPath: CameraPath;\n private _cameraPathPaused: boolean;\n private _hotspot: HotspotRenderer;\n private _projection: Projection | null;\n private _mesh: TriangleMesh | null;\n private _autoResizer: AutoResizer;\n private _vr: XRManager;\n private _plugins: View360Plugin[];\n private _initialized: boolean;\n private _videoEventTarget: HTMLVideoElement | null;\n private _earlyHls: Hls | null = null;\n\n private _autoInit: View360Options[\"autoInit\"];\n private _autoResize: View360Options[\"autoResize\"];\n private _renderWidth: View360Options[\"renderWidth\"];\n private _renderHeight: View360Options[\"renderHeight\"];\n private _canvasSelector: View360Options[\"canvasSelector\"];\n private _useResizeObserver: View360Options[\"useResizeObserver\"];\n private _tabIndex: View360Options[\"tabIndex\"];\n private _debug: View360Options[\"debug\"];\n\n /**\n * Root element (`.view360-container`)\n * @ko 루트 엘리먼트 (`.view360-container`)\n * @since 4.0.0\n * @readonly\n * @example\n * ```html\n * <div id=\"viewer\" class=\"view360-container\">\n * <canvas class=\"view360-canvas\"></canvas>\n * </div>\n * ```\n * ```ts\n * import View360 from \"@egjs/view360\";\n *\n * const viewer = new View360(\"#viewer\");\n * console.log(viewer.rootEl); // Element with id \"viewer\"\n * ```\n */\n public get rootEl() { return this._rootEl; }\n /**\n * Projection renderer.\n * @ko 프로젝션 렌더러.\n * @since 4.0.0\n * @readonly\n */\n public get renderer() { return this._renderer; }\n /**\n * Fixed rendering buffer width.\n * @ko 고정 렌더링 버퍼 너비.\n * @since 4.0.0\n */\n public get renderWidth() { return this._renderWidth; }\n public set renderWidth(val: View360Options[\"renderWidth\"]) {\n this._renderWidth = val != null && val > 0 ? val : null;\n this._renderer.setRenderSize(this._renderWidth, this._renderHeight);\n this.resize();\n }\n /**\n * Fixed rendering buffer height.\n * @ko 고정 렌더링 버퍼 높이.\n * @since 4.0.0\n */\n public get renderHeight() { return this._renderHeight; }\n public set renderHeight(val: View360Options[\"renderHeight\"]) {\n this._renderHeight = val != null && val > 0 ? val : null;\n this._renderer.setRenderSize(this._renderWidth, this._renderHeight);\n this.resize();\n }\n /**\n * Projection camera.\n * @ko 프로젝션 카메라.\n * @since 4.0.0\n * @readonly\n */\n public get camera() { return this._camera; }\n /**\n * Rotate/Zoom Controller.\n * @ko 회전/줌 컨트롤러.\n * @since 4.0.0\n * @readonly\n */\n public get control() { return this._control; }\n /**\n * Camera path controller.\n * @ko 자동 운경 컨트롤러.\n * @since 4.0.0\n * @readonly\n */\n public get cameraPath() { return this._cameraPath; }\n /**\n * Hls instance for current video source.\n * @ko 현재 비디오 소스에 연결된 Hls 인스턴스.\n * @since 4.0.0\n * @readonly\n */\n public get hls(): Hls | null {\n if (this._earlyHls) return this._earlyHls;\n const texture = this._mesh?.getTexture();\n if (!texture || !texture.isVideo()) return null;\n return texture.hls || null;\n }\n /**\n * WebXR-based VR manager.\n * @ko WebXR 기반의 VR 기능 매니저 인스턴스.\n * @since 4.0.0\n * @readonly\n * @example\n * ```ts\n * // Example: Enter VR\n * // This must be called on user interaction, else will be rejected.\n * viewer.vr.enter();\n * ```\n */\n public get vr() { return this._vr; }\n /**\n * Hotspot renderer.\n * You can also change options of {@link View360Options#hotspot} with this.\n * @ko 핫스팟 렌더러 인스턴스.\n * {@link View360Options#hotspot} 옵션 변경도 가능합니다.\n * @since 4.0.0\n * @readonly\n */\n public get hotspot() { return this._hotspot; }\n /**\n * An array of plugins added.\n * @ko 추가된 플러그인의 배열\n * @since 4.0.0\n * @readonly\n * @example\n * ```ts\n * const viewer = new View360(\"#el_id\", {\n * plugins: [new ControlBar()]\n * });\n *\n * console.log(viewer.plugins); // [ControlBar]\n *\n * viewer.addPlugins(new LoadingSpinner()) // [ControlBar, LoadingSpinner];\n * ```\n */\n public get plugins() { return this._plugins; }\n /**\n * An instance of {@link Projection} that currently enabled. `null` if not initialized yet.\n * You should call {@link View360#load} to change panorama src or projection type.\n * @ko 현재 사용중인 {@link Projection}의 인스턴스. 프로젝션을 활성화하지 않았을 경우 `null`입니다.\n * 파노라마 이미지 소스나 프로젝션 타입을 변경하려면 {@link View360#load}를 호출하면 됩니다.\n * @since 4.0.0\n * @example\n * ```ts\n * const viewer = new View360\n * ```\n */\n public get projection() { return this._projection; }\n public set projection(val: View360Options[\"projection\"]) {\n if (this._initialized && val) {\n this.load(val);\n } else {\n this._projection = val;\n }\n }\n /**\n * An instance of triangle mesh to render.\n * @ko 렌더링할 triangle mesh의 인스턴스\n * @internal\n * @since 4.0.0\n * @readonly\n */\n public get mesh() { return this._mesh; }\n /**\n * A boolean value whether {@link View360#init init()} is called before.\n * @ko {@link View360#init init()}이 호출되었는지 여부를 가리키는 값\n * @since 4.0.0\n * @readonly\n * @example\n * ```ts\n * const viewer = new View360(\"#el\", { autoInit: false });\n *\n * console.log(viewer.initialized); // false\n *\n * await viewer.init();\n *\n * console.log(viewer.initialized); // true\n * ```\n */\n public get initialized() { return this._initialized; }\n /**\n * Instance of the Autoplay manager.\n * You can also change {@link View360Options#autoplay} options with this.\n * @ko Autoplay 기능의 매니저 인스턴스.\n * 이 인스턴스를 통해 {@link View360Options#autoplay} 옵션을 변경하는 것도 가능합니다.\n * @since 4.0.0\n * @readonly\n * @example\n * ```ts\n * // Disable autoplay\n * viewer.autoplay.disable();\n * ```\n */\n public get autoplay() { return this._autoplay; }\n /**\n * When this value is `true` and {@link View360Options#projection} is set, {@link View360#init init()} will be called automatically when instance is created.\n * @ko 이 값이 `true`이고, {@link View360Options#projection}이 설정되었으면, 인스턴스 생성 시점에 자동으로 {@link View360#init init()}을 호출합니다.\n * @default true\n * @since 4.0.0\n * @example\n * ```ts\n * import View360, { EquirectProjection, EVENTS } from \"@egjs/view360\";\n *\n * // viewer.init() is called on instance creation\n * // But as `init` is asynchronous, you should wait for \"ready\" event if you want to do something after initialization.\n * const viewer = new View360(\"#el_id\", {\n * autoInit: true,\n * projection: new EquirectProjection({ src: \"SRC_TO_URL\" })\n * });\n *\n * console.log(viewer.initialized); // false, as `init` is asynchronous\n *\n * viewer.once(EVENTS.READY, () => {\n * console.log(viewer.initialized); // true\n * });\n * ```\n */\n public get autoInit() { return this._autoInit; }\n /**\n * When `true`, {@link View360#resize} is called when the canvas size is changed.\n * @ko `true`일 경우, 캔버스의 크기가 변경되었을 때 자동으로 {@link View360#resize}를 호출합니다.\n * @default true\n * @since 4.0.0\n * @see View360#useResizeObserver\n * @example\n * ```ts\n * const viewer = new View360(\"#el_id\", {\n * autoResize: true\n * });\n *\n * // This can trigger `viewer.resize()` if the canvas size was not 400px\n * const canvas = viewer.renderer.canvas;\n * canvas.style.width = \"400px\";\n * ```\n */\n public get autoResize() { return this._autoResize; }\n /**\n * CSS selector for canvas element to render panorama image/video.\n * The canvas element should be placed inside the root element. (Dont' have to be direct child)\n * @ko 파노라마 이미지/비디오를 렌더링할 canvas 엘리먼트의 CSS 선택자\n * 캔버스 엘리먼트는 루트 엘리먼트 내부에 있어야합니다. 루트 엘리먼트의 직계 자식 엘리먼트(Direct child element)일 필요는 없습니다.\n * @default \"canvas\"\n * @since 4.0.0\n * @example\n * ```html\n * <div class=\"view360-container\">\n * <canvas id=\"not_this_one\"></canvas>\n * <!-- This will be selected -->\n * <canvas id=\"canvas_to_select\"></canvas>\n * </div>\n * ```\n *\n * ```ts\n * const viewer = new View360(\"#el_id\", {\n * canvasSelector: \"#canvas_to_select\"\n * });\n * ```\n */\n public get canvasSelector() { return this._canvasSelector; }\n /**\n * When `true`, it will use {@link ResizeObserver} API to detect canvas size change when {@link View360Options#autoResize} is enabled.\n * @ko `true`일 때 {@link View360Options#autoResize}가 활성화되었으면, 사용 가능한 환경에서 {@link ResizeObserver} API를 사용해서 캔버스 크기 변화를 추적합니다.\n * @default true\n * @since 4.0.0\n */\n public get useResizeObserver() { return this._useResizeObserver; }\n /**\n * {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex tabindex} attribute for the canvas element.\n * This is necessary for the keyboard controls.\n * By default, `0` will be assigned. `null` to disable.\n * @ko 캔버스 엘리먼트에 적용할 {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex tabindex} 어트리뷰트의 값.\n * 이 값을 설정해야만 키보드 컨트롤을 사용 가능합니다.\n * 기본값으로 `0`이 설정됩니다. `null`로 지정하면 `tabindex`를 설정하지 않습니다.\n * @see RotateControlOptions#disableKeyboard\n * @default 0\n * @since 4.0.0\n * @example\n * ```ts\n * const viewer = new View360(\"#el_id\", {\n * tabindex: 5\n * });\n * ```\n *\n * ```html\n * <!-- After init -->\n * <div class=\"view360-container\">\n * <canvas class=\"view360-canvas\" tabindex=\"5\"></canvas>\n * </div>\n * ```\n */\n public get tabIndex() { return this._tabIndex; }\n public set tabIndex(val: View360Options[\"tabIndex\"]) {\n const canvas = this._renderer.canvas;\n this._tabIndex = val;\n\n if (val != null) {\n canvas.tabIndex = val;\n } else {\n canvas.removeAttribute(\"tabindex\");\n }\n }\n /**\n * A maximum delta time between frames in seconds.\n * It can prevent camera or control changing too fast when frame being late.\n * @ko 프레임간 시간 차이의 최대값. (초 단위)\n * 퍼포먼스 등의 이유로 프레임 렌더링이 늦어졌을 때, 화면이 갑작스럽게 바뀌는 것을 막아줍니다.\n * @default 1 / 30\n * @since 4.0.0\n */\n public get maxDeltaTime() { return this._animator.maxDeltaTime; }\n public set maxDeltaTime(val: View360Options[\"maxDeltaTime\"]) { this._animator.maxDeltaTime = val; }\n /**\n * Enable WebGL debugging. Setting this to `true` can decrease performance.\n * This is used internally on developing View360.\n * @ko WebGL 디버깅을 활성화합니다. 이 값을 `true`로 할 경우 성능이 하락할 수 있습니다.\n * 이 옵션은 View360을 개발하기 위해 내부적으로 사용됩니다.\n * @default false\n */\n public get debug() { return this._debug; }\n public set debug(val: View360Options[\"debug\"]) { this._debug = val; }\n\n // Camera options\n /**\n * Initial yaw (y-axis rotation) value for camera. (in degrees, °)\n * As View360 uses right-handed coordinate system internally, camera will rotate counter-clockwise by this value.\n * @ko 카메라의 초기 yaw(y축 회전)값 (도 단위, °)\n * View360은 오른손 좌표계를 사용하기 때문에, 카메라가 해당 값만큼 시계 반대방향으로 회전합니다.\n * @default 0\n * @since 4.0.0\n * @example\n * ```ts\n * const viewer = new View360(\"#el_id\", {\n * initialYaw: 30\n * });\n *\n * viewer.on(\"ready\", () => {\n * console.log(viewer.camera.yaw); // 30\n * });\n * ```\n */\n public get initialYaw() { return this._camera.initialYaw; }\n public set initialYaw(val: View360Options[\"initialYaw\"]) { this._camera.initialYaw = val; }\n /**\n * Initial pitch (x-axis rotation) value for camera. (in degrees, °)\n * As View360 uses right-handed coordinate system internally, positive value will make camera to look upside, while negative value will look down.\n * @ko 카메라의 초기 pitch(x축 회전)값 (도 단위, °)\n * View360은 오른손 좌표계를 사용하기 때문에, 양(+)의 값은 카메라가 위를 보게 하고, 음(-)의 값은 카메라가 아래를 보게 합니다.\n * @default 0\n * @since 4.0.0\n * @example\n * ```ts\n * const viewer = new View360(\"#el_id\", {\n * initialPitch: 60\n * });\n *\n * viewer.on(\"ready\", () => {\n * console.log(viewer.camera.pitch); // 60\n * });\n * ```\n */\n public get initialPitch() { return this._camera.initialPitch; }\n public set initialPitch(val: View360Options[\"initialPitch\"]) { this._camera.initialPitch = val; }\n /**\n * Initial zoom value for camera.\n * Setting this value to `2` will enlarge panorama 200% by width.\n * @ko 카메라의 초기 줌 값.\n * 이 값을 `2`로 설정할 경우 파노라마 이미지를 가로 기준 200%만큼 확대합니다.\n * @default 1\n * @since 4.0.0\n * @example\n * ```ts\n * const viewer = new View360(\"#el_id\", {\n * initialZoom: 2\n * });\n *\n * viewer.on(\"ready\", () => {\n * console.log(viewer.camera.zoom); // 2\n * });\n * ```\n */\n public get initialZoom() { return this._camera.initialZoom; }\n public set initialZoom(val: View360Options[\"initialZoom\"]) { this._camera.initialZoom = val; }\n /**\n * Restrict yaw(y-axis rotation) range. (in degrees, °)\n * @ko yaw(y축 회전) 범위를 제한합니다. (도 단위, °)\n * @since 4.0.0\n * @example\n * ```ts\n * const viewer = new View360(\"#el_id\", {\n * yawRange: [-30, 30]\n * });\n *\n * viewer.on(\"ready\", () => {\n * console.log(viewer.camera.yaw); // 0\n * viewer.camera.lookAt({ yaw: 60 });\n * console.log(viewer.camera.yaw); // 30\n * });\n * ```\n */\n public get yawRange() { return this._camera.yawRange; }\n public set yawRange(val: View360Options[\"yawRange\"]) {\n this._camera.yawRange = val;\n if (this._projection) this._projection.updateCamera(this._camera);\n }\n /**\n * Restrict pitch(x-axis rotation) range. (in degrees, °)\n * @ko pitch(x축 회전) 범위를 제한합니다. (도 단위, °)\n * @default null\n * @since 4.0.0\n * @example\n * ```ts\n * const viewer = new View360(\"#el_id\", {\n * pitchRange: [-45, 45]\n * });\n *\n * viewer.on(\"ready\", () => {\n * console.log(viewer.camera.pitch); // 0\n * viewer.camera.lookAt({ pitch: 60 });\n * console.log(viewer.camera.pitch); // 45\n * });\n * ```\n */\n public get pitchRange() { return this._camera.pitchRange; }\n public set pitchRange(val: View360Options[\"pitchRange\"]) {\n this._camera.pitchRange = val;\n if (this._projection) this._projection.updateCamera(this._camera);\n }\n /**\n * Restrict camera zoom range.\n * If `null`, a default zoom range from `0.6` to `10` will be used.\n * @ko 카메라 줌 범위를 제한합니다.\n * `null`일 경우 기본값으로 `0.6`에서 `10`의 범위를 사용합니다.\n * @default null\n * @since 4.0.0\n * @example\n * ```ts\n * const viewer = new View360(\"#el_id\", {\n * zoomRange: [0.5, 4]\n * });\n *\n * viewer.on(\"ready\", () => {\n * console.log(viewer.camera.zoom); // 1\n * viewer.camera.lookAt({ zoom: 6 });\n * console.log(viewer.camera.zoom); // 4\n * });\n * ```\n */\n public get zoomRange() { return this._camera.zoomRange; }\n public set zoomRange(val: View360Options[\"zoomRange\"]) {\n this._camera.zoomRange = val;\n if (this._projection) this._projection.updateCamera(this._camera);\n }\n /**\n * Camera's horizontal FOV(Field of View). (in degrees, °)\n * @ko 카메라의 수평 FOV(Field of View) 값. (도 단위, °)\n * @default 90\n * @since 4.0.0\n * @example\n * ```ts\n * // Init with fov: 120\n * const viewer = new View360(\"#el_id\", { fov: 120 });\n *\n * // Back to 90\n * viewer.fov = 90;\n * ```\n */\n public get fov() { return this._camera.fov; }\n public set fov(val: View360Options[\"fov\"]) {\n const camera = this._camera;\n const control = this._control;\n\n camera.fov = val;\n camera.updateMatrix();\n control.sync();\n }\n\n // Control options\n /**\n * A control for camera rotation.\n * You can also change options of {@link View360Options#rotate} with this.\n * @ko 카메라 회전을 담당하는 컨트롤.\n * {@link View360Options#rotate} 옵션 변경도 가능합니다.\n * @since 4.0.0\n * @readonly\n */\n public get rotate() { return this._control.rotate; }\n /**\n * A control for camera zoom.\n * You can also change options of {@link View360Options#zoom} with this.\n * @ko 카메라 줌을 담당하는 컨트롤.\n * {@link View360Options#zoom} 옵션 변경도 가능합니다.\n * @since 4.0.0\n * @readonly\n */\n public get zoom() { return this._control.zoom; }\n /**\n * A control for camera rotation with gyroscope input.\n * You can also change options of {@link View360Options#gyro} with this.\n * @ko 자이로스코프를 통한 카메라 회전을 담당하는 컨트롤.\n * {@link View360Options#gyro} 옵션 변경도 가능합니다.\n * @since 4.0.0\n * @readonly\n */\n public get gyro() { return this._control.gyro; }\n /**\n * Apply CSS {@link https://developer.mozilla.org/en-US/docs/Web/CSS/cursor cursor} by current state of input when using mouse.\n * If `true`, this will add CSS style to canvas element. It'll apply `cursor: \"grab\"` by default and `cursor: \"grabbing\"` when holding the mouse button.\n * @ko 마우스 사용시 CSS {@link https://developer.mozilla.org/en-US/docs/Web/CSS/cursor cursor}값을 자동으로 변경할지 여부.\n * `true`일 경우 기본 상태에서 `cursor: \"grab\"`을, 입력 도중에 `cursor: \"grabbing\"`을 캔버스에 적용합니다.\n * @default true\n * @since 4.0.0\n */\n public get useGrabCursor() { return this._control.useGrabCursor; }\n public set useGrabCursor(val: View360Options[\"useGrabCursor\"]) { this._control.useGrabCursor = val; }\n /**\n * Disable context menu which pops up on mouse right click.\n * @ko 마우스 우클릭시 표시되는 컨텍스트 메뉴를 비활성화합니다.\n * @default false\n * @since 4.0.0\n */\n public get disableContextMenu() { return this._control.disableContextMenu; }\n public set disableContextMenu(val: View360Options[\"disableContextMenu\"]) { this._control.disableContextMenu = val; }\n /**\n * If `true`, enables scroll on mobile(touch) devices on canvas.\n * :::caution\n * When this option is enabled, users must swipe horizontally first then vertically to change view up or down.\n * :::\n * @ko `true`로 설정할 경우, 모바일(터치) 환경의 캔버스 영역 내에서 스크롤을 가능하게 합니다.\n * :::caution\n * 이 값을 활성화할 경우, 사용자가 카메라 뷰를 위/아래로 바꾸기 위해서는 먼저 가로로 스와이프한 이후에 세로로 스와이프해야만 합니다.\n * :::\n * @since 4.0.0\n * @default true\n */\n public get scrollable() { return this._control.scrollable; }\n public set scrollable(val: View360Options[\"scrollable\"]) { this._control.scrollable = val; }\n /**\n * If `true`, enables scroll by mouse wheel on canvas.\n * :::caution\n * When this option is enabled, zoom by mouse wheel will be disabled.\n * :::\n * @ko `true`로 설정할 경우, 캔버스 영역 내에서 마우스 휠을 이용한 페이지 스크롤이 가능해집니다.\n * :::caution\n * 이 값을 활성화할 경우, 마우스 휠을 통한 줌이 불가능하게 됩니다.\n * :::\n * @since 4.0.0\n * @default false\n */\n public get wheelScrollable() { return this._control.wheelScrollable; }\n public set wheelScrollable(val: View360Options[\"wheelScrollable\"]) { this._control.wheelScrollable = val; }\n\n /**\n * Create new instance of View360\n * @ko View360의 새로운 인스턴스를 생성합니다\n * @param root - Root element(`.view360-container`) to mount View360\n * Can be either a CSS selector or HTMLElement.\n * {@ko View360을 마운트할 루트 엘리먼트, CSS 셀렉터나 HTMLElement를 지정 가능합니다.}\n * @param options - Options to apply\n * {@ko 적용할 옵션들}\n * @example\n * ```ts\n * import View360, { EquirectProjection } from \"@egjs/view360\";\n *\n * // Create new View360 instance\n * const viewer = new View360(\"#id-of-a-container\", {\n * projection: new EquirectProjection({\n * src: \"URL_TO_PANORAMA_IMAGE_OR_VIDEO\",\n * })\n * });\n * ```\n */\n public constructor(root: string | HTMLElement, {\n projection = null,\n initialYaw = 0,\n initialPitch = 0,\n initialZoom = 1,\n yawRange = null,\n pitchRange = null,\n zoomRange = null,\n fov = 90,\n useGrabCursor = true,\n disableContextMenu = false,\n rotate = true,\n zoom = true,\n gyro = false,\n scrollable = true,\n wheelScrollable = false,\n autoplay = false,\n hotspot = {},\n autoInit = true,\n autoResize = true,\n renderWidth = null,\n renderHeight = null,\n canvasSelector = \"canvas\",\n useResizeObserver = true,\n on = {},\n plugins = [],\n maxDeltaTime = 1 / 30,\n tabIndex = 0,\n debug = false\n }: Partial<View360Options> = {}) {\n super();\n\n this._rootEl = getElement(root);\n this._plugins = plugins;\n this._initialized = false;\n\n // Options\n this._autoInit = autoInit;\n this._autoResize = autoResize;\n this._renderWidth = renderWidth != null && renderWidth > 0 ? renderWidth : null;\n this._renderHeight = renderHeight != null && renderHeight > 0 ? renderHeight : null;\n this._canvasSelector = canvasSelector;\n this._useResizeObserver = useResizeObserver;\n this._tabIndex = tabIndex;\n this._debug = debug;\n\n // Core components\n const canvas = findCanvas(this._rootEl, canvasSelector);\n this._renderer = new WebGLRenderer(canvas, debug);\n this._renderer.setRenderSize(this._renderWidth, this._renderHeight);\n this._camera = new Camera({\n initialYaw,\n initialPitch,\n initialZoom,\n fov,\n yawRange,\n pitchRange,\n zoomRange\n });\n this._control = new PanoControl(canvas, this._camera, {\n useGrabCursor,\n scrollable,\n wheelScrollable,\n disableContextMenu,\n rotate,\n zoom,\n gyro\n });\n this._animator = new FrameAnimator(maxDeltaTime);\n this._autoplay = new Autoplay(this, canvas, autoplay);\n this._cameraPath = new CameraPath(this);\n this._cameraPathPaused = false;\n this._projection = projection;\n this._mesh = null;\n this._autoResizer = new AutoResizer(useResizeObserver, () => this.resize());\n this._vr = new XRManager(this._renderer.ctx);\n this._hotspot = new HotspotRenderer(this._rootEl, this._renderer, hotspot);\n this._videoEventTarget = null;\n\n this._addEventHandlers(on);\n\n if (projection && autoInit) {\n this.init();\n }\n }\n\n /**\n * Destroy instance and release all resources.\n * @ko 인스턴스를 제거하고 모든 리소스를 해제합니다.\n * @since 4.0.0\n */\n public destroy() {\n this._camera.destroy();\n this._animator.stop();\n this._renderer.destroy();\n this._control.destroy();\n this._cameraPath.destroy();\n this._autoResizer.disable();\n this._unbindVideoEvents();\n\n if (this._mesh) {\n this._mesh.destroy(this._renderer.ctx);\n this._mesh = null;\n }\n\n this._plugins.forEach(plugin => plugin.destroy(this));\n\n this._earlyHls = null;\n this._initialized = false;\n }\n\n /**\n * Initialize inner components and load projection src.\n * @ko 내부 컴포넌트들을 초기화하고 프로젝션 소스를 로드합니다.\n * @since 4.0.0\n */\n public async init() {\n if (!this._projection) {\n throw new View360Error(ERROR.MESSAGES.PROVIDE_PROJECTION_FIRST, ERROR.CODES.PROVIDE_PROJECTION_FIRST);\n }\n\n const renderer = this._renderer;\n const camera = this._camera;\n const control = this._control;\n const animator = this._animator;\n const hotspot = this._hotspot;\n const projection = this._projection;\n const canvas = renderer.canvas;\n\n this._bindComponentEvents();\n renderer.ctx.init();\n this._resizeComponents();\n camera.updateMatrix();\n\n if (this._autoResize) {\n this._autoResizer.enable(canvas);\n }\n\n if (!this._autoplay.enableBlocked) {\n this._autoplay.enable();\n }\n\n this._plugins.forEach(plugin => {\n plugin.init(this);\n });\n\n const texture = await this._loadTexture(projection);\n this._applyProjection(projection, texture);\n hotspot.refresh();\n animator.start(this._renderFrameOnDemand);\n await control.enable();\n\n if (this._tabIndex != null && !canvas.hasAttribute(\"tabIndex\")) {\n canvas.tabIndex = this._tabIndex;\n }\n\n this._initialized = true;\n this.renderFrame(0);\n\n this._emit(EVENTS.READY);\n }\n\n /**\n * Load new panorama image/video and display it.\n * This will {@link View360#init init()} View360 if it's not initialized yet.\n * @ko 새로운 파노라마 이미지 혹은 비디오를 로드하고 표시합니다.\n * 만약 View360이 아직 초기화되지 않았다면, {@link View360#init init()}을 호출합니다.\n * @param projection - Projection & video options for new source. {@ko 새로운 파노라마 이미지/비디오에 적용할 옵션들}\n * @returns `Promise<true>` if load was successful. {@ko 프로젝션 로드에 성공했을 경우 `Promise<true>`를 반환합니다. }\n * @since 4.0.0\n * @example\n * ```ts\n * // Change to video\n * viewer.load({\n * src: \"URL_TO_NEW_VIDEO\",\n * video: true\n * });\n * ```\n */\n public async load(projection: Projection): Promise<boolean> {\n if (!projection) return false;\n\n if (this._initialized) {\n const texture = await this._loadTexture(projection);\n this._applyProjection(projection, texture);\n this.renderFrame(0);\n } else {\n // Should update internal options before init\n this._projection = projection;\n this.init();\n }\n\n return true;\n }\n\n /**\n * Refresh component's size by current\n * @ko View360이 내부적으로 캐시하고 있는 엘리먼트 크기를 현재 크기로 갱신합니다.\n * @since 4.0.0\n */\n public resize() {\n if (!this._initialized) return;\n\n this._resizeComponents();\n\n // To prevent flickering, render immediately after resizing components\n this.renderFrame(0);\n\n const { width, height } = this._renderer;\n\n this._emit(EVENTS.RESIZE, {\n width,\n height\n });\n }\n\n /**\n * Add new plugins\n * @ko 새로운 플러그인을 추가합니다.\n * @param plugins Plugins to add {@ko 추가할 플러그인들}\n * @see View360Options#plugins\n * @since 4.0.0\n * @example\n * ```ts\n * // Add a single plugin\n * viewer.addPlugins(new ControlBar());\n *\n * // Add multiple plugins\n * viewer.addPlugins(new ControlBar(), new LoadingSpinner());\n * ```\n */\n public addPlugins(...plugins: View360Plugin[]) {\n if (this._initialized) {\n plugins.forEach(plugin => { plugin.init(this); });\n }\n\n this._plugins.push(...plugins);\n }\n\n /**\n * Remove plugins.\n * @ko 플러그인을 제거합니다.\n * @param plugins Plugins to remove {@ko 제거할 플러그인들}\n * @since 4.0.0\n * @example\n * ```ts\n * // Remove a single plugin\n * viewer.removePlugins(plugin1);\n *\n * // Remove multiple plugins\n * viewer.removePlugins(plugin2, plugin3);\n * ```\n */\n public removePlugins(...plugins: View360Plugin[]) {\n plugins.forEach(plugin => {\n const pluginIdx = this._plugins.indexOf(plugin);\n\n if (pluginIdx < 0) return;\n\n plugin.destroy(this);\n this._plugins.splice(pluginIdx, 1);\n });\n }\n\n /**\n * Render a single panorama image/video frame.\n * Rendering is performed automatically on demand, so you usually don't have to call this.\n * Call this when a frame is not renewed after changing options.\n * @ko 파노라마 이미지/비디오의 한 프레임을 렌더링합니다.\n * 프레임 갱신은 보통 필요한 때에만 자동적으로 이루어지기 때문에, 보통은 이 메소드를 호출할 필요는 없습니다.\n * 옵션 변경 이후에도 프레임 갱신이 이루어지지 않는다면, 이 메소드를 호출해주세요.\n * @param delta Delta time in milisec. {@ko 프레임간 시간 차이, 밀리초 단위}\n * @since 4.0.0\n */\n public renderFrame = (delta: number) => {\n const camera = this._camera;\n const renderer = this._renderer;\n const control = this._control;\n const hotspot = this._hotspot;\n const autoPlayer = this._autoplay;\n const cameraPath = this._cameraPath;\n const mesh = this._mesh;\n\n if (!mesh) return;\n\n const texture = mesh.getTexture();\n const video = texture && texture.isVideo() ? texture.source : null;\n const useCameraPath = cameraPath.enabled && cameraPath.hasFrames && !!video;\n\n this._emit(EVENTS.BEFORE_RENDER);\n\n if (autoPlayer.playing && !useCameraPath) {\n autoPlayer.update(delta);\n control.sync();\n }\n\n if (useCameraPath) {\n const paused = video!.paused || video!.ended;\n\n if (paused) {\n if (!this._cameraPathPaused) {\n control.sync();\n this._cameraPathPaused = true;\n }\n } else {\n this._cameraPathPaused = false;\n cameraPath.updateFromVideo(video!, camera);\n }\n\n control.updateByCameraPath(delta);\n } else if (camera.animation) {\n this._cameraPathPaused = false;\n camera.animation.update(delta);\n } else {\n this._cameraPathPaused = false;\n control.update(delta);\n }\n\n renderer.render(mesh, camera);\n hotspot.render(camera);\n\n if (camera.changed) {\n this._emit(EVENTS.VIEW_CHANGE, {\n yaw: camera.yaw,\n pitch: camera.pitch,\n zoom: camera.zoom,\n quaternion: [\n camera.quaternion[0],\n camera.quaternion[1],\n camera.quaternion[2],\n camera.quaternion[3]\n ]\n });\n }\n camera.onFrameRender();\n\n this._emit(EVENTS.RENDER);\n };\n\n private _emit<K extends keyof View360Events>(eventName: K, ...params: EventParams<View360Events, K>) {\n const evtParams = params ? params[0] : {};\n\n this.trigger(eventName as any, {\n type: eventName,\n target: this,\n ...evtParams\n });\n }\n\n private _renderFrameOnDemand = (delta: number) => {\n const camera = this._camera;\n const control = this._control;\n const autoplay = this._autoplay;\n const mesh = this._mesh;\n const texture = mesh?.getTexture();\n\n if (!this._initialized || !texture) return;\n const isVideo = texture.isVideo();\n const isVideoPaused = isVideo && texture.isPaused();\n if (\n !camera.animation\n && !control.animating\n && !autoplay.playing\n && (!isVideo || isVideoPaused)\n ) return;\n\n this.renderFrame(delta);\n };\n\n private _renderVRFrame = (_delta: number, frame: XRFrame) => {\n const vr = this._vr;\n const mesh = this._mesh;\n const renderer = this._renderer;\n\n if (!mesh) return;\n\n this._emit(EVENTS.BEFORE_RENDER);\n\n renderer.renderVR(mesh, vr, frame);\n\n this._emit(EVENTS.RENDER);\n }\n\n private _applyProjection(projection: Projection, texture: Texture) {\n const camera = this._camera;\n const control = this._control;\n const renderer = this._renderer;\n const mesh = this._mesh;\n\n this._unbindVideoEvents();\n\n // Remove previous context\n if (mesh) {\n mesh.destroy(renderer.ctx);\n }\n\n const newMesh = projection.createMesh(renderer.ctx, texture);\n projection.updateCamera(camera);\n projection.updateControl(control);\n\n this._mesh = newMesh;\n if (texture.isVideo()) {\n this._bindVideoEvents(texture.source);\n }\n this._emit(EVENTS.PROJECTION_CHANGE, {\n projection\n });\n }\n\n private async _loadTexture(projection: Projection): Promise<Texture> {\n const contentLoader = new TextureLoader(this._debug);\n const { src, video } = projection;\n\n this._emit(EVENTS.LOAD_START, {\n src,\n video\n });\n\n const loadPromise = contentLoader.load(src, video);\n this._earlyHls = contentLoader.pendingHls;\n\n let texture: Texture;\n try {\n texture = await loadPromise;\n } catch (err) {\n this._earlyHls = null;\n throw err;\n }\n\n this._emit(EVENTS.LOAD, {\n src,\n video\n });\n\n return texture;\n }\n\n private _resizeComponents() {\n const renderer = this._renderer;\n const camera = this._camera;\n const control = this._control;\n\n renderer.resize();\n camera.resize(renderer.width, renderer.height);\n control.resize(renderer.width, renderer.height);\n }\n\n private _addEventHandlers(events: View360Options[\"on\"]) {\n // Bind option \"on\"\n Object.keys(events).forEach((evtName: keyof typeof EVENT_TYPES) => {\n this.on(evtName, events[evtName]);\n });\n }\n\n private _bindComponentEvents() {\n // Bind internal component events\n const root = this._rootEl;\n const control = this._control;\n const animator = this._animator;\n const renderer = this._renderer;\n const vr = this._vr;\n\n const controlEventsToPropagate = [\n CONTROL_EVENTS.STATIC_CLICK,\n CONTROL_EVENTS.INPUT_START,\n CONTROL_EVENTS.INPUT_END\n ];\n\n controlEventsToPropagate.forEach(evtName => {\n control.rotate.on(evtName, evt => {\n this._emit(evtName, evt);\n });\n\n control.zoom.on(evtName, evt => {\n this._emit(evtName, evt);\n });\n });\n\n vr.on(EVENTS.VR_START, evt => {\n root.classList.add(DEFAULT_CLASS.IN_VR);\n\n animator.changeContext(evt.session);\n animator.start(this._renderVRFrame);\n\n this._emit(EVENTS.VR_START);\n });\n\n vr.on(EVENTS.VR_END, () => {\n root.classList.remove(DEFAULT_CLASS.IN_VR);\n\n renderer.ctx.useDefaultFrameBuffer();\n animator.changeContext(window);\n animator.start(this._renderFrameOnDemand);\n\n this.resize();\n\n this._emit(EVENTS.VR_END);\n });\n }\n\n private _bindVideoEvents(video: HTMLVideoElement) {\n if (this._videoEventTarget === video) return;\n this._unbindVideoEvents();\n\n this._videoEventTarget = video;\n video.addEventListener(\"seeked\", this._onVideoTimeUpdate);\n video.addEventListener(\"timeupdate\", this._onVideoTimeUpdate);\n video.addEventListener(VIDEO_TIME_CHANGE_EVENT, this._onVideoTimeUpdate);\n }\n\n private _unbindVideoEvents() {\n if (!this._videoEventTarget) return;\n\n this._videoEventTarget.removeEventListener(\"seeked\", this._onVideoTimeUpdate);\n this._videoEventTarget.removeEventListener(\"timeupdate\", this._onVideoTimeUpdate);\n this._videoEventTarget.removeEventListener(VIDEO_TIME_CHANGE_EVENT, this._onVideoTimeUpdate);\n this._videoEventTarget = null;\n }\n\n private _onVideoTimeUpdate = (evt: Event) => {\n const video = evt.currentTarget as HTMLVideoElement | null;\n if (!video) return;\n if (!video.paused && !video.ended) return;\n\n const cameraPath = this._cameraPath;\n if (!cameraPath.enabled || !cameraPath.hasFrames) return;\n\n const mesh = this._mesh;\n const texture = mesh?.getTexture();\n if (!texture || !texture.isVideo() || texture.source !== video) return;\n\n this.renderFrame(0);\n };\n}\n\nexport default View360;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport { mat4, quat, vec3 } from \"gl-matrix\";\nimport { OBJECT_3D_EVENTS } from \"../const/internal\";\nimport Camera from \"./Camera\";\n\n/**\n * Context interface used for object update\n * @internal\n */\ninterface ObjectUpdateContext {\n camera: Camera;\n}\n\n/**\n * Base class for 3D objects\n * @ko 3D 오브젝트의 베이스 클래스\n * @since 4.0.0\n * @internal\n */\nclass Object3D extends Component<{\n [OBJECT_3D_EVENTS.UPDATE]: {\n camera: Camera\n };\n}> {\n /**\n * Local matrix of the object\n * @ko 오브젝트의 local matrix\n * @since 4.0.0\n */\n public matrix: mat4;\n /**\n * Rotation quaternion\n * @ko 현재 오브젝트의 회전을 나타내는 사원수 값\n * @since 4.0.0\n */\n public rotation: quat;\n /**\n * Position of the object\n * @ko 오브젝트의 위치\n * @since 4.0.0\n */\n public position: vec3;\n /**\n * A scale vector of the object\n * @ko 오브젝트가 각 축으로 확대된 정도를 나타내는 벡터\n * @since 4.0.0\n */\n public scale: vec3;\n\n /**\n * Create new instance.\n * @ko 새로운 인스턴스를 생성합니다.\n */\n public constructor() {\n super();\n\n this.matrix = mat4.create();\n this.rotation = quat.create();\n this.position = vec3.fromValues(0, 0, 0);\n this.scale = vec3.fromValues(1, 1, 1);\n }\n\n /**\n * Update local matrix of the object.\n * @ko 오브젝트의 local matrix를 갱신합니다.\n * @since 4.0.0\n */\n public updateMatrix() {\n mat4.fromRotationTranslationScale(this.matrix, this.rotation, this.position, this.scale);\n }\n\n public update(ctx: ObjectUpdateContext) {\n this.trigger(OBJECT_3D_EVENTS.UPDATE, ctx);\n }\n}\n\nexport default Object3D;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport View360Plugin from \"../View360Plugin\";\nimport View360 from \"../../View360\";\nimport { EVENTS } from \"../../const/external\";\nimport { createElement } from \"../../utils\";\nimport { LoadStartEvent } from \"../../type/events\";\n\n/**\n * Options for {@link LoadingSpinner}\n * @ko {@link LoadingSpinner}용 옵션들\n * @since 4.0.0\n * @category Plugin\n */\nexport interface LoadingSpinnerOptions {\n /**\n * Override default class names.\n * @ko 디폴트 클래스 이름들을 오버라이드합니다.\n * @since 4.0.0\n */\n className: Partial<{ -readonly [key in keyof typeof LoadingSpinner.DEFAULT_CLASS]: string }>;\n}\n\n/**\n * A plugin that displays loading spinner while loading the projection.\n * @ko 프로젝션 로딩중에 로딩 스피너를 보여주는 플러그인\n * @since 4.0.0\n * @category Plugin\n */\nclass LoadingSpinner implements View360Plugin {\n /**\n * Default class names that LoadingSpinner uses\n * @ko LoadingSpinner가 사용하는 디폴트 클래스 이름\n * @since 4.0.0\n */\n public static readonly DEFAULT_CLASS = {\n /**\n * A class name for the container element\n * @ko 컨테이너 엘리먼트의 클래스 이름\n * @since 4.0.0\n */\n CONTAINER: \"view360-spinner\",\n /**\n * A class name for the spinning ring element\n * @ko 돌아가는 링 엘리먼트의 클래스 이름\n * @since 4.0.0\n */\n RING: \"view360-spinner-ring\"\n } as const;\n\n /**\n * A class names overriding\n * @ko 현재 오버라이드 중인 클래스 이름\n * @since 4.0.0\n */\n public readonly className: LoadingSpinnerOptions[\"className\"];\n\n private _container: HTMLElement;\n\n /**\n * Create a new instance of LoadingSpinner. {@ko LoadingSpinner의 새 인스턴스를 생성합니다.}\n * @param options Options {@ko 옵션들}\n */\n public constructor({\n className = {}\n }: Partial<LoadingSpinnerOptions> = {}) {\n this.className = className;\n this._container = this._createElements();\n }\n\n public init(viewer: View360) {\n viewer.on(EVENTS.LOAD_START, this._startLoading);\n }\n\n public destroy(viewer: View360): void {\n viewer.off(EVENTS.LOAD_START, this._startLoading);\n this._detachElements({ target: viewer });\n }\n\n private _startLoading = ({ target: viewer }: LoadStartEvent) => {\n viewer.rootEl.appendChild(this._container);\n\n if (viewer.initialized) {\n viewer.once(EVENTS.LOAD, this._detachElements);\n } else {\n viewer.once(EVENTS.READY, this._detachElements);\n }\n };\n\n private _detachElements = ({ target: viewer }: { target: View360 }) => {\n const container = this._container;\n if (!container) return;\n\n if (container.parentElement === viewer.rootEl) {\n viewer.rootEl.removeChild(container);\n }\n };\n\n private _createElements() {\n const className = {\n ...this.className,\n ...LoadingSpinner.DEFAULT_CLASS\n };\n\n const container = createElement(className.CONTAINER);\n const ring = createElement(className.RING);\n\n container.appendChild(ring);\n\n return container;\n }\n}\n\nexport default LoadingSpinner;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\n/* eslint-disable @typescript-eslint/no-empty-function */\n/* eslint-disable @typescript-eslint/no-unused-vars */\nimport ControlBar from \"./ControlBar\";\nimport View360 from \"../../View360\";\n\n/**\n * Common options for {@link ControlBarItem}\n * @ko {@link ControlBarItem}의 공통 옵션들\n * @category Plugin\n * @since 4.0.0\n */\nexport interface ControlBarItemOptions {\n /**\n * @copy ControlBarItem#position\n */\n position: typeof ControlBar.POSITION[keyof typeof ControlBar.POSITION];\n /**\n * @copy ControlBarItem#order\n */\n order: number;\n}\n\n/**\n * Interface of the ControlBar items\n * @ko 컨트롤바 아이템의 인터페이스\n * @category Plugin\n * @group ControlBar\n * @since 4.0.0\n */\nabstract class ControlBarItem {\n /**\n * Element of the item.\n * @ko 아이템의 엘리먼트\n * @since 4.0.0\n */\n public abstract element: HTMLElement;\n\n /**\n * Position to display item.\n * @ko 아이템을 표시할 위치.\n * @since 4.0.0\n */\n public position: ControlBarItemOptions[\"position\"];\n /**\n * Order within the same position.\n * The lowest one will be shown first.\n * @ko 동일한 position 내에서의 순서, 작을수록 먼저 표시됩니다.\n * @since 4.0.0\n */\n public order: ControlBarItemOptions[\"order\"];\n\n /**\n * Create new instance of the ControlBarItem\n * @ko ControlBarItem의 새로운 인스턴스를 생성합니다.\n * @param options Options {@ko 옵션들}\n */\n public constructor(options: ControlBarItemOptions) {\n this.position = options.position;\n this.order = options.order;\n }\n\n /**\n * Initialize item.\n * @ko 아이템을 초기화합니다.\n * @param viewer - A instance of viewer to attach item {@ko 아이템을 부착할 뷰어의 인스턴스}\n * @param controlBar - A instance of control bar to attach item {@ko 아이템을 부착할 컨트롤바의 인스턴스}\n * @since 4.0.0\n */\n public abstract init(viewer: View360, controlBar: ControlBar): any;\n /**\n * Destroy item and release all resources & event handlers.\n * @ko 아이템을 제거하고 할당된 모든 리소스 및 이벤트 핸들러를 제거합니다.\n * @param viewer - A instance of viewer to detach item {@ko 아이템을 떼어 낼 뷰어의 인스턴스}\n * @param controlBar - A instance of control bar to detach item {@ko 아이템을 떼어 낼 컨트롤바의 인스턴스}\n * @since 4.0.0\n */\n public abstract destroy(viewer: View360, controlBar: ControlBar): any;\n}\n\nexport default ControlBarItem;\n","export const CONTROL_BAR_DEFAULT_CLASS = {\n CONTROLS_ROOT: \"view360-controls\",\n CONTROLS_BG: \"view360-controls-background\",\n CONTROLS_MAIN: \"view360-controls-main\",\n CONTROLS_TOP: \"view360-controls-top\",\n CONTROLS_BOTTOM: \"view360-controls-bottom\",\n CONTROLS_MID: \"view360-controls-mid\",\n CONTROLS_LEFT: \"view360-controls-left\",\n CONTROLS_RIGHT: \"view360-controls-right\",\n CONTROLS_FLOAT_LEFT: \"view360-controls-float-left\",\n CONTROLS_FLOAT_RIGHT: \"view360-controls-float-right\",\n CONTROLS_BUTTON: \"view360-controls-button\",\n PROGRESS_ROOT: \"view360-controls-progress\",\n VOLUME_ROOT: \"view360-controls-volume\",\n RANGE_ROOT: \"view360-range\",\n RANGE_TRACK: \"view360-range-track\",\n RANGE_THUMB: \"view360-range-thumb\",\n RANGE_FILLER: \"view360-range-filler\",\n PLAY_BUTTON: \"view360-controls-play\",\n PAUSE_BUTTON: \"view360-controls-pause\",\n UNMUTED_BUTTON: \"view360-controls-unmuted\",\n MUTED_BUTTON: \"view360-controls-muted\",\n FULLSCREEN_BUTTON: \"view360-controls-fullscreen\",\n FULLSCREEN_EXIT_BUTTON: \"view360-controls-fullscreen-exit\",\n VR_BUTTON: \"view360-controls-vr\",\n GYRO_ENABLED: \"view360-controls-gyro-enabled\",\n GYRO_DISABLED: \"view360-controls-gyro-disabled\",\n VIDEO_TIME_DISPLAY: \"view360-controls-time\",\n PIEVIEW_ROOT: \"view360-controls-pie\",\n FIXED: \"view360-controls-fixed\",\n UNAVAILABLE: \"view360-controls-unavailable\",\n HIDDEN: \"view360-controls-hidden\"\n} as const;\n\nexport const CONTROL_BAR_ITEM_POSITION = {\n /**\n * Place control bar item floating at top-left corner\n * @ko 아이템을 왼쪽 위 구석에 표시합니다.\n * @since 4.0.0\n */\n TOP_LEFT: \"top-left\",\n /**\n * Place control bar item floating at top-right corner\n * @ko 아이템을 오른쪽 위 구석에 표시합니다.\n * @since 4.0.0\n */\n TOP_RIGHT: \"top-right\",\n /**\n * Place control bar item at upper block inside the bottom control bar.\n * @ko 아이템을 하단에 표시되는 컨트롤바 내에서 위쪽 블럭에 표시합니다.\n * @since 4.0.0\n */\n MAIN_TOP: \"main-top\",\n /**\n * Place control bar item at lower block inside the bottom control bar.\n * @ko 아이템을 하단에 표시되는 컨트롤바 내에서 하단 블럭에 표시합니다.\n * @since 4.0.0\n */\n MAIN_BOTTOM: \"main-bottom\",\n /**\n * Place control bar item at center-left block inside the bottom control bar.\n * @ko 아이템을 하단에 표시되는 컨트롤바 내에서 중간 왼쪽 블럭에 표시합니다.\n * @since 4.0.0\n */\n MAIN_LEFT: \"main-left\",\n /**\n * Place control bar item at center-right block inside the bottom control bar.\n * @ko 아이템을 하단에 표시되는 컨트롤바 내에서 중간 오른쪽 블럭에 표시합니다.\n * @since 4.0.0\n */\n MAIN_RIGHT: \"main-right\"\n} as const;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Component from \"@egjs/component\";\nimport { ControlBarOptions } from \"./ControlBar\";\nimport { CONTROL_BAR_DEFAULT_CLASS } from \"./const\";\nimport Motion from \"../../core/Motion\";\nimport MouseInput from \"../../control/input/MouseInput\";\nimport TouchInput from \"../../control/input/TouchInput\";\nimport { CONTROL_EVENTS, INFINITE_RANGE } from \"../../const/internal\";\nimport { clamp } from \"../../utils\";\nimport { InputEvents } from \"../../type/internal\";\nimport { EL_DIV } from \"../../const/browser\";\n\nclass RangeControl extends Component<{\n [CONTROL_EVENTS.INPUT_START]: number;\n [CONTROL_EVENTS.CHANGE]: number;\n [CONTROL_EVENTS.INPUT_END]: void;\n}> {\n public readonly rootEl: HTMLElement;\n public readonly thumbEl: HTMLElement;\n public readonly trackEl: HTMLElement;\n public readonly fillerEl: HTMLElement;\n\n private _motion: Motion;\n private _mouseInput: MouseInput;\n private _touchInput: TouchInput;\n private _fixedClass: string;\n private _bbox: DOMRect;\n\n /**\n *\n */\n public constructor() {\n super();\n\n const root = document.createElement(EL_DIV);\n const track = document.createElement(EL_DIV);\n const thumb = document.createElement(EL_DIV);\n const filler = document.createElement(EL_DIV);\n\n root.draggable = false;\n\n track.appendChild(filler);\n track.appendChild(thumb);\n root.appendChild(track);\n\n this.rootEl = root;\n this.trackEl = track;\n this.thumbEl = thumb;\n this.fillerEl = filler;\n\n this._mouseInput = new MouseInput();\n this._touchInput = new TouchInput();\n this._motion = new Motion({ duration: 1, range: INFINITE_RANGE, easing: x => x });\n this._bbox = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n left: 0,\n right: 0,\n bottom: 0,\n top: 0\n } as DOMRect;\n this._fixedClass = CONTROL_BAR_DEFAULT_CLASS.FIXED;\n }\n\n public init(className: Required<ControlBarOptions[\"className\"]>) {\n const mouseInput = this._mouseInput;\n const touchInput = this._touchInput;\n\n this.rootEl.classList.add(className.RANGE_ROOT);\n this.trackEl.classList.add(className.RANGE_TRACK);\n this.thumbEl.classList.add(className.RANGE_THUMB);\n this.fillerEl.classList.add(className.RANGE_FILLER);\n this._fixedClass = className.FIXED;\n\n mouseInput.on(CONTROL_EVENTS.INPUT_START, this._onHold);\n touchInput.on(CONTROL_EVENTS.INPUT_START, this._onHold);\n\n mouseInput.on(CONTROL_EVENTS.INPUT_END, this._onRelease);\n touchInput.on(CONTROL_EVENTS.INPUT_END, this._onRelease);\n\n mouseInput.on(CONTROL_EVENTS.CHANGE, this._onChange);\n touchInput.on(CONTROL_EVENTS.CHANGE, this._onChange);\n\n mouseInput.enable(this.rootEl);\n touchInput.enable(this.rootEl);\n\n this.resize();\n }\n\n public destroy() {\n const mouseInput = this._mouseInput;\n const touchInput = this._touchInput;\n\n this.rootEl.className = \"\";\n this.trackEl.className = \"\";\n this.thumbEl.className = \"\";\n this.fillerEl.className = \"\";\n\n mouseInput.off();\n touchInput.off();\n mouseInput.disable();\n touchInput.disable();\n }\n\n public resize() {\n this._bbox = this.trackEl.getBoundingClientRect();\n }\n\n public updateStyle(progress: number) {\n const width = this._bbox.width;\n const clampedProgress = clamp(progress, 0, 1);\n\n this.fillerEl.style.width = `${clampedProgress * 100}%`;\n this.thumbEl.style.transform = `translateX(${clampedProgress * width}px)`;\n }\n\n private _onHold = ({ srcEvent, isTouch }: InputEvents<{ x: number; y: number }>[typeof CONTROL_EVENTS.INPUT_START]) => {\n const bbox = this._bbox;\n if (!bbox) return;\n\n const x = isTouch\n ? (srcEvent as TouchEvent).touches[0].pageX\n : (srcEvent as MouseEvent).pageX;\n const elX = bbox.x + (window.scrollX ?? window.pageXOffset);\n\n const clamepdX = clamp(x, elX, elX + bbox.width);\n const progress = (clamepdX - elX) / bbox.width;\n\n this._motion.reset(clamepdX);\n this.thumbEl.classList.add(this._fixedClass);\n\n this.trigger(CONTROL_EVENTS.INPUT_START, progress);\n };\n\n private _onChange = ({ delta }: InputEvents<{ x: number; y: number }>[typeof CONTROL_EVENTS.CHANGE]) => {\n const motion = this._motion;\n const bbox = this._bbox;\n if (!bbox) return;\n\n motion.setNewEndByDelta(delta.x);\n motion.update(1);\n\n const elX = bbox.x + (window.scrollX ?? window.pageXOffset);\n const clampedX = clamp(motion.val, elX, elX + bbox.width);\n const progress = (clampedX - elX) / bbox.width;\n\n this.trigger(CONTROL_EVENTS.CHANGE, progress);\n };\n\n private _onRelease = () => {\n const bbox = this._bbox;\n if (!bbox) return;\n\n this.thumbEl.classList.remove(this._fixedClass);\n\n this.trigger(CONTROL_EVENTS.INPUT_END);\n };\n}\n\nexport default RangeControl;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ControlBar from \"./ControlBar\";\nimport ControlBarItem, { ControlBarItemOptions } from \"./ControlBarItem\";\nimport RangeControl from \"./RangeControl\";\nimport View360 from \"../../View360\";\nimport TextureVideo from \"../../texture/TextureVideo\";\nimport { CONTROL_EVENTS, VIDEO_TIME_CHANGE_EVENT } from \"../../const/internal\";\nimport { CONTROL_BAR_ITEM_POSITION } from \"./const\";\nimport { EVENTS } from \"../../const/external\";\nimport * as BROWSER from \"../../const/browser\";\n\n/**\n * Show video progress bar.\n * @ko 비디오의 프로그레스 바를 표시합니다.\n * @category Plugin\n * @group ControlBar\n * @since 4.0.0\n */\nclass ProgressBar extends ControlBarItem {\n public get element() { return this._rangeControl.rootEl; }\n\n private _controlBar: ControlBar | null;\n private _video: TextureVideo | null;\n private _rangeControl: RangeControl;\n\n private _wasPaused: boolean;\n private _currentTime: number;\n private _duration: number;\n private _playPromise: Promise<void> | null;\n\n /**\n * Create a new instance.\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor({\n position = CONTROL_BAR_ITEM_POSITION.MAIN_TOP,\n order = 9999\n }: Partial<ControlBarItemOptions> = {}) {\n super({\n position,\n order\n });\n\n this.position = position;\n this.order = order;\n\n this._controlBar = null;\n this._rangeControl = new RangeControl();\n\n this._video = null;\n this._wasPaused = false;\n this._currentTime = 0;\n this._duration = 0;\n this._playPromise = null;\n }\n\n public init(viewer: View360, controlBar: ControlBar) {\n const video = viewer.mesh?.getTexture();\n const element = this.element;\n const rangeControl = this._rangeControl;\n const unavailableClass = controlBar.className.UNAVAILABLE;\n\n if (!video || !video.isVideo()) {\n element.classList.add(unavailableClass);\n return;\n }\n\n element.classList.remove(unavailableClass);\n element.classList.add(controlBar.className.PROGRESS_ROOT);\n viewer.on(EVENTS.RESIZE, this._onResize);\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_TIME_UPDATE, this._onTimeUpdate);\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_DURATION_CHANGE, this._onDurationChange);\n video.source.addEventListener(VIDEO_TIME_CHANGE_EVENT, this._onTimeUpdate);\n rangeControl.init(controlBar.className);\n rangeControl.on(CONTROL_EVENTS.INPUT_START, this._onHold);\n rangeControl.on(CONTROL_EVENTS.CHANGE, this._onControl);\n rangeControl.on(CONTROL_EVENTS.INPUT_END, this._onRelease);\n\n this._video = video;\n this._currentTime = video.source.currentTime;\n this._duration = video.source.duration;\n this._controlBar = controlBar;\n\n rangeControl.updateStyle(this._currentTime / this._duration);\n }\n\n public destroy(viewer: View360) {\n const video = this._video;\n\n viewer.off(EVENTS.RESIZE, this._onResize);\n\n if (video) {\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_TIME_UPDATE, this._onTimeUpdate);\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_DURATION_CHANGE, this._onDurationChange);\n video.source.removeEventListener(VIDEO_TIME_CHANGE_EVENT, this._onTimeUpdate);\n }\n\n this._rangeControl.destroy();\n this._video = null;\n this._playPromise = null;\n }\n\n private _onResize = () => {\n this._rangeControl.resize();\n }\n\n private _onTimeUpdate = () => {\n const video = this._video;\n if (!video) return;\n\n this._currentTime = video.source.currentTime;\n this._rangeControl.updateStyle(this._currentTime / this._duration);\n };\n\n private _onDurationChange = () => {\n const video = this._video;\n if (!video) return;\n\n this._duration = video.source.duration;\n this._rangeControl.updateStyle(this._currentTime / this._duration);\n };\n\n private _onHold = (progress: number) => {\n const video = this._video;\n const controlBar = this._controlBar;\n if (!video || !controlBar) return;\n\n const paused = video.isPaused();\n\n video.source.pause();\n\n const time = video.source.duration * progress;\n video.source.currentTime = time;\n video.source.dispatchEvent(new CustomEvent(VIDEO_TIME_CHANGE_EVENT, { detail: { time }}));\n\n controlBar.rootEl.classList.add(controlBar.className.FIXED);\n this._wasPaused = !this._playPromise && paused;\n };\n\n private _onControl = (progress: number) => {\n const video = this._video;\n if (!video) return;\n\n const time = video.source.duration * progress;\n video.source.currentTime = time;\n video.source.dispatchEvent(new CustomEvent(VIDEO_TIME_CHANGE_EVENT, { detail: { time }}));\n };\n\n private _onRelease = () => {\n const video = this._video;\n const controlBar = this._controlBar;\n\n if (video && controlBar) {\n if (!this._wasPaused && !this._playPromise) {\n this._playPromise = video.source.play()\n .catch(() => void 0);\n\n // This should not be chained\n this._playPromise.then(() => {\n this._playPromise = null;\n });\n\n controlBar.rootEl.classList.remove(controlBar.className.FIXED);\n }\n }\n\n this._wasPaused = false;\n };\n}\n\nexport default ProgressBar;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ControlBar from \"./ControlBar\";\nimport ControlBarItem, { ControlBarItemOptions } from \"./ControlBarItem\";\nimport { CONTROL_BAR_ITEM_POSITION } from \"./const\";\nimport View360 from \"../../View360\";\nimport TextureVideo from \"../../texture/TextureVideo\";\nimport * as BROWSER from \"../../const/browser\";\n\n/**\n * Show video play / pause button.\n * @ko 비디오 재생 / 일시정지 버튼을 표시합니다.\n * @category Plugin\n * @group ControlBar\n * @since 4.0.0\n */\nclass PlayButton extends ControlBarItem {\n public readonly element: HTMLElement;\n private _controlBar: ControlBar | null;\n private _video: TextureVideo | null;\n private _paused: boolean;\n\n /**\n * Create a new instance.\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor({\n position = CONTROL_BAR_ITEM_POSITION.MAIN_LEFT,\n order = 9999\n }: Partial<ControlBarItemOptions> = {}) {\n super({\n position,\n order\n });\n\n this.element = document.createElement(BROWSER.EL_BUTTON);\n\n this._video = null;\n this._paused = true;\n this._controlBar = null;\n }\n\n public init(viewer: View360, controlBar: ControlBar) {\n const element = this.element;\n const video = viewer.mesh?.getTexture();\n const className = controlBar.className;\n const unavailableClass = className.UNAVAILABLE;\n\n if (!video || !video.isVideo()) {\n element.classList.add(unavailableClass);\n return;\n }\n\n element.classList.add(className.CONTROLS_BUTTON);\n element.classList.remove(unavailableClass);\n\n const paused = video.isPaused();\n this._video = video;\n this._paused = paused;\n this._controlBar = controlBar;\n\n if (paused) {\n this._onPause();\n } else {\n this._onPlay();\n }\n\n element.addEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_PLAY, this._onPlay);\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_PAUSE, this._onPause);\n }\n\n public destroy() {\n const video = this._video;\n const element = this.element;\n\n if (!video) return;\n\n element.className = \"\";\n element.removeEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_PLAY, this._onPlay);\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_PAUSE, this._onPause);\n\n this._video = null;\n this._paused = true;\n this._controlBar = null;\n }\n\n private _onClick = () => {\n const video = this._video;\n if (!video) return;\n\n if (this._paused) {\n video.source.play();\n } else {\n video.source.pause();\n }\n };\n\n private _onPlay = () => {\n if (!this._controlBar) return;\n\n const element = this.element;\n const className = this._controlBar.className;\n\n element.classList.add(className.PAUSE_BUTTON);\n element.classList.remove(className.PLAY_BUTTON);\n element.title = \"Pause Video\";\n\n this._paused = false;\n };\n\n private _onPause = () => {\n if (!this._controlBar) return;\n\n const element = this.element;\n const className = this._controlBar.className;\n\n element.classList.add(className.PLAY_BUTTON);\n element.classList.remove(className.PAUSE_BUTTON);\n element.title = \"Play Video\";\n\n this._paused = true;\n };\n}\n\nexport default PlayButton;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ControlBar from \"./ControlBar\";\nimport ControlBarItem, { ControlBarItemOptions } from \"./ControlBarItem\";\nimport RangeControl from \"./RangeControl\";\nimport { CONTROL_BAR_ITEM_POSITION } from \"./const\";\nimport View360 from \"../../View360\";\nimport TextureVideo from \"../../texture/TextureVideo\";\nimport * as BROWSER from \"../../const/browser\";\nimport { CONTROL_EVENTS } from \"../../const/internal\";\nimport { EVENTS } from \"../../const/external\";\n\n/**\n * Show video volume control.\n * @ko 비디오 볼륨 조절 버튼을 표시합니다.\n * @category Plugin\n * @group ControlBar\n * @since 4.0.0\n */\nclass VolumeControl extends ControlBarItem {\n public get element() { return this._rootEl; }\n\n private _controlBar: ControlBar | null;\n private _rootEl: HTMLButtonElement;\n private _buttonEl: HTMLElement;\n private _rangeControl: RangeControl;\n private _video: TextureVideo | null;\n\n /**\n * Create a new instance.\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor({\n position = CONTROL_BAR_ITEM_POSITION.MAIN_RIGHT,\n order = 9999\n }: Partial<ControlBarItemOptions> = {}) {\n super({\n position,\n order\n });\n\n this._controlBar = null;\n this._rangeControl = new RangeControl();\n this._createElements();\n\n this._video = null;\n }\n\n public init(viewer: View360, controlBar: ControlBar) {\n const video = viewer.mesh?.getTexture();\n const root = this._rootEl;\n const button = this._buttonEl;\n const rangeControl = this._rangeControl;\n const className = controlBar.className;\n const unavailableClass = className.UNAVAILABLE;\n\n if (!video || !video.isVideo()) {\n root.classList.add(unavailableClass);\n return;\n }\n\n root.classList.remove(unavailableClass);\n root.classList.add(className.CONTROLS_BUTTON);\n root.classList.add(className.VOLUME_ROOT);\n button.classList.add(className.CONTROLS_BUTTON);\n\n if (video.source.muted) {\n button.classList.add(className.MUTED_BUTTON);\n } else {\n button.classList.add(className.UNMUTED_BUTTON);\n }\n\n viewer.on(EVENTS.RESIZE, this._onResize);\n root.addEventListener(BROWSER.EVENTS.TRANSITION_END, this._onResize);\n button.addEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_VOLUME_CHANGE, this._onVolumeChange);\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_LOADED_DATA, this._updateDisplay);\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_CAN_PLAYTHROUGH, this._updateDisplay);\n\n rangeControl.init(className);\n rangeControl.on(CONTROL_EVENTS.INPUT_START, this._onHold);\n rangeControl.on(CONTROL_EVENTS.CHANGE, this._onChange);\n rangeControl.on(CONTROL_EVENTS.INPUT_END, this._onRelease);\n\n this._controlBar = controlBar;\n this._video = video;\n\n this._updateDisplay();\n }\n\n public destroy(viewer: View360) {\n const video = this._video;\n const button = this._buttonEl;\n const root = this._rootEl;\n\n root.className = \"\";\n button.className = \"\";\n\n viewer.off(EVENTS.RESIZE, this._onResize);\n root.removeEventListener(BROWSER.EVENTS.TRANSITION_END, this._onResize);\n button.removeEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n\n if (video) {\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_VOLUME_CHANGE, this._onVolumeChange);\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_LOADED_DATA, this._updateDisplay);\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_CAN_PLAYTHROUGH, this._updateDisplay);\n }\n\n this._controlBar = null;\n this._rangeControl.destroy();\n this._video = null;\n }\n\n private _onResize = () => {\n this._rangeControl.resize();\n this._updateDisplay();\n }\n\n private _onClick = () => {\n const video = this._video;\n if (!video || this._rootEl.disabled) return;\n\n video.source.muted = !video.source.muted;\n };\n\n private _onVolumeChange = () => {\n const button = this._buttonEl;\n const video = this._video;\n const controlBar = this._controlBar;\n\n if (!video || !controlBar) return;\n\n const className = controlBar.className;\n\n if (video.source.muted || video.source.volume === 0) {\n button.classList.add(className.MUTED_BUTTON);\n button.classList.remove(className.UNMUTED_BUTTON);\n } else {\n button.classList.add(className.UNMUTED_BUTTON);\n button.classList.remove(className.MUTED_BUTTON);\n }\n\n this._updateDisplay();\n };\n\n private _createElements() {\n const root = document.createElement(BROWSER.EL_BUTTON);\n const buttonEl = document.createElement(BROWSER.EL_DIV);\n\n root.appendChild(this._rangeControl.rootEl);\n root.appendChild(buttonEl);\n root.title = \"Toggle Mute\";\n\n this._rootEl = root;\n this._buttonEl = buttonEl;\n }\n\n private _onHold = (progress: number) => {\n const video = this._video;\n const controlBar = this._controlBar;\n\n if (!video || !controlBar) return;\n\n const className = controlBar.className;\n\n video.source.volume = progress;\n\n this._rootEl.classList.add(className.FIXED);\n controlBar.containerEl.classList.add(className.FIXED);\n\n this._updateDisplay();\n };\n\n private _onChange = (progress: number) => {\n const video = this._video;\n if (!video) return;\n\n video.source.volume = progress;\n if (progress > 0) {\n video.source.muted = false;\n } else {\n video.source.muted = true;\n }\n\n this._updateDisplay();\n };\n\n private _onRelease = () => {\n const controlBar = this._controlBar;\n if (!controlBar) return;\n\n const className = controlBar.className;\n\n this._rootEl.classList.remove(className.FIXED);\n controlBar.containerEl.classList.remove(className.FIXED);\n };\n\n private _updateDisplay = () => {\n const video = this._video;\n const root = this._rootEl;\n if (!video) return;\n\n if (!video.hasAudio()) {\n root.disabled = true;\n return;\n }\n\n root.disabled = false;\n\n const volume = video.source.muted ? 0 : video.source.volume;\n\n this._rangeControl.updateStyle(volume);\n };\n}\n\nexport default VolumeControl;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ControlBar from \"./ControlBar\";\nimport ControlBarItem, { ControlBarItemOptions } from \"./ControlBarItem\";\nimport { CONTROL_BAR_ITEM_POSITION } from \"./const\";\nimport View360 from \"../../View360\";\nimport * as BROWSER from \"../../const/browser\";\nimport { isFullscreen } from \"../../utils\";\n\n/**\n * Show fullscreen enter / exit button.\n * @ko 풀스크린 진입 / 해제 버튼을 표시합니다.\n * @category Plugin\n * @group ControlBar\n * @since 4.0.0\n */\nclass FullscreenButton extends ControlBarItem {\n public readonly element: HTMLElement;\n private _controlBar: ControlBar | null;\n private _targetEl: HTMLElement | null;\n\n /**\n * Create a new instance.\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor({\n position = CONTROL_BAR_ITEM_POSITION.MAIN_RIGHT,\n order = 9999\n }: Partial<ControlBarItemOptions> = {}) {\n super({\n position,\n order\n });\n\n this.element = document.createElement(BROWSER.EL_BUTTON);\n this.element.title = \"Toggle Fullscreen\";\n this._controlBar = null;\n this._targetEl = null;\n }\n\n public init(viewer: View360, controlBar: ControlBar) {\n const element = this.element;\n const className = controlBar.className;\n\n if (!this._fullscreenAvailable()) {\n element.classList.add(className.UNAVAILABLE);\n return;\n }\n\n element.classList.add(className.CONTROLS_BUTTON);\n element.classList.remove(className.UNAVAILABLE);\n element.addEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n this._addFullscreenHandlers();\n\n if (isFullscreen()) {\n element.classList.add(className.FULLSCREEN_EXIT_BUTTON);\n } else {\n element.classList.add(className.FULLSCREEN_BUTTON);\n }\n\n this._controlBar = controlBar;\n this._targetEl = viewer.rootEl;\n }\n\n public destroy() {\n const element = this.element;\n\n element.className = \"\";\n element.removeEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n this._removeFullscreenHandlers();\n\n this._controlBar = null;\n this._targetEl = null;\n }\n\n private _onClick = () => {\n const target = this._targetEl;\n if (!target) return;\n\n if (isFullscreen()) {\n this._exitFullscreen();\n } else {\n this._requestFullscreen(target);\n }\n };\n\n private _fullscreenAvailable() {\n return BROWSER.FULLSCREEN_REQUEST.some(key => !!document[key]);\n }\n\n private _requestFullscreen(el: HTMLElement) {\n for (const key of BROWSER.FULLSCREEN_REQUEST) {\n const request = el[key];\n if (request) {\n request.call(el);\n return;\n }\n }\n }\n\n private _exitFullscreen() {\n for (const key of BROWSER.FULLSCREEN_EXIT) {\n const exit = document[key];\n\n if (exit) {\n exit.call(document);\n return;\n }\n }\n }\n\n private _addFullscreenHandlers() {\n BROWSER.FULLSCREEN_CHANGE.forEach(evtName => {\n document.addEventListener(evtName, this._onFullscreenChange);\n });\n }\n\n private _removeFullscreenHandlers() {\n BROWSER.FULLSCREEN_CHANGE.forEach(evtName => {\n document.removeEventListener(evtName, this._onFullscreenChange);\n });\n }\n\n private _onFullscreenChange = () => {\n const element = this.element;\n const controlBar = this._controlBar;\n\n if (!controlBar) return;\n\n const className = controlBar.className;\n\n if (isFullscreen()) {\n element.classList.add(className.FULLSCREEN_EXIT_BUTTON);\n element.classList.remove(className.FULLSCREEN_BUTTON);\n } else {\n element.classList.add(className.FULLSCREEN_BUTTON);\n element.classList.remove(className.FULLSCREEN_EXIT_BUTTON);\n }\n };\n}\n\nexport default FullscreenButton;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ControlBar from \"./ControlBar\";\nimport ControlBarItem, { ControlBarItemOptions } from \"./ControlBarItem\";\nimport { CONTROL_BAR_ITEM_POSITION } from \"./const\";\nimport View360 from \"../../View360\";\nimport TextureVideo from \"../../texture/TextureVideo\";\nimport * as BROWSER from \"../../const/browser\";\nimport { VIDEO_TIME_CHANGE_EVENT } from \"../../const/internal\";\n\n/**\n * Show video current / total time.\n * @ko 비디오의 현재 / 총 재생시간을 표시합니다.\n * @category Plugin\n * @group ControlBar\n * @since 4.0.0\n */\nclass VideoTime extends ControlBarItem {\n public readonly element: HTMLElement;\n private _video: TextureVideo | null;\n private _currentTime: number;\n private _duration: number;\n\n /**\n * Create a new instance.\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor({\n position = CONTROL_BAR_ITEM_POSITION.MAIN_LEFT,\n order = 9999\n }: Partial<ControlBarItemOptions> = {}) {\n super({\n position,\n order\n });\n\n this.element = document.createElement(BROWSER.EL_DIV);\n\n this._video = null;\n this._currentTime = 0;\n this._duration = 0;\n }\n\n public init(viewer: View360, controlBar: ControlBar) {\n const video = viewer.mesh?.getTexture();\n const element = this.element;\n const className = controlBar.className;\n\n if (!video || !video.isVideo()) {\n element.classList.add(className.UNAVAILABLE);\n return;\n }\n\n element.classList.add(className.VIDEO_TIME_DISPLAY);\n element.classList.remove(className.UNAVAILABLE);\n\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_TIME_UPDATE, this._onTimeUpdate);\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_DURATION_CHANGE, this._onDurationChange);\n video.source.addEventListener(VIDEO_TIME_CHANGE_EVENT, this._onCustomTimeChange);\n\n this._video = video;\n this._currentTime = video.source.currentTime;\n this._duration = video.source.duration;\n\n this._updateDisplay();\n }\n\n public destroy() {\n const video = this._video;\n\n if (!video) return;\n\n this.element.className = \"\";\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_TIME_UPDATE, this._onTimeUpdate);\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_DURATION_CHANGE, this._onDurationChange);\n video.source.removeEventListener(VIDEO_TIME_CHANGE_EVENT, this._onCustomTimeChange);\n\n this._video = null;\n }\n\n private _onTimeUpdate = () => {\n const video = this._video;\n if (!video) return;\n\n this._currentTime = video.source.currentTime;\n this._updateDisplay();\n };\n\n private _onDurationChange = () => {\n const video = this._video;\n if (!video) return;\n\n this._duration = video.source.duration;\n this._updateDisplay();\n };\n\n private _onCustomTimeChange = (evt: CustomEvent<{ time: number }>) => {\n this._currentTime = evt.detail.time;\n this._updateDisplay();\n };\n\n private _updateDisplay() {\n const time = this._currentTime;\n const timeMinute = Math.floor(time / 60);\n const timeSeconds = Math.floor(time - timeMinute * 60);\n const timeSecondsFormatted = timeSeconds < 10 ? `0${timeSeconds}` : timeSeconds;\n\n const duration = this._duration;\n const durationMinute = Math.floor(duration / 60);\n const durationSeconds = Math.floor(duration - durationMinute * 60);\n const durationSecondsFormatted = durationSeconds < 10 ? `0${durationSeconds}` : durationSeconds;\n\n this.element.innerText = `${timeMinute}:${timeSecondsFormatted} / ${durationMinute}:${durationSecondsFormatted}`;\n }\n}\n\nexport default VideoTime;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ControlBar from \"./ControlBar\";\nimport ControlBarItem, { ControlBarItemOptions } from \"./ControlBarItem\";\nimport { CONTROL_BAR_ITEM_POSITION } from \"./const\";\nimport View360 from \"../../View360\";\nimport { circulate, getObjectOption } from \"../../utils\";\nimport * as BROWSER from \"../../const/browser\";\nimport { EVENTS } from \"../../const/external\";\nimport { SVG_NAMESPACE } from \"../../const/internal\";\n\n/**\n * Options for {@link PieView}\n * @ko {@link PieView}용 옵션들\n * @category Plugin\n */\nexport interface PieViewOptions extends ControlBarItemOptions {\n /**\n * @copy PieView#resetCamera\n */\n resetCamera: boolean | Partial<{\n yaw: number;\n pitch: number;\n zoom: number;\n duration: number;\n easing: (x: number) => number;\n }>;\n}\n\n/**\n * Show camera direction/fov indicator.\n * @ko 카메라가 향하는 방향 및 FOV를 표시합니다.\n * @category Plugin\n * @group ControlBar\n * @since 4.0.0\n */\nclass PieView extends ControlBarItem {\n public readonly element: HTMLElement;\n\n /**\n * Set rotation to reset camera to when PieView is clicked.\n * `false` will disable this value, and `true` will enable with default options.\n * @ko PieView가 클릭되었을 때 카메라를 리셋할 방향을 지정합니다.\n * `false`일 경우 이 동작을 비활성화하며, `true`일 경우 기본값을 사용합니다.\n * @since 4.0.0\n */\n public resetCamera: PieViewOptions[\"resetCamera\"];\n\n private _viewer: View360 | null;\n private _piePathEl: SVGPathElement;\n private _rangeCircleEl: SVGCircleElement;\n\n /**\n * Create a new instance.\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor({\n resetCamera = true,\n position = CONTROL_BAR_ITEM_POSITION.TOP_RIGHT,\n order = 9999\n }: Partial<PieViewOptions> = {}) {\n super({\n position,\n order\n });\n\n this.element = document.createElement(BROWSER.EL_DIV);\n this.element.title = \"Reset view\";\n this.resetCamera = resetCamera;\n this._createPieElements();\n this._viewer = null;\n }\n\n public init(viewer: View360, controlBar: ControlBar) {\n const element = this.element;\n\n if (!viewer.initialized) {\n viewer.once(EVENTS.READY, this._updatePie);\n } else {\n this._updatePie({ target: viewer });\n }\n\n const rootClass = controlBar.className.PIEVIEW_ROOT;\n element.classList.add(rootClass);\n\n if (this.resetCamera) {\n element.addEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n }\n\n viewer.on(EVENTS.VIEW_CHANGE, this._updatePie);\n\n this._viewer = viewer;\n }\n\n public destroy(viewer: View360) {\n const element = this.element;\n\n element.removeEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n element.className = \"\";\n viewer.off(EVENTS.READY, this._updatePie);\n viewer.off(EVENTS.VIEW_CHANGE, this._updatePie);\n\n this._viewer = null;\n }\n\n private _onClick = () => {\n const viewer = this._viewer;\n const resetCamera = this.resetCamera;\n\n if (!viewer || !resetCamera) return;\n\n const {\n yaw = viewer.initialYaw,\n pitch = viewer.initialPitch,\n zoom = viewer.initialZoom,\n duration = 500\n } = getObjectOption(resetCamera);\n\n viewer.camera.animateTo({\n yaw,\n pitch,\n zoom,\n duration\n });\n };\n\n private _createPieElements() {\n const root = this.element;\n const pieSVG = document.createElementNS(SVG_NAMESPACE, \"svg\");\n pieSVG.setAttribute(\"viewBox\", \"0 0 48 48\");\n pieSVG.setAttribute(\"width\", \"100%\");\n pieSVG.setAttribute(\"height\", \"100%\");\n\n const piePath = document.createElementNS(SVG_NAMESPACE, \"circle\");\n\n piePath.setAttribute(\"stroke\", \"currentColor\");\n piePath.setAttribute(\"fill\", \"transparent\");\n piePath.setAttribute(\"cx\", \"24\");\n piePath.setAttribute(\"cy\", \"24\");\n piePath.setAttribute(\"r\", \"12\");\n piePath.setAttribute(\"stroke-width\", \"24\");\n pieSVG.appendChild(piePath);\n\n const rangeCircle = document.createElementNS(SVG_NAMESPACE, \"circle\");\n\n rangeCircle.setAttribute(\"stroke\", \"currentColor\");\n rangeCircle.setAttribute(\"fill\", \"transparent\");\n rangeCircle.setAttribute(\"cx\", \"24\");\n rangeCircle.setAttribute(\"cy\", \"24\");\n rangeCircle.setAttribute(\"r\", \"22.5\");\n rangeCircle.setAttribute(\"stroke-width\", \"3\");\n pieSVG.appendChild(rangeCircle);\n\n root.appendChild(pieSVG);\n\n this._piePathEl = piePath;\n this._rangeCircleEl = rangeCircle;\n }\n\n private _updatePie = ({ target: viewer }: { target: View360 }) => {\n const piePath = this._piePathEl;\n const rangeCircle = this._rangeCircleEl;\n const camera = viewer.camera;\n const fov = camera.getHorizontalFov();\n const yawRange = camera.getYawRange(camera.zoom);\n const halfFov = fov * 0.5;\n\n const pieRadius = 24 * Math.PI;\n const pieDeg = pieRadius * fov / 360;\n const pieOffset = pieRadius * (camera.yaw + halfFov + 90) / 360;\n\n piePath.setAttribute(\"stroke-dasharray\", `${pieDeg} ${pieRadius - pieDeg}`);\n piePath.setAttribute(\"stroke-dashoffset\", `${pieOffset}`);\n\n if (isFinite(yawRange.min) && isFinite(yawRange.max)) {\n const radius = 45 * Math.PI; // 2 * PI * r\n const min = (circulate(yawRange.min, -180, 180) - halfFov) / 360;\n const max = (circulate(yawRange.max, -180, 180) + halfFov) / 360;\n\n const rangeDiff = radius * Math.abs(max - min);\n const offset = -radius * (min - 0.25);\n\n rangeCircle.setAttribute(\"stroke-dasharray\", `${rangeDiff} ${radius - rangeDiff}`);\n rangeCircle.setAttribute(\"stroke-dashoffset\", `${offset}`);\n } else {\n rangeCircle.setAttribute(\"stroke-dasharray\", \"\");\n rangeCircle.setAttribute(\"stroke-dashoffset\", \"\");\n }\n };\n}\n\nexport default PieView;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ControlBar from \"./ControlBar\";\nimport ControlBarItem, { ControlBarItemOptions } from \"./ControlBarItem\";\nimport { CONTROL_BAR_ITEM_POSITION } from \"./const\";\nimport View360 from \"../../View360\";\nimport * as BROWSER from \"../../const/browser\";\n\n/**\n * Show VR enter button.\n * @ko VR 진입 버튼을 표시합니다.\n * @category Plugin\n * @group ControlBar\n * @since 4.0.0\n */\nclass VRButton extends ControlBarItem {\n public readonly element: HTMLElement;\n\n private _viewer: View360 | null;\n\n /**\n * Create a new instance.\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor({\n position = CONTROL_BAR_ITEM_POSITION.MAIN_RIGHT,\n order = 9999\n }: Partial<ControlBarItemOptions> = {}) {\n super({\n position,\n order\n });\n\n this.element = document.createElement(BROWSER.EL_BUTTON);\n this.element.title = \"Enter VR\";\n this._viewer = null;\n }\n\n public init(viewer: View360, controlBar: ControlBar) {\n const element = this.element;\n const className = controlBar.className;\n\n element.classList.add(className.UNAVAILABLE);\n element.classList.add(className.VR_BUTTON);\n element.classList.add(className.CONTROLS_BUTTON);\n\n viewer.vr.isAvailable()\n .then(available => {\n if (available) {\n element.classList.remove(className.UNAVAILABLE);\n }\n });\n\n element.addEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n this._viewer = viewer;\n }\n\n public destroy() {\n const element = this.element;\n\n element.className = \"\";\n element.removeEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n\n this._viewer = null;\n }\n\n private _onClick = () => {\n const viewer = this._viewer;\n if (!viewer) return;\n\n viewer.vr.enter();\n };\n}\n\nexport default VRButton;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ControlBar from \"./ControlBar\";\nimport ControlBarItem, { ControlBarItemOptions } from \"./ControlBarItem\";\nimport { CONTROL_BAR_ITEM_POSITION } from \"./const\";\nimport View360 from \"../../View360\";\nimport * as BROWSER from \"../../const/browser\";\nimport GyroControl from \"../../control/GyroControl\";\nimport { CONTROL_EVENTS } from \"../../const/internal\";\nimport { sensorCanBeEnabledIOS } from \"../../utils\";\n\n/**\n * Show gyroscope control enable / disable button\n * @ko 자이로스코프 컨트롤 활성화 / 비활성화 버튼을 표시합니다.\n * @category Plugin\n * @group ControlBar\n * @since 4.0.0\n */\nclass GyroButton extends ControlBarItem {\n public readonly element: HTMLElement;\n private _viewer: View360 | null;\n private _controlBar: ControlBar | null;\n\n /**\n * Create a new instance.\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor({\n position = CONTROL_BAR_ITEM_POSITION.MAIN_RIGHT,\n order = 9999\n }: Partial<ControlBarItemOptions> = {}) {\n super({\n position,\n order\n });\n\n this.element = document.createElement(BROWSER.EL_DIV);\n this.element.title = \"Toggle gyroscope control\";\n }\n\n public init(viewer: View360, controlBar: ControlBar) {\n const element = this.element;\n const className = controlBar.className;\n\n element.addEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n element.classList.add(className.CONTROLS_BUTTON);\n element.classList.add(className.UNAVAILABLE);\n\n const enableButton = () => {\n element.classList.remove(className.UNAVAILABLE);\n viewer.control.gyro.on(CONTROL_EVENTS.ENABLE, this._updateStyle);\n viewer.control.gyro.on(CONTROL_EVENTS.DISABLE, this._updateStyle);\n };\n\n if (sensorCanBeEnabledIOS()) {\n enableButton();\n } else {\n GyroControl.isAvailable().then(available => {\n if (!available) return;\n enableButton();\n });\n }\n\n this._controlBar = controlBar;\n this._viewer = viewer;\n this._updateStyle();\n }\n\n public destroy(viewer: View360) {\n const element = this.element;\n\n viewer.control.gyro.off(CONTROL_EVENTS.ENABLE, this._updateStyle);\n viewer.control.gyro.off(CONTROL_EVENTS.DISABLE, this._updateStyle);\n element.removeEventListener(BROWSER.EVENTS.CLICK, this._onClick);\n element.className = \"\";\n\n this._controlBar = null;\n this._viewer = null;\n }\n\n private _onClick = () => {\n const viewer = this._viewer;\n const controlBar = this._controlBar;\n\n if (!viewer || !controlBar) return;\n\n const gyroControl = viewer.control.gyro;\n if (gyroControl.enabled) {\n gyroControl.disable();\n } else {\n GyroControl.requestSensorPermission().then(available => {\n if (available) {\n gyroControl.enable();\n } else {\n this.element.classList.add(controlBar.className.UNAVAILABLE);\n }\n });\n }\n };\n\n private _updateStyle = () => {\n const element = this.element;\n const viewer = this._viewer;\n const controlBar = this._controlBar;\n\n if (!viewer || !controlBar) return;\n\n const gyroControl = viewer.control.gyro;\n const className = controlBar.className;\n\n if (gyroControl.enabled) {\n element.classList.add(className.GYRO_ENABLED);\n element.classList.remove(className.GYRO_DISABLED);\n } else {\n element.classList.add(className.GYRO_DISABLED);\n element.classList.remove(className.GYRO_ENABLED);\n }\n };\n}\n\nexport default GyroButton;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ControlBar from \"./ControlBar\";\nimport View360 from \"../../View360\";\nimport * as BROWSER from \"../../const/browser\";\nimport { FULLSCREEN_CHANGE } from \"../../const/browser\";\nimport TextureVideo from \"../../texture/TextureVideo\";\nimport { isFullscreen } from \"../../utils\";\n\n/**\n * Options for ControlBar's {@link ControlBarOptions#autoHide}\n * @ko ControlBar의 {@link ControlBarOptions#autoHide}용 옵션\n * @category Plugin\n * @since 4.0.0\n */\nexport interface AutoHideOptions {\n /**\n * Initial delay before the control bar hides (ms)\n * @ko 컨트롤바가 처음으로 표시되고 사라지기까지 걸리는 시간 (ms)\n * @default 3000\n * @since 4.0.0\n */\n initialDelay: number;\n /**\n * Delay time before hiding the control bar after mouse leave (ms)\n * @ko 마우스가 컨트롤바 영역을 떠난 뒤 컨트롤바가 사라지기까지 걸리는 시간 (ms)\n * @default 0\n * @since 4.0.0\n */\n delay: number;\n /**\n * Delay time before hiding the control bar becomes active, like touch on mobile device or mouse move in fullscreen mode (ms)\n * @ko 모바일이나 풀스크린 환경 등에서 사용자 입력이 없을 때 컨트롤바가 사라지기까지 걸리는 시간 (ms)\n * @default 3000\n * @since 4.0.0\n */\n idleDelay: number;\n}\n\nclass AutoHide {\n private _initialDelay: AutoHideOptions[\"initialDelay\"];\n private _delay: AutoHideOptions[\"delay\"];\n private _idleDelay: AutoHideOptions[\"idleDelay\"];\n\n private _controlBar: ControlBar;\n private _timer: number;\n private _isGrabbing: boolean;\n private _isCursorInside: boolean;\n private _isFullscreen: boolean;\n private _targetEl: HTMLElement | null;\n private _video: TextureVideo | null;\n\n public get enabled() { return !!this._targetEl; }\n public get hidden() { return this._controlBar.containerEl.classList.contains(this._hiddenClass); }\n\n private get _hiddenClass() { return this._controlBar.className.HIDDEN; }\n private get _fixedClass() { return this._controlBar.className.FIXED; }\n\n public constructor(controlBar: ControlBar, {\n initialDelay = 3000,\n delay = 0,\n idleDelay: activationDelay = 3000\n }: Partial<AutoHideOptions>) {\n this._controlBar = controlBar;\n this._initialDelay = initialDelay;\n this._delay = delay;\n this._idleDelay = activationDelay;\n this._timer = -1;\n this._isCursorInside = false;\n this._isGrabbing = false;\n this._isFullscreen = false;\n this._video = null;\n this._targetEl = null;\n }\n\n public enable(viewer: View360) {\n if (this._targetEl) {\n this.disable(viewer);\n }\n\n const initialDelay = this._initialDelay;\n const root = viewer.rootEl;\n\n this._targetEl = viewer.rootEl;\n this._timer = window.setTimeout(() => {\n this.hide();\n }, initialDelay);\n\n root.addEventListener(BROWSER.EVENTS.MOUSE_DOWN, this._onHold);\n root.addEventListener(BROWSER.EVENTS.MOUSE_ENTER, this._onMouseEnter);\n root.addEventListener(BROWSER.EVENTS.MOUSE_MOVE, this._onMouseMove);\n root.addEventListener(BROWSER.EVENTS.MOUSE_LEAVE, this._onMouseLeave);\n this._addFullscreenHandlers();\n\n const video = viewer.mesh?.getTexture();\n if (!video || !video.isVideo()) {\n return;\n }\n\n if (video.isPaused()) {\n this._controlBar.containerEl.classList.add(this._fixedClass);\n }\n\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_PLAY, this._onVideoPlay);\n video.source.addEventListener(BROWSER.EVENTS.VIDEO_PAUSE, this._onVideoPause);\n\n this._video = video;\n }\n\n public disable(viewer: View360) {\n if (!this._targetEl) return;\n\n const controlBar = this._controlBar;\n const root = viewer.rootEl;\n const video = this._video;\n\n root.removeEventListener(BROWSER.EVENTS.MOUSE_DOWN, this._onHold);\n window.removeEventListener(BROWSER.EVENTS.MOUSE_UP, this._onRelease);\n root.removeEventListener(BROWSER.EVENTS.MOUSE_ENTER, this._onMouseEnter);\n root.removeEventListener(BROWSER.EVENTS.MOUSE_MOVE, this._onMouseMove);\n root.removeEventListener(BROWSER.EVENTS.MOUSE_LEAVE, this._onMouseLeave);\n this._removeFullscreenHandlers();\n\n window.clearTimeout(this._timer);\n controlBar.containerEl.classList.remove(this._fixedClass);\n\n if (video) {\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_PLAY, this._onVideoPlay);\n video.source.removeEventListener(BROWSER.EVENTS.VIDEO_PAUSE, this._onVideoPause);\n }\n\n this._isCursorInside = false;\n this._isGrabbing = false;\n this._video = null;\n this._targetEl = null;\n }\n\n public show() {\n this._clearHideTimer();\n this._controlBar.containerEl.classList.remove(this._hiddenClass);\n }\n\n public showTemporaliy() {\n this.show();\n this._hideAfterDelay(this._idleDelay);\n }\n\n public hide() {\n this._clearHideTimer();\n this._controlBar.containerEl.classList.add(this._hiddenClass);\n }\n\n private _clearHideTimer() {\n if (this._timer) {\n window.clearTimeout(this._timer);\n this._timer = -1;\n }\n }\n\n private _hideAfterDelay(delay = this._delay) {\n if (this._isGrabbing || (!this._isFullscreen && this._isCursorInside)) return;\n\n this._clearHideTimer();\n if (delay <= 0) {\n this.hide();\n } else {\n this._timer = window.setTimeout(() => {\n this.hide();\n }, delay);\n }\n }\n\n private _onMouseEnter = () => {\n this._isCursorInside = true;\n this.show();\n };\n\n private _onMouseLeave = () => {\n this._isCursorInside = false;\n this._hideAfterDelay();\n };\n\n private _onMouseMove = () => {\n if (!this._isFullscreen) return;\n\n this.showTemporaliy();\n }\n\n private _onHold = (evt: PointerEvent) => {\n this._isGrabbing = true;\n\n if (evt.pointerType === \"mouse\") {\n this._isCursorInside = true;\n }\n\n window.addEventListener(BROWSER.EVENTS.MOUSE_UP, this._onRelease);\n\n this.show();\n };\n\n private _onRelease = () => {\n this._isGrabbing = false;\n\n window.removeEventListener(BROWSER.EVENTS.MOUSE_UP, this._onRelease);\n\n this._hideAfterDelay();\n };\n\n private _onVideoPlay = () => {\n const root = this._targetEl;\n if (!root) return;\n\n this._controlBar.containerEl.classList.remove(this._fixedClass);\n };\n\n private _onVideoPause = () => {\n const root = this._targetEl;\n if (!root) return;\n\n this._controlBar.containerEl.classList.add(this._fixedClass);\n };\n\n private _addFullscreenHandlers() {\n FULLSCREEN_CHANGE.forEach(evtName => {\n document.addEventListener(evtName, this._onFullscreenChange);\n });\n }\n\n private _removeFullscreenHandlers() {\n FULLSCREEN_CHANGE.forEach(evtName => {\n document.removeEventListener(evtName, this._onFullscreenChange);\n });\n }\n\n private _onFullscreenChange = () => {\n this._isFullscreen = isFullscreen();\n\n if (this._isFullscreen) {\n this._hideAfterDelay();\n }\n };\n}\n\nexport default AutoHide;\n","import TextureVideo from \"../../texture/TextureVideo\";\nimport * as BROWSER from \"../../const/browser\";\nimport { clamp } from \"../../utils\";\nimport { VIDEO_TIME_CHANGE_EVENT } from \"../../const/internal\";\n\nclass VideoControl {\n private _video: TextureVideo | null;\n\n public enable(root: HTMLElement, video: TextureVideo) {\n this._video = video;\n // capture is needed for resolving conflict with keyboard control\n root.addEventListener(BROWSER.EVENTS.KEY_DOWN, this._onKeyDown, true);\n }\n\n public disable(root: HTMLElement) {\n this._video = null;\n root.removeEventListener(BROWSER.EVENTS.KEY_DOWN, this._onKeyDown, true);\n }\n\n private _onKeyDown = (event: KeyboardEvent) => {\n const video = this._video;\n if (!video) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n const videoEl = video.source;\n const keyPressed = event.keyCode != null\n ? BROWSER.DIRECTION_KEY_CODE[event.keyCode]\n : BROWSER.DIRECTION_KEY_NAME[event.key];\n\n switch (keyPressed) {\n case \"LEFT\":\n case \"RIGHT\":\n return this._changeVideoTime(videoEl, keyPressed === \"RIGHT\");\n case \"UP\":\n case \"DOWN\":\n return this._changeVideoVolume(videoEl, keyPressed === \"UP\");\n }\n\n const spacePressed = event.keyCode === BROWSER.SPACE_KEY_CODE || event.key === BROWSER.SPACE_KEY_NAME;\n if (spacePressed) {\n this._toggleVideo(video);\n }\n }\n\n private _changeVideoTime(video: HTMLVideoElement, forward: boolean) {\n const delta = forward ? 5 : -5;\n\n video.currentTime += delta;\n video.dispatchEvent(new CustomEvent(VIDEO_TIME_CHANGE_EVENT, { detail: { time: video.currentTime }}));\n }\n\n private _changeVideoVolume(video: HTMLVideoElement, increase: boolean) {\n const delta = increase ? 0.1 : -0.1;\n\n if (video.muted) {\n video.volume = clamp(delta, 0, 1);\n } else {\n video.volume = clamp(video.volume + delta, 0, 1);\n }\n\n if (video.volume > 0) {\n video.muted = false;\n } else {\n video.muted = true;\n }\n }\n\n private _toggleVideo(video: TextureVideo) {\n if (video.isPaused()) {\n video.source.play();\n } else {\n video.source.pause();\n }\n }\n}\n\nexport default VideoControl;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport ControlBarItem, { ControlBarItemOptions } from \"./ControlBarItem\";\nimport ProgressBar from \"./ProgressBar\";\nimport PlayButton from \"./PlayButton\";\nimport VolumeControl from \"./VolumeControl\";\nimport FullscreenButton from \"./FullscreenButton\";\nimport VideoTime from \"./VideoTime\";\nimport PieView, { PieViewOptions } from \"./PieView\";\nimport VRButton from \"./VRButton\";\nimport GyroButton from \"./GyroButton\";\nimport AutoHide, { AutoHideOptions } from \"./AutoHide\";\nimport VideoControl from \"./VideoControl\";\nimport View360, { View360Events } from \"../../View360\";\nimport View360Plugin from \"../View360Plugin\";\nimport { EVENTS } from \"../../const/external\";\nimport { createElement, findIndex, getObjectOption } from \"../../utils\";\nimport { ValueOf } from \"../../type/utils\";\nimport { StaticClickEvent } from \"../../type/events\";\nimport { CONTROL_BAR_DEFAULT_CLASS, CONTROL_BAR_ITEM_POSITION } from \"./const\";\n\n/**\n * Options for {@link ControlBar}\n * @ko {@link ControlBar}용 옵션들\n * @category Plugin\n * @since 4.0.0\n */\nexport interface ControlBarOptions {\n /**\n * @copy ControlBar#autoHide\n */\n autoHide: boolean | Partial<AutoHideOptions>;\n /**\n * @copy ControlBar#showBackground\n */\n showBackground: boolean;\n /**\n * @copy ControlBar#clickToPlay\n */\n clickToPlay: boolean;\n /**\n * @copy ControlBar#keyboardControls\n */\n keyboardControls: boolean;\n /**\n * @copy ControlBar#progressBar\n */\n progressBar: boolean | Partial<ControlBarItemOptions>;\n /**\n * @copy ControlBar#playButton\n */\n playButton: boolean | Partial<ControlBarItemOptions>;\n /**\n * @copy ControlBar#volumeButton\n */\n volumeButton: boolean | Partial<ControlBarItemOptions>;\n /**\n * @copy ControlBar#fullscreenButton\n */\n fullscreenButton: boolean | Partial<ControlBarItemOptions>;\n /**\n * @copy ControlBar#videoTime\n */\n videoTime: boolean | Partial<ControlBarItemOptions>;\n /**\n * @copy ControlBar#pieView\n */\n pieView: boolean | Partial<PieViewOptions>;\n /**\n * @copy ControlBar#vrButton\n */\n vrButton: boolean | Partial<ControlBarItemOptions>;\n /**\n * @copy ControlBar#gyroButton\n */\n gyroButton: boolean | Partial<ControlBarItemOptions>;\n /**\n * @copy ControlBar#className\n */\n className: Partial<{ -readonly [key in keyof typeof ControlBar.DEFAULT_CLASS]: string }>;\n /**\n * @copy ControlBar#customItems\n */\n customItems: ControlBarItem[];\n}\n\n/**\n * A plugin that displays extra buttons & controls that controls {@link View360}.\n * @ko {@link View360}에 부가적인 버튼과 컨트롤을 추가해주는 플러그인.\n * @category Plugin\n * @since 4.0.0\n */\nclass ControlBar implements View360Plugin {\n /**\n * Default class names that ControlBar uses\n * @ko ControlBar가 사용하는 디폴트 클래스 이름들\n * @since 4.0.0\n */\n public static readonly DEFAULT_CLASS = CONTROL_BAR_DEFAULT_CLASS;\n\n /**\n * Constants for {@link ControlBarItemOptions#position}\n * @ko {@link ControlBarItemOptions#position}에 사용 가능한 값들\n */\n public static readonly POSITION = CONTROL_BAR_ITEM_POSITION;\n\n /**\n * Automatically hide control bar on video plays.\n * `true` to enable with default values, `false` to disable.\n * @ko 비디오 재생시 자동으로 컨트롤바를 숨깁니다.\n * `true`일 경우 기본값을 적용하고, `false`일 경우 비활성화합니다.\n * @since 4.0.0\n */\n public readonly autoHide?: ControlBarOptions[\"autoHide\"];\n /**\n * Show background element.\n * @ko 배경 엘리먼트를 표시합니다.\n * @since 4.0.0\n */\n public readonly showBackground?: ControlBarOptions[\"showBackground\"];\n /**\n * Whether to play / pause video on canvas click\n * @ko 캔버스 클릭시에 비디오를 재생 / 일시정지 토글합니다.\n * @since 4.0.0\n */\n public readonly clickToPlay: ControlBarOptions[\"clickToPlay\"];\n /**\n * Enable keyboard controls for video.\n * Pressing up / down arrow will control video volume, and pressing left / right arrow will control video time.\n * @ko 비디오 키보드 컨트롤을 활성화합니다.\n * 위 / 아래 화살표키를 누를 시 비디오 볼륨을, 왼쪽 / 오른쪽 화살표키를 누를 시 비디오 시간을 조정합니다.\n * @since 4.0.0\n */\n public readonly keyboardControls: ControlBarOptions[\"keyboardControls\"];\n /**\n * Show video progress bar.\n * `true` to enable with default values, `false` to disable.\n * @ko 비디오 프로그레스 바를 표시합니다.\n * `true`일 경우 기본값을 적용하고, `false`일 경우 비활성화합니다.\n * @since 4.0.0\n */\n public readonly progressBar: ControlBarOptions[\"progressBar\"];\n /**\n * Show video play / pause button.\n * `true` to enable with default values, `false` to disable.\n * @ko 비디오 재생 / 일시정지 버튼을 표시합니다.\n * `true`일 경우 기본값을 적용하고, `false`일 경우 비활성화합니다.\n * @since 4.0.0\n */\n public readonly playButton: ControlBarOptions[\"playButton\"];\n /**\n * Show video volume control button.\n * `true` to enable with default values, `false` to disable.\n * @ko 비디오 볼륨 조절 버튼을 표시합니다.\n * `true`일 경우 기본값을 적용하고, `false`일 경우 비활성화합니다.\n * @since 4.0.0\n */\n public readonly volumeButton: ControlBarOptions[\"volumeButton\"];\n /**\n * Show fullscreen button.\n * `true` to enable with default values, `false` to disable.\n * @ko 풀스크린 진입 / 해제 버튼을 표시합니다.\n * `true`일 경우 기본값을 적용하고, `false`일 경우 비활성화합니다.\n * @since 4.0.0\n */\n public readonly fullscreenButton: ControlBarOptions[\"fullscreenButton\"];\n /**\n * Show video current / total time\n * `true` to enable with default values, `false` to disable.\n * @ko 비디오의 현재 시간 / 총 시간을 표시합니다.\n * `true`일 경우 기본값을 적용하고, `false`일 경우 비활성화합니다.\n * @since 4.0.0\n */\n public readonly videoTime: ControlBarOptions[\"videoTime\"];\n /**\n * Show camera pie view.\n * `true` to enable with default values, `false` to disable.\n * @ko 현재 카메라가 가리키는 방향을 표시하는 파이 뷰를 표시합니다.\n * `true`일 경우 기본값을 적용하고, `false`일 경우 비활성화합니다.\n * @since 4.0.0\n */\n public readonly pieView: ControlBarOptions[\"pieView\"];\n /**\n * Show VR button.\n * `true` to enable with default values, `false` to disable.\n * @ko VR 진입버튼을 표시합니다.\n * `true`일 경우 기본값을 적용하고, `false`일 경우 비활성화합니다.\n * @since 4.0.0\n */\n public readonly vrButton: ControlBarOptions[\"vrButton\"];\n /**\n * Show gyroscope control enable / disable button.\n * `true` to enable with default values, `false` to disable.\n * @ko 자이로스코프 컨트롤을 활성화 / 비활성화하는 버튼을 표시합니다.\n * `true`일 경우 기본값을 적용하고, `false`일 경우 비활성화합니다.\n * @since 4.0.0\n */\n public readonly gyroButton: ControlBarOptions[\"gyroButton\"];\n /**\n * Override default class names.\n * @ko 디폴트 클래스 이름들을 오버라이드합니다.\n * @since 4.0.0\n */\n public readonly className: Required<ControlBarOptions[\"className\"]>;\n\n /**\n * Root element of the control bar\n * @ko 컨트롤바의 루트 엘리먼트\n * @since 4.0.0\n */\n public get rootEl() { return this._rootEl; }\n /**\n * Container element of the control bar\n * @ko 컨트롤바의 컨테이너 엘리먼트\n * @since 4.0.0\n */\n public get containerEl() { return this._containerEl; }\n /**\n * Background element of the control bar\n * @ko 컨트롤바의 배경 엘리먼트\n * @since 4.0.0\n */\n public get backgroundEl() { return this._bgEl; }\n /**\n * Control bar's default items created by {@link ControlBarOptions}\n * @ko 주어진 {@link ControlBarOptions}에 의해 생성된 디폴트 아이템들\n * @since 4.0.0\n */\n public get items() { return this._items; }\n /**\n * Custom control bar items\n * @ko 커스텀 컨트롤바 아이템들을 추가합니다.\n * @since 4.0.0\n */\n public get customItems() { return this._customItems; }\n\n private _rootEl: HTMLElement;\n private _containerEl: HTMLElement;\n private _bgEl: HTMLElement;\n private _wrapperEl: Record<ValueOf<typeof ControlBar.POSITION>, HTMLElement>;\n private _items: Record<ValueOf<typeof ControlBar.POSITION>, ControlBarItem[]>;\n private _customItems: ControlBarItem[];\n private _autoHider: AutoHide;\n private _videoControl: VideoControl;\n\n /**\n * Create new instance of ControlBar.\n * @ko ControlBar의 새 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor({\n autoHide,\n showBackground,\n clickToPlay = true,\n keyboardControls = true,\n progressBar = true,\n playButton = true,\n volumeButton = true,\n fullscreenButton = true,\n videoTime = true,\n pieView = true,\n vrButton = true,\n gyroButton = true,\n className = {},\n customItems = []\n }: Partial<ControlBarOptions> = {}) {\n this.autoHide = autoHide;\n this.showBackground = showBackground;\n this.clickToPlay = clickToPlay;\n this.keyboardControls = keyboardControls;\n this.progressBar = progressBar;\n this.playButton = playButton;\n this.volumeButton = volumeButton;\n this.fullscreenButton = fullscreenButton;\n this.videoTime = videoTime;\n this.pieView = pieView;\n this.vrButton = vrButton;\n this.gyroButton = gyroButton;\n this.className = {\n ...ControlBar.DEFAULT_CLASS,\n ...className\n };\n\n const rootClass = className.CONTROLS_ROOT ?? ControlBar.DEFAULT_CLASS.CONTROLS_ROOT;\n\n this._rootEl = createElement(rootClass);\n this._createPositionWrappers();\n this._items = Object.keys(ControlBar.POSITION).reduce((items, key) => {\n items[ControlBar.POSITION[key]] = [];\n return items;\n }, {}) as Record<ValueOf<typeof ControlBar.POSITION>, ControlBarItem[]>;\n this._customItems = customItems;\n this._autoHider = new AutoHide(this, getObjectOption(autoHide));\n this._videoControl = new VideoControl();\n\n customItems.forEach(item => {\n this._items[item.position].push(item);\n });\n }\n\n public init(viewer: View360) {\n const panoRoot = viewer.rootEl;\n const controlsRoot = this._rootEl;\n const defaultItems = this._createDefaultItems();\n\n this._updateBackground(viewer);\n this._updateAutoHide(viewer);\n this._updateKeyboardHandler(viewer);\n\n panoRoot.appendChild(controlsRoot);\n this._addItem(viewer, defaultItems);\n this._addItem(viewer, this._customItems);\n\n viewer.on(EVENTS.PROJECTION_CHANGE, this._onNewSrcLoad);\n viewer.on(EVENTS.STATIC_CLICK, this._onStaticClick);\n }\n\n public destroy(viewer: View360): void {\n // Remove controls root from pano root\n const panoRoot = viewer.rootEl;\n const controlsRoot = this._rootEl;\n const items = this._items;\n\n if (controlsRoot.parentElement === panoRoot) {\n panoRoot.removeChild(controlsRoot);\n }\n\n Object.keys(items).forEach((key: ValueOf<typeof ControlBar.POSITION>) => {\n const category = items[key];\n\n category.forEach(item => {\n item.destroy(viewer, this);\n });\n\n items[key] = [];\n });\n\n this._clearItemElements();\n this._autoHider.disable(viewer);\n this._videoControl.disable(panoRoot);\n\n viewer.off(EVENTS.PROJECTION_CHANGE, this._onNewSrcLoad);\n viewer.off(EVENTS.STATIC_CLICK, this._onStaticClick);\n }\n\n private _addItem(viewer: View360, items: ControlBarItem[]) {\n for (const item of items) {\n const category = this._items[item.position];\n const wrapper = this._wrapperEl[item.position];\n\n const nextSiblingIndex = findIndex(category, sibling => sibling.order > item.order);\n\n if (nextSiblingIndex >= 0) {\n const nextSibling = category[nextSiblingIndex].element;\n category.splice(nextSiblingIndex, 0, item);\n wrapper.insertBefore(item.element, nextSibling);\n } else {\n category.push(item);\n wrapper.appendChild(item.element);\n }\n\n item.init(viewer, this);\n }\n }\n\n private _createPositionWrappers() {\n const className = {\n ...ControlBar.DEFAULT_CLASS,\n ...this.className\n };\n const rootEl = this._rootEl;\n\n // BG & FLOATING CONTROLS\n const backgroundEl = createElement(className.CONTROLS_BG);\n const floatLeftEl = createElement(className.CONTROLS_FLOAT_LEFT);\n const floatRightEl = createElement(className.CONTROLS_FLOAT_RIGHT);\n\n rootEl.appendChild(floatLeftEl);\n rootEl.appendChild(floatRightEl);\n\n // BOTTOM CONTROLS\n const container = createElement(className.CONTROLS_MAIN);\n const topWrapper = createElement(className.CONTROLS_TOP);\n const bottomWrapper = createElement(className.CONTROLS_BOTTOM);\n const midWrapper = createElement(className.CONTROLS_MID);\n const leftControlsWrapper = createElement(className.CONTROLS_LEFT);\n const rightControlsWrapper = createElement(className.CONTROLS_RIGHT);\n\n midWrapper.appendChild(leftControlsWrapper);\n midWrapper.appendChild(rightControlsWrapper);\n container.appendChild(backgroundEl);\n container.appendChild(topWrapper);\n container.appendChild(midWrapper);\n container.appendChild(bottomWrapper);\n rootEl.appendChild(container);\n\n this._bgEl = backgroundEl;\n this._containerEl = container;\n this._wrapperEl = {\n [ControlBar.POSITION.MAIN_TOP]: topWrapper,\n [ControlBar.POSITION.MAIN_LEFT]: leftControlsWrapper,\n [ControlBar.POSITION.MAIN_RIGHT]: rightControlsWrapper,\n [ControlBar.POSITION.MAIN_BOTTOM]: bottomWrapper,\n [ControlBar.POSITION.TOP_LEFT]: floatLeftEl,\n [ControlBar.POSITION.TOP_RIGHT]: floatRightEl\n };\n }\n\n private _clearItemElements() {\n const wrappers = Object.keys(ControlBar.POSITION)\n .map(key => ControlBar.POSITION[key])\n .map(pos => this._wrapperEl[pos]);\n\n // Remove all elements inside wrappers\n wrappers.forEach(wrapper => {\n while (wrapper.firstChild) {\n wrapper.removeChild(wrapper.firstChild);\n }\n });\n }\n\n private _onStaticClick = ({ target: viewer, isTouch }: StaticClickEvent) => {\n const autoHider = this._autoHider;\n\n if (isTouch) {\n if (!autoHider.enabled) return;\n\n if (autoHider.hidden) {\n autoHider.showTemporaliy();\n } else {\n autoHider.hide();\n }\n } else {\n if (!this.clickToPlay) return;\n\n const video = viewer.mesh?.getTexture();\n if (!video || !video.isVideo()) return;\n\n if (video.isPaused()) {\n video.source.play();\n } else {\n video.source.pause();\n }\n }\n };\n\n private _onNewSrcLoad = ({ target: viewer }: View360Events[\"projectionChange\"]) => {\n const items = this._items;\n\n this._updateBackground(viewer);\n this._updateAutoHide(viewer);\n this._updateKeyboardHandler(viewer);\n\n Object.keys(items).forEach((key: ValueOf<typeof ControlBar.POSITION>) => {\n const category = items[key];\n\n category.forEach(item => {\n item.destroy(viewer, this);\n item.init(viewer, this);\n });\n });\n };\n\n private _updateAutoHide(viewer: View360) {\n const autoHide = this.autoHide;\n const autoHider = this._autoHider;\n\n if (autoHide != null) {\n if (autoHide) {\n autoHider.enable(viewer);\n } else {\n autoHider.disable(viewer);\n }\n } else {\n // Automatically choose whether to show background by content type\n const texture = viewer.mesh?.getTexture();\n\n if (texture && texture.isVideo()) {\n // Enable auto hide when content type is video\n autoHider.enable(viewer);\n } else {\n autoHider.disable(viewer);\n }\n }\n }\n\n private _updateBackground(viewer: View360) {\n const background = this._bgEl;\n const showBackground = this.showBackground;\n const hiddenClass = this.className.HIDDEN ?? ControlBar.DEFAULT_CLASS.HIDDEN;\n\n if (showBackground != null) {\n if (showBackground) {\n background.classList.remove(hiddenClass);\n } else {\n background.classList.add(hiddenClass);\n }\n } else {\n // Automatically choose whether to show background by content type\n const texture = viewer.mesh?.getTexture();\n\n if (texture && texture.isVideo()) {\n // Show bg when content type is video\n background.classList.remove(hiddenClass);\n } else {\n background.classList.add(hiddenClass);\n }\n }\n }\n\n private _updateKeyboardHandler(viewer: View360) {\n const panoRoot = viewer.rootEl;\n const videoControl = this._videoControl;\n const texture = viewer.mesh?.getTexture();\n\n if (this.keyboardControls && texture && texture.isVideo()) {\n videoControl.enable(panoRoot, texture);\n } else {\n videoControl.disable(panoRoot);\n }\n }\n\n private _createDefaultItems(): ControlBarItem[] {\n const items: ControlBarItem[] = [];\n\n if (this.progressBar) {\n items.push(new ProgressBar(getObjectOption(this.progressBar)));\n }\n\n if (this.playButton) {\n items.push(new PlayButton(getObjectOption(this.playButton)));\n }\n\n if (this.volumeButton) {\n items.push(new VolumeControl(getObjectOption(this.volumeButton)));\n }\n\n if (this.gyroButton) {\n items.push(new GyroButton(getObjectOption(this.gyroButton)));\n }\n\n if (this.vrButton) {\n items.push(new VRButton(getObjectOption(this.vrButton)));\n }\n\n if (this.fullscreenButton) {\n items.push(new FullscreenButton(getObjectOption(this.fullscreenButton)));\n }\n\n if (this.videoTime) {\n items.push(new VideoTime(getObjectOption(this.videoTime)));\n }\n\n if (this.pieView) {\n items.push(new PieView(getObjectOption(this.pieView)));\n }\n\n return items;\n }\n}\n\nexport default ControlBar;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Camera from \"../core/Camera\";\nimport PanoControl from \"../control/PanoControl\";\nimport TriangleMesh from \"../core/TriangleMesh\";\nimport Texture from \"../texture/Texture\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport { VideoConfig } from \"../type/external\";\n\n/**\n * Common option for {@link Projection}s\n * @ko {@link Projection}을 위한 공통 옵션들\n * @category Projection\n * @since 4.0.0\n */\nexport interface ProjectionOptions {\n /**\n * @copy Projection#src\n */\n src: string | HTMLElement | Array<string | HTMLElement>;\n /**\n * @copy Projection#video\n */\n video?: boolean | Partial<VideoConfig>;\n}\n\n/**\n * Base class for projections.\n * @ko 프로젝션 베이스 클래스.\n * @category Projection\n * @since 4.0.0\n */\nabstract class Projection {\n /**\n * Source URL to panorama image/video.\n * @ko 파노라마 이미지/비디오의 URL\n * @since 4.0.0\n */\n public readonly src: ProjectionOptions[\"src\"];\n /**\n * Properties for the video element.\n * Setting `false` will treat panorama source as an image, `true` will use default properties.\n * @ko 비디오 엘리먼트에 설정할 프로퍼티를 담는 객체.\n * @since 4.0.0\n * @example\n * Default properties\n * ```ts\n * autoplay: true\n * muted: true\n * loop: false\n * volume: 1\n * ```\n */\n public readonly video: ProjectionOptions[\"video\"];\n\n /**\n * Create new instance\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor({\n src,\n video = false\n }: ProjectionOptions) {\n this.src = src;\n this.video = video;\n }\n\n /**\n * Generate triangle mesh from current projection.\n * @ko 현재 프로젝션으로부터 TriangleMesh의 인스턴스를 생성합니다.\n * @param ctx - Instance of the WebGLContext helper {@ko WebGL context 헬퍼의 인스턴스}\n * @param texture - New texture to apply {@ko 새로 적용할 텍스쳐}\n * @internal\n * @since 4.0.0\n */\n public abstract createMesh(ctx: WebGLContext, texture: Texture): TriangleMesh;\n\n /**\n * Update camera to match projection's settings.\n * @ko 현재 프로젝션의 세팅으로 카메라를 업데이트합니다.\n * @param camera - Instance of the camera to update {@ko 업데이트할 카메라의 인스턴스}\n * @since 4.0.0\n */\n public updateCamera(camera: Camera) {\n // Use default mode & no view restriction\n camera.resetRange();\n }\n\n /**\n * Update control to match projection's settings.\n * @ko 현재 프로젝션의 세팅으로 컨트롤을 업데이트합니다.\n * @param control - Instance of the control to update {@ko 업데이트할 컨트롤의 인스턴스}\n * @since 4.0.0\n */\n public updateControl(control: PanoControl) {\n control.ignoreZoomScale = false;\n }\n}\n\nexport default Projection;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nabstract class Uniform {\n public needsUpdate: boolean;\n\n public constructor() {\n this.needsUpdate = true;\n }\n\n public abstract update(gl: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation, isWebGL2: boolean): void;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public destroy(gl: WebGLRenderingContext | WebGL2RenderingContext) {\n // DO_NOTHING\n }\n}\n\nexport default Uniform;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport TextureCube from \"../texture/TextureCube\";\nimport { reorderCube } from \"../utils\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport Uniform from \"./Uniform\";\n\nclass UniformTextureCube extends Uniform {\n public readonly texture: TextureCube;\n private _webglTexture: WebGLTexture;\n private _cubemapOrder: string;\n\n public constructor(ctx: WebGLContext, texture: TextureCube, cubemapOrder: string) {\n super();\n\n this.texture = texture;\n this._webglTexture = ctx.createWebGLCubeTexture(texture, texture.width);\n this._cubemapOrder = cubemapOrder;\n }\n\n public destroy(gl: WebGLRenderingContext | WebGL2RenderingContext): void {\n this.texture.destroy();\n gl.deleteTexture(this._webglTexture);\n }\n\n public update(gl: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation, isWebGL2: boolean) {\n const texture = this.texture;\n\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);\n gl.uniform1i(location, 0);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._webglTexture);\n\n const sources = reorderCube(texture.sources, this._cubemapOrder);\n sources.forEach((src, idx) => {\n if (isWebGL2) {\n gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + idx, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, src);\n } else {\n gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + idx, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, src);\n }\n });\n\n if (!texture.isVideo()) {\n this.needsUpdate = false;\n }\n }\n}\n\nexport default UniformTextureCube;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Texture2D from \"../texture/Texture2D\";\nimport { range, reorderCube } from \"../utils\";\n\n/** @hidden */\nclass CubeTexturePainter {\n public readonly texture: Texture2D;\n private _renderingOrder: number[];\n private _canvas: HTMLCanvasElement;\n private _ctx: CanvasRenderingContext2D;\n private _row: number;\n private _column: number;\n private _size: number;\n\n public get size() { return this._size; }\n\n public constructor(texture: Texture2D, cubemapOrder: string) {\n this.texture = texture;\n this._renderingOrder = reorderCube(range(6), cubemapOrder);\n\n const canvas = document.createElement(\"canvas\");\n\n this._calcRenderingSize();\n\n canvas.width = this._size;\n canvas.height = this._size;\n\n this._canvas = canvas;\n this._ctx = canvas.getContext(\"2d\")!;\n }\n\n public destroy() {\n const canvas = this._canvas;\n\n // release memories\n canvas.width = 1;\n canvas.height = 1;\n this._canvas = null as any;\n }\n\n public draw(gl: WebGLRenderingContext | WebGL2RenderingContext, isWebGL2: boolean) {\n const size = this._size;\n const texture = this.texture;\n let surfaceIdx = 0;\n\n for (let row = 0; row < this._row; row++) {\n for (let column = 0; column < this._column; column++) {\n const x = size * column;\n const y = size * row;\n const renderingFace = this._renderingOrder[surfaceIdx];\n\n this._ctx.drawImage(texture.source as CanvasImageSource, x, y, size, size, 0, 0, size, size);\n\n if (isWebGL2) {\n gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderingFace, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this._canvas);\n } else {\n gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderingFace, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._canvas);\n }\n\n surfaceIdx++;\n }\n }\n }\n\n private _calcRenderingSize() {\n const {\n width,\n height\n } = this.texture;\n const aspect = width / height;\n\n if (aspect === 1 / 6) {\n this._size = width;\n this._row = 6;\n this._column = 1;\n } else if (aspect === 6) {\n this._size = height;\n this._row = 1;\n this._column = 6;\n } else if (aspect === 2 / 3) {\n this._size = width * 0.5;\n this._row = 3;\n this._column = 2;\n } else {\n this._size = width / 3;\n this._row = 2;\n this._column = 3;\n }\n }\n}\n\nexport default CubeTexturePainter;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport CubeTexturePainter from \"../core/CubeTexturePainter\";\nimport Texture2D from \"../texture/Texture2D\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport Uniform from \"./Uniform\";\n\nclass UniformCanvasCube extends Uniform {\n private _webglTexture: WebGLTexture;\n private _painter: CubeTexturePainter;\n\n public get texture() { return this._painter.texture; }\n\n public constructor(ctx: WebGLContext, texture: Texture2D, cubemapOrder: string) {\n super();\n\n this._painter = new CubeTexturePainter(texture as Texture2D, cubemapOrder);\n this._webglTexture = ctx.createWebGLCubeTexture(texture, this._painter.size);\n }\n\n public destroy(gl: WebGLRenderingContext | WebGL2RenderingContext) {\n gl.deleteTexture(this._webglTexture);\n this._painter.destroy();\n }\n\n public update(gl: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation, isWebGL2: boolean) {\n const texture = this.texture;\n\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\n gl.uniform1i(location, 0);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._webglTexture);\n\n this._painter.draw(gl, isWebGL2);\n\n if (!texture.isVideo()) {\n this.needsUpdate = false;\n }\n }\n}\n\nexport default UniformCanvasCube;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Object3D from \"./Object3D\";\nimport ShaderProgram from \"./ShaderProgram\";\nimport VertexArrayObject from \"./VertexArrayObject\";\nimport Uniform from \"../uniform/Uniform\";\nimport WebGLContext from \"./WebGLContext\";\nimport UniformCanvasCube from \"../uniform/UniformCanvasCube\";\nimport UniformTexture2D from \"../uniform/UniformTexture2D\";\nimport UniformTextureCube from \"../uniform/UniformTextureCube\";\nimport UniformTextureRenderTarget from \"../uniform/UniformTextureRenderTarget\";\n\n// CommonProjectionUniforms 使用 Uniform 基类,以支持自定义纹理 uniform(如实时矫正的 RealtimeCorrectionTextureUniform)\ntype CommonProjectionUniforms = {\n uTexture: UniformTexture2D | UniformTextureCube | UniformCanvasCube | UniformTextureRenderTarget | Uniform;\n}\n\n/**\n * @hidden\n */\nclass TriangleMesh<T extends CommonProjectionUniforms = CommonProjectionUniforms> extends Object3D {\n /**\n * @internal\n * Geometry data for projection\n */\n public readonly vao: VertexArrayObject;\n /**\n * @internal\n * Material(shader) data for projection\n */\n public readonly program: ShaderProgram<T>;\n\n public constructor(vao: VertexArrayObject, program: ShaderProgram<T>) {\n super();\n\n this.vao = vao;\n this.program = program;\n }\n\n public destroy(ctx: WebGLContext) {\n ctx.releaseVAO(this.vao);\n ctx.releaseShaderResources(this.program);\n }\n\n public getTexture() {\n const uniform: any = this.program.uniforms.uTexture as any;\n\n return uniform.sourceTexture || uniform.texture;\n }\n}\n\nexport default TriangleMesh;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Uniform from \"../uniform/Uniform\";\nimport WebGLContext from \"./WebGLContext\";\nimport { UniformLocations } from \"../type/internal\";\n\nclass ShaderProgram<T extends Record<string, Uniform> = Record<string, Uniform>> {\n public readonly program: WebGLProgram;\n public readonly uniforms: T;\n public readonly uniformLocations: UniformLocations<T>;\n\n public constructor(ctx: WebGLContext, vertexShader: string, fragmentShader: string, uniforms: T) {\n this.program = ctx.createProgram(vertexShader, fragmentShader);\n this.uniforms = uniforms;\n this.uniformLocations = ctx.getUniformLocations(this.program, uniforms);\n }\n}\n\nexport default ShaderProgram;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport { TypedArray } from \"../type/utils\";\n\n/**\n * @hidden\n */\nclass VertexData<T extends TypedArray> {\n public readonly data: T;\n public itemSize: number;\n public count: number;\n\n /** */\n public constructor(data: T, itemSize: number) {\n this.data = data;\n this.itemSize = itemSize;\n this.count = data.length / itemSize;\n }\n}\n\nexport default VertexData;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport VertexData from \"../core/VertexData\";\n\n/**\n * @hidden\n */\nabstract class Geometry {\n public readonly vertices: VertexData<Float32Array>;\n public readonly indicies: VertexData<Uint16Array>;\n public readonly uvs: VertexData<Float32Array>;\n\n /** */\n public constructor(vertices: number[], indicies: number[], uvs: number[]) {\n this.vertices = new VertexData(new Float32Array(vertices), 3);\n this.indicies = new VertexData(new Uint16Array(indicies), 1);\n this.uvs = new VertexData(new Float32Array(uvs), 2);\n }\n}\n\nexport default Geometry;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Geometry from \"./Geometry\";\nimport { ROTATE } from \"../const/internal\";\nimport { reorderCube } from \"../utils\";\n\n/**\n * @hidden\n */\nclass CubeGeometry extends Geometry {\n public constructor({\n order,\n rotateUV\n }: {\n order: string;\n rotateUV?: ROTATE[]\n }) {\n const vertices = [\n // back\n 1, -1, 1,\n -1, -1, 1,\n -1, 1, 1,\n 1, 1, 1,\n\n // front\n -1, -1, -1,\n 1, -1, -1,\n 1, 1, -1,\n -1, 1, -1,\n\n // up\n -1, 1, -1,\n 1, 1, -1,\n 1, 1, 1,\n -1, 1, 1,\n\n // down\n -1, -1, 1,\n 1, -1, 1,\n 1, -1, -1,\n -1, -1, -1,\n\n // right\n 1, -1, -1,\n 1, -1, 1,\n 1, 1, 1,\n 1, 1, -1,\n\n // left\n -1, -1, 1,\n -1, -1, -1,\n -1, 1, -1,\n -1, 1, 1\n ];\n\n const indicies = [\n 0, 1, 2,\n 0, 2, 3,\n 4, 5, 6,\n 4, 6, 7,\n 8, 9, 10,\n 8, 10, 11,\n 12, 13, 14,\n 12, 14, 15,\n 16, 17, 18,\n 16, 18, 19,\n 20, 21, 22,\n 20, 22, 23\n ];\n\n const oneThird = 1 / 3;\n const coords: number[][] = [];\n\n for (let r = 1; r >= 0; r--) {\n for (let c = 0; c < 3; c++) {\n const coord = [\n c * oneThird, r * 0.5,\n (c + 1) * oneThird, r * 0.5,\n (c + 1) * oneThird, (r + 1) * 0.5,\n c * oneThird, (r + 1) * 0.5\n ];\n\n coords.push(coord);\n }\n }\n\n if (rotateUV) {\n rotateUV.forEach((degree, idx) => {\n if (degree === ROTATE.ZERO) return;\n\n const coord = coords[idx];\n let newOrder: number[];\n\n if (degree === ROTATE.CW_90) {\n newOrder = [1, 2, 3, 0];\n } else if (degree === ROTATE.CCW_90) {\n newOrder = [3, 0, 1, 2];\n } else {\n newOrder = [2, 3, 0, 1];\n }\n\n const newCoords = Array<number>(coord.length);\n for (let uvIdx = 0; uvIdx < coord.length / 2; uvIdx++) {\n newCoords[uvIdx * 2 + 0] = coord[newOrder[uvIdx] * 2 + 0];\n newCoords[uvIdx * 2 + 1] = coord[newOrder[uvIdx] * 2 + 1];\n }\n\n coords[idx] = newCoords;\n });\n }\n\n const uvs = reorderCube(coords, order, \"BFUDRL\")\n .reduce((acc, val) => acc.concat(val), []);\n\n super(vertices, indicies, uvs);\n }\n}\n\nexport default CubeGeometry;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Texture2D from \"../texture/Texture2D\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport Uniform from \"./Uniform\";\n\nclass UniformTexture2D extends Uniform {\n public readonly texture: Texture2D;\n private _webglTexture: WebGLTexture;\n\n public constructor(ctx: WebGLContext, texture: Texture2D) {\n super();\n\n this.texture = texture;\n this._webglTexture = ctx.createWebGLTexture(texture);\n }\n\n public destroy(gl: WebGLRenderingContext | WebGL2RenderingContext): void {\n this.texture.destroy();\n gl.deleteTexture(this._webglTexture);\n }\n\n public update(gl: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation, isWebGL2: boolean) {\n const texture = this.texture;\n const isVideo = texture.isVideo();\n\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);\n gl.uniform1i(location, 0);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this._webglTexture);\n\n if (!isVideo && isWebGL2) {\n gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, texture.source);\n } else {\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source);\n }\n\n if (!isVideo) {\n this.needsUpdate = false;\n }\n }\n}\n\nexport default UniformTexture2D;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Geometry from \"./Geometry\";\n\n/**\n * @hidden\n */\nclass CylinderGeometry extends Geometry {\n public constructor(maxTheta: number) {\n const vertices: number[] = [];\n const indicies: number[] = [];\n const uvs: number[] = [];\n\n const height = 1;\n const radialSegments = 60;\n const halfHeight = height * 0.5;\n const heightSegments = [-halfHeight, halfHeight];\n const invRadialSegments = 1 / radialSegments;\n const angleConst = maxTheta * invRadialSegments;\n\n for (let yIdx = 0; yIdx < 2; yIdx++) {\n const y = heightSegments[yIdx];\n\n for (let lngIdx = 0; lngIdx <= radialSegments; lngIdx++) {\n const angle = lngIdx * angleConst + Math.PI - maxTheta * 0.5;\n const x = Math.cos(angle);\n const z = Math.sin(angle);\n const u = lngIdx * invRadialSegments;\n const v = yIdx;\n\n uvs.push(u, v);\n vertices.push(x, y, z);\n\n if (yIdx === 0 && lngIdx < radialSegments) {\n const a = lngIdx;\n const b = a + radialSegments + 1;\n\n indicies.push(a, b, a + 1, b, b + 1, a + 1);\n }\n }\n }\n\n super(vertices, indicies, uvs);\n }\n}\n\nexport default CylinderGeometry;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Geometry from \"./Geometry\";\n\n/**\n * @hidden\n */\nclass SphereGeometry extends Geometry {\n /** */\n public constructor() {\n // const radius = 1;\n const widthSegments = 60;\n const heightSegments = 60;\n const ANGLE_CORRECTION_FOR_CENTER_ALIGN = -0.5 * Math.PI;\n\n const uvs: number[] = [];\n const vertices: number[] = [];\n const indicies: number[] = [];\n let latIdx: number;\n let lngIdx: number;\n\n for (latIdx = 0; latIdx <= widthSegments; latIdx++) {\n const theta = (latIdx / widthSegments - 0.5) * Math.PI;\n const sinTheta = Math.sin(theta);\n const cosTheta = Math.cos(theta);\n\n for (lngIdx = 0; lngIdx <= heightSegments; lngIdx++) {\n const phi = (lngIdx / heightSegments - 0.5) * 2 * Math.PI + ANGLE_CORRECTION_FOR_CENTER_ALIGN;\n const sinPhi = Math.sin(phi);\n const cosPhi = Math.cos(phi);\n const x = cosPhi * cosTheta;\n const y = sinTheta;\n const z = sinPhi * cosTheta;\n const u = lngIdx / heightSegments;\n const v = latIdx / widthSegments;\n\n uvs.push(u, v);\n vertices.push(x, y, z);\n\n if (lngIdx !== heightSegments && latIdx !== widthSegments) {\n const a = latIdx * (heightSegments + 1) + lngIdx;\n const b = a + heightSegments + 1;\n\n indicies.push(a, a + 1, b, b, a + 1, b + 1);\n }\n }\n }\n\n super(vertices, indicies, uvs);\n }\n}\n\nexport default SphereGeometry;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Uniform from \"./Uniform\";\n\nclass UniformFloat extends Uniform {\n public val: number;\n\n public constructor(val: number) {\n super();\n\n this.val = val;\n }\n\n public update(gl: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation) {\n gl.uniform1f(location, this.val);\n\n this.needsUpdate = false;\n }\n}\n\nexport default UniformFloat;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Geometry from \"./Geometry\";\n\n/**\n * @hidden\n */\nclass PlaneGeometry extends Geometry {\n /** */\n public constructor(width: number = 2, height: number = 2, z: number = -1) {\n const halfWidth = width * 0.5;\n const halfHeight = height * 0.5;\n const vertices = [\n -halfWidth, -halfHeight, z,\n halfWidth, -halfHeight, z,\n -halfWidth, halfHeight, z,\n halfWidth, halfHeight, z\n ];\n const indicies = [\n 0, 1, 2,\n 2, 1, 3\n ];\n const uvs = [\n 0, 0,\n 1, 0,\n 0, 1,\n 1, 1\n ];\n\n super(vertices, indicies, uvs);\n }\n}\n\nexport default PlaneGeometry;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Uniform from \"./Uniform\";\n\nclass UniformVector4Array extends Uniform {\n public val: number[][];\n\n public constructor(val: number[][]) {\n super();\n\n this.val = val;\n }\n\n public update(gl: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation) {\n gl.uniform4fv(location, this.val.reduce((arr, vector) => [...arr, ...vector], []));\n\n this.needsUpdate = false;\n }\n}\n\nexport default UniformVector4Array;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Projection, { ProjectionOptions } from \"./Projection\";\nimport UniformTexture2D from \"../uniform/UniformTexture2D\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport Texture2D from \"../texture/Texture2D\";\nimport SphereGeometry from \"../geometry/SphereGeometry\";\nimport ShaderProgram from \"../core/ShaderProgram\";\nimport TriangleMesh from \"../core/TriangleMesh\";\nimport UniformVector4Array from \"../uniform/UniformVector4Array\";\nimport UniformFloat from \"../uniform/UniformFloat\";\nimport vs from \"../shader/stereoequi.vert\";\nimport fs from \"../shader/common.frag\";\n\n/**\n * Options for {@link StereoEquiProjection}\n * @ko {@link StereoEquiProjection}의 옵션들\n * @since 4.0.0\n * @category Projection\n */\nexport interface StereoEquiProjectionOptions extends ProjectionOptions {\n src: string | HTMLElement;\n /**\n * Stereoscopic mode of the image\n * @ko 이미지의 스테레오스코픽 모드\n * @since 4.0.0\n * @default \"top_bottom\"\n */\n mode: typeof StereoEquiProjection.MODE[keyof typeof StereoEquiProjection.MODE]\n}\n\n/**\n * Projection based on stereo equirectangular images.\n * @ko Stereo equirectangular 이미지 기반의 프로젝션\n * @since 4.0.0\n * @category Projection\n */\nclass StereoEquiProjection extends Projection {\n /**\n * Available stereoscopic modes\n * @ko 사용가능한 스테레오스코픽 모드들\n * @since 4.0.0\n */\n public static MODE = {\n /**\n * @ko 이미지가 왼쪽/오른쪽으로 구성되어있을 경우\n * @since 4.0.0\n */\n LEFT_RIGHT: \"left_right\",\n /**\n * @ko 이미지가 위/아래로 구성되어있을 경우\n * @since 4.0.0\n */\n TOP_BOTTOM: \"top_bottom\",\n } as const;\n\n private _mode: StereoEquiProjectionOptions[\"mode\"];\n\n /**\n * Create new instance\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor(options: StereoEquiProjectionOptions) {\n super(options);\n\n this._mode = options.mode;\n }\n\n public createMesh(ctx: WebGLContext, texture: Texture2D) {\n let leftEye: number[];\n let rightEye: number[];\n\n switch (this._mode) {\n case StereoEquiProjection.MODE.LEFT_RIGHT:\n leftEye = [0.5, 1, 0, 0];\n rightEye = [0.5, 1, 0.5, 0];\n break;\n default:\n // Default, uses \"top_bottom\"\n leftEye = [1, 0.5, 0, 0];\n rightEye = [1, 0.5, 0, 0.5];\n }\n\n\n const uniforms = {\n uTexture: new UniformTexture2D(ctx, texture),\n uEye: new UniformFloat(0),\n uTexScaleOffset: new UniformVector4Array([leftEye, rightEye])\n };\n\n const geometry = new SphereGeometry();\n const program = new ShaderProgram(ctx, vs, fs, uniforms);\n\n const vao = ctx.createVAO(geometry, program);\n const mesh = new TriangleMesh(vao, program);\n\n return mesh;\n }\n}\n\nexport default StereoEquiProjection;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Texture from \"./Texture\";\n\n/**\n * 用于 Render-to-Texture 的纹理类型\n * 不持有 HTMLElement source,而是直接持有 WebGLTexture\n * @hidden\n */\nclass TextureRenderTarget extends Texture {\n public readonly glTexture: WebGLTexture;\n\n public constructor(glTexture: WebGLTexture, width: number, height: number) {\n super({\n width,\n height,\n flipY: false\n });\n this.glTexture = glTexture;\n }\n\n public isVideo(): this is never {\n return false;\n }\n\n public destroy(): void {\n // WebGLTexture 由 WebGLContext.deleteFramebuffer 管理,这里不处理\n }\n}\n\nexport default TextureRenderTarget;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport WebGLContext from \"../core/WebGLContext\";\nimport TextureRenderTarget from \"../texture/TextureRenderTarget\";\nimport vsSource from \"../shader/fullscreen.vert\";\nimport fsSource from \"../shader/correction.frag\";\n\nexport interface CorrectionParams {\n /** 输入图像模式:erp(等距柱状) 或 fisheye(鱼眼) */\n mode: \"erp\" | \"fisheye\";\n /** Yaw 旋转角度(度) */\n yaw: number;\n /** Pitch 旋转角度(度) */\n pitch: number;\n /** Roll 旋转角度(度) */\n roll: number;\n /** 输入图像水平 FOV(度) */\n hfov: number;\n /** 输入图像垂直 FOV(度) */\n vfov: number;\n /** 鱼眼模式 FOV(度) */\n fisheyeFov: number;\n}\n\n/**\n * 离屏矫正渲染 Pass\n * 将超宽全景输入转换为标准 2:1 equirectangular 纹理\n * @hidden\n */\nclass CorrectionPass {\n private _ctx: WebGLContext;\n private _program: WebGLProgram;\n private _fbo: { framebuffer: WebGLFramebuffer; texture: WebGLTexture };\n private _outputTexture: TextureRenderTarget;\n private _quadBuffer: WebGLBuffer;\n private _uniformLocations: Record<string, WebGLUniformLocation | null>;\n private _outputWidth: number;\n private _outputHeight: number;\n\n public get outputTexture() { return this._outputTexture; }\n\n public constructor(ctx: WebGLContext, outputWidth: number, outputHeight: number) {\n this._ctx = ctx;\n this._outputWidth = outputWidth;\n this._outputHeight = outputHeight;\n\n const gl = ctx.gl;\n\n // 创建 FBO\n this._fbo = ctx.createFramebuffer(outputWidth, outputHeight);\n this._outputTexture = new TextureRenderTarget(this._fbo.texture, outputWidth, outputHeight);\n\n // 创建着色器程序\n this._program = ctx.createProgram(vsSource, fsSource);\n\n // 缓存 uniform 位置\n this._uniformLocations = {\n uTexture: gl.getUniformLocation(this._program, \"uTexture\"),\n uMode: gl.getUniformLocation(this._program, \"uMode\"),\n uRotYPR: gl.getUniformLocation(this._program, \"uRotYPR\"),\n uHFov: gl.getUniformLocation(this._program, \"uHFov\"),\n uVFov: gl.getUniformLocation(this._program, \"uVFov\"),\n uFisheyeFov: gl.getUniformLocation(this._program, \"uFisheyeFov\"),\n uImgSize: gl.getUniformLocation(this._program, \"uImgSize\")\n };\n\n // 创建全屏四边形顶点缓冲区\n const quadBuffer = gl.createBuffer();\n if (!quadBuffer) {\n throw new Error(\"无法创建顶点缓冲区\");\n }\n this._quadBuffer = quadBuffer;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n }\n\n public render(inputTexture: WebGLTexture, inputWidth: number, inputHeight: number, params: CorrectionParams) {\n const gl = this._ctx.gl;\n const locs = this._uniformLocations;\n\n const prevFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING) as WebGLFramebuffer | null;\n const prevViewport = gl.getParameter(gl.VIEWPORT) as Int32Array;\n const prevProgram = gl.getParameter(gl.CURRENT_PROGRAM) as WebGLProgram | null;\n const prevClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE) as Float32Array;\n const prevActiveTexture = gl.getParameter(gl.ACTIVE_TEXTURE) as number;\n const prevTextureBinding2D = gl.getParameter(gl.TEXTURE_BINDING_2D) as WebGLTexture | null;\n const prevArrayBuffer = gl.getParameter(gl.ARRAY_BUFFER_BINDING) as WebGLBuffer | null;\n\n const glAsAny = gl as any;\n const vaoExt = !glAsAny.bindVertexArray ? gl.getExtension(\"OES_vertex_array_object\") : null;\n const prevVAOBinding = glAsAny.bindVertexArray\n ? (gl as WebGL2RenderingContext).getParameter((gl as WebGL2RenderingContext).VERTEX_ARRAY_BINDING)\n : (vaoExt ? gl.getParameter((vaoExt as any).VERTEX_ARRAY_BINDING_OES) : null);\n\n if (glAsAny.bindVertexArray) {\n (gl as WebGL2RenderingContext).bindVertexArray(null);\n } else if (vaoExt) {\n (vaoExt as any).bindVertexArrayOES(null);\n }\n\n // 绑定 FBO\n this._ctx.bindFramebuffer(this._fbo.framebuffer);\n gl.viewport(0, 0, this._outputWidth, this._outputHeight);\n gl.clearColor(0, 0, 0, 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n // 使用矫正程序\n gl.useProgram(this._program);\n\n // 设置 uniforms\n // 注意:yaw 和 pitch 需要取反,与 app.js 主 canvas 渲染保持一致\n // 这样图像移动方向与用户调整参数的直觉一致\n const toRad = (deg: number) => deg * Math.PI / 180;\n gl.uniform1i(locs.uMode, params.mode === \"fisheye\" ? 1 : 0);\n gl.uniform3f(locs.uRotYPR!, toRad(-params.yaw), toRad(-params.pitch), toRad(params.roll));\n gl.uniform1f(locs.uHFov!, toRad(params.hfov));\n gl.uniform1f(locs.uVFov!, toRad(params.vfov));\n gl.uniform1f(locs.uFisheyeFov!, toRad(params.fisheyeFov));\n gl.uniform2f(locs.uImgSize!, inputWidth, inputHeight);\n\n // 绑定输入纹理\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, inputTexture);\n gl.uniform1i(locs.uTexture, 0);\n\n // 绘制全屏四边形\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadBuffer);\n const posLoc = gl.getAttribLocation(this._program, \"aPosition\");\n gl.enableVertexAttribArray(posLoc);\n gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n gl.disableVertexAttribArray(posLoc);\n\n gl.useProgram(prevProgram);\n gl.activeTexture(prevActiveTexture);\n gl.bindTexture(gl.TEXTURE_2D, prevTextureBinding2D);\n gl.bindBuffer(gl.ARRAY_BUFFER, prevArrayBuffer);\n\n if (glAsAny.bindVertexArray) {\n (gl as WebGL2RenderingContext).bindVertexArray(prevVAOBinding);\n } else if (vaoExt) {\n (vaoExt as any).bindVertexArrayOES(prevVAOBinding);\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, prevFramebuffer);\n gl.viewport(prevViewport[0], prevViewport[1], prevViewport[2], prevViewport[3]);\n gl.clearColor(prevClearColor[0], prevClearColor[1], prevClearColor[2], prevClearColor[3]);\n }\n\n public destroy() {\n const gl = this._ctx.gl;\n gl.deleteBuffer(this._quadBuffer);\n gl.deleteProgram(this._program);\n this._ctx.deleteFramebuffer(this._fbo);\n }\n}\n\nexport default CorrectionPass;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport TextureRenderTarget from \"../texture/TextureRenderTarget\";\nimport Uniform from \"./Uniform\";\n\n/**\n * Uniform for TextureRenderTarget\n * 与 UniformTexture2D 不同,不执行 texImage2D,只绑定已有纹理\n * @hidden\n */\nclass UniformTextureRenderTarget extends Uniform {\n public readonly texture: TextureRenderTarget;\n private _onDestroy: (() => void) | null;\n private readonly _keepNeedsUpdateForDestroy: boolean;\n\n public constructor(texture: TextureRenderTarget, onDestroy?: () => void) {\n super();\n this.texture = texture;\n this._onDestroy = onDestroy ?? null;\n this._keepNeedsUpdateForDestroy = !!this._onDestroy;\n\n // 首帧必须执行一次 update 以完成纹理绑定与 uniform 赋值。\n // 当需要释放离屏资源时,needsUpdate 必须保持为 true,\n // 以确保 releaseShaderResources 阶段会调用 destroy()。\n this.needsUpdate = true;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public destroy(gl: WebGLRenderingContext | WebGL2RenderingContext): void {\n // 纹理由 CorrectionPass/FBO 管理,这里通过回调释放\n if (this._onDestroy) {\n this._onDestroy();\n this._onDestroy = null;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public update(gl: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation, isWebGL2: boolean): void {\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\n gl.uniform1i(location, 0);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.texture.glTexture);\n // 注意:当需要释放离屏资源时,needsUpdate 必须保持为 true,\n // 以确保 releaseShaderResources 阶段会调用 destroy()\n\n if (!this._keepNeedsUpdateForDestroy) {\n // 无需释放离屏资源时,仅需绑定一次即可\n this.needsUpdate = false;\n }\n }\n}\n\nexport default UniformTextureRenderTarget;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Uniform from \"./Uniform\";\n\n/**\n * 整数类型的 Uniform\n * @hidden\n */\nclass UniformInt extends Uniform {\n public val: number;\n\n public constructor(val: number) {\n super();\n this.val = val;\n }\n\n public update(gl: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation) {\n gl.uniform1i(location, this.val);\n this.needsUpdate = false;\n }\n}\n\nexport default UniformInt;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Uniform from \"./Uniform\";\n\n/**\n * vec2 类型的 Uniform\n * @hidden\n */\nclass UniformVec2 extends Uniform {\n public val: [number, number];\n\n public constructor(x: number, y: number) {\n super();\n this.val = [x, y];\n }\n\n public update(gl: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation) {\n gl.uniform2f(location, this.val[0], this.val[1]);\n this.needsUpdate = false;\n }\n}\n\nexport default UniformVec2;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Uniform from \"./Uniform\";\n\n/**\n * vec3 类型的 Uniform\n * @hidden\n */\nclass UniformVec3 extends Uniform {\n public val: [number, number, number];\n\n public constructor(x: number, y: number, z: number) {\n super();\n this.val = [x, y, z];\n }\n\n public update(gl: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation) {\n gl.uniform3f(location, this.val[0], this.val[1], this.val[2]);\n this.needsUpdate = false;\n }\n}\n\nexport default UniformVec3;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Projection, { ProjectionOptions } from \"./Projection\";\nimport type { CorrectionParams as CorrectionPassParams } from \"./CorrectionPass\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport Texture from \"../texture/Texture\";\nimport Texture2D from \"../texture/Texture2D\";\nimport TriangleMesh from \"../core/TriangleMesh\";\nimport PlaneGeometry from \"../geometry/PlaneGeometry\";\nimport SphereGeometry from \"../geometry/SphereGeometry\";\nimport ShaderProgram from \"../core/ShaderProgram\";\nimport Uniform from \"../uniform/Uniform\";\nimport UniformInt from \"../uniform/UniformInt\";\nimport UniformFloat from \"../uniform/UniformFloat\";\nimport UniformVec2 from \"../uniform/UniformVec2\";\nimport UniformVec3 from \"../uniform/UniformVec3\";\nimport vs from \"../shader/wideangle_realtime.vert\";\nimport fs from \"../shader/wideangle_realtime.frag\";\n\n/**\n * 矫正参数配置\n * @ko 보정 매개변수 설정\n * @since 4.0.0\n * @category Projection\n */\nexport type CorrectionParams = Partial<CorrectionPassParams>;\n\n/**\n * Options for {@link WideAngleRealtimeProjection}\n * @ko {@link WideAngleRealtimeProjection}의 옵션들\n * @since 4.0.0\n * @category Projection\n */\nexport interface WideAngleRealtimeOptions extends ProjectionOptions {\n /**\n * 矫正参数配置\n * @ko 보정 매개변수\n */\n correction?: CorrectionParams;\n /**\n * 是否使用平面投影模式展示结果(而非 360 球体)\n * @default false\n */\n flatProjection?: boolean;\n /**\n * 输入纹理宽度(用于缩放视频帧以降低 GPU 压力)\n * 如果指定,视频帧会先缩放到此尺寸再上传 GPU\n * @default undefined (使用原始视频尺寸)\n */\n inputWidth?: number;\n /**\n * 输入纹理高度(用于缩放视频帧以降低 GPU 压力)\n * 如果指定,视频帧会先缩放到此尺寸再上传 GPU\n * @default undefined (使用原始视频尺寸)\n */\n inputHeight?: number;\n\n // --- Deprecated: Legacy flat parameters (use 'correction' object instead) ---\n /** @deprecated Use correction.mode instead */\n mode?: \"erp\" | \"fisheye\";\n /** @deprecated Use correction.yaw instead */\n yaw?: number;\n /** @deprecated Use correction.pitch instead */\n pitch?: number;\n /** @deprecated Use correction.roll instead */\n roll?: number;\n /** @deprecated Use correction.hfov instead */\n hfov?: number;\n /** @deprecated Use correction.vfov instead */\n vfov?: number;\n /** @deprecated Use correction.fisheyeFov instead */\n fisheyeFov?: number;\n}\n\n// 角度转弧度\nconst toRad = (deg: number) => (deg * Math.PI) / 180;\n\n/**\n * 实时宽角矫正纹理 Uniform\n * 处理视频帧更新和尺寸同步\n * @hidden\n */\nclass RealtimeCorrectionTextureUniform extends Uniform {\n public readonly texture: Texture2D;\n private _webglTexture: WebGLTexture;\n private _imgSizeUniform: UniformVec2 | null = null;\n private _initialized: boolean = false;\n // 输入纹理缩放相关\n private _targetWidth: number;\n private _targetHeight: number;\n private _scaleCanvas: OffscreenCanvas | HTMLCanvasElement | null = null;\n private _scaleCtx:\n | OffscreenCanvasRenderingContext2D\n | CanvasRenderingContext2D\n | null = null;\n // 纹理尺寸是否已分配(用于 texSubImage2D 优化)\n private _textureAllocated: boolean = false;\n private _allocatedWidth: number = 0;\n private _allocatedHeight: number = 0;\n // 标记纹理是否为 immutable(WebGL2 非视频使用 texStorage2D 创建)\n private _isImmutableTexture: boolean = false;\n\n public constructor(\n tex: Texture2D,\n glTex: WebGLTexture,\n targetWidth?: number,\n targetHeight?: number,\n isImmutableTexture?: boolean\n ) {\n super();\n this.texture = tex;\n this._webglTexture = glTex;\n this._targetWidth = targetWidth || 0;\n this._targetHeight = targetHeight || 0;\n this._isImmutableTexture = isImmutableTexture || false;\n\n // 如果指定了目标尺寸,创建缩放用的 Canvas\n if (this._targetWidth > 0 && this._targetHeight > 0) {\n this._initScaleCanvas();\n }\n }\n\n public setImgSizeUniform(uniform: UniformVec2) {\n this._imgSizeUniform = uniform;\n }\n\n public destroy(glCtx: WebGLRenderingContext | WebGL2RenderingContext): void {\n this.texture.destroy();\n this._scaleCanvas = null;\n this._scaleCtx = null;\n glCtx.deleteTexture(this._webglTexture);\n }\n\n public update(\n glCtx: WebGLRenderingContext | WebGL2RenderingContext,\n location: WebGLUniformLocation,\n _isWebGL2: boolean\n ) {\n const tex = this.texture;\n const isVideo = tex.isVideo();\n void _isWebGL2;\n\n // 上传纹理数据\n glCtx.pixelStorei(glCtx.UNPACK_FLIP_Y_WEBGL, 0); // 不翻转,矫正 shader 自己处理坐标\n glCtx.uniform1i(location, 0);\n glCtx.activeTexture(glCtx.TEXTURE0);\n glCtx.bindTexture(glCtx.TEXTURE_2D, this._webglTexture);\n\n // 视频纹理需要每帧更新,并同步更新尺寸 uniform\n if (isVideo) {\n const videoEl = tex.source as HTMLVideoElement;\n // 视频尺寸可能在播放后才可用\n if (\n videoEl.readyState < 2 ||\n videoEl.videoWidth <= 0 ||\n videoEl.videoHeight <= 0\n ) {\n this._uploadPlaceholder(glCtx);\n return;\n }\n\n // 确定实际使用的纹理尺寸(缩放后的或原始的)\n const actualWidth =\n this._targetWidth > 0 ? this._targetWidth : videoEl.videoWidth;\n const actualHeight =\n this._targetHeight > 0 ? this._targetHeight : videoEl.videoHeight;\n\n if (this._imgSizeUniform) {\n const curSize = this._imgSizeUniform.val;\n if (curSize[0] !== actualWidth || curSize[1] !== actualHeight) {\n this._imgSizeUniform.val = [actualWidth, actualHeight];\n this._imgSizeUniform.needsUpdate = true;\n }\n }\n }\n\n // 确定纹理源:如果有缩放 Canvas,先绘制缩放后再上传\n let textureSource: TexImageSource = tex.source;\n if (isVideo && this._scaleCanvas && this._scaleCtx) {\n const videoEl = tex.source as HTMLVideoElement;\n // 将视频帧绘制到缩放 Canvas(自动缩放)\n this._scaleCtx.drawImage(\n videoEl,\n 0,\n 0,\n this._targetWidth,\n this._targetHeight\n );\n textureSource = this._scaleCanvas as TexImageSource;\n }\n\n // 上传纹理数据\n // 确定当前纹理源的实际尺寸\n // 对于视频:使用 videoWidth/videoHeight(真实像素尺寸),而不是 width/height(显示尺寸)\n // 对于 Canvas/OffscreenCanvas:使用 width/height 属性\n let sourceWidth: number;\n let sourceHeight: number;\n\n if (this._targetWidth > 0 && this._targetHeight > 0) {\n // 启用了输入缩放,尺寸固定\n sourceWidth = this._targetWidth;\n sourceHeight = this._targetHeight;\n } else if (isVideo) {\n // 未缩放的视频:使用 videoWidth/videoHeight(实际像素尺寸)\n const videoEl = tex.source as HTMLVideoElement;\n sourceWidth = videoEl.videoWidth;\n sourceHeight = videoEl.videoHeight;\n } else {\n // 静态图片或其他源\n sourceWidth = (textureSource as any).width || 0;\n sourceHeight = (textureSource as any).height || 0;\n }\n\n // 检查是否可以使用 texSubImage2D(尺寸不变且已分配)\n // WebGL1 和 WebGL2 都支持 texSubImage2D 用于 DOM 源\n const canUseSubImage =\n this._textureAllocated &&\n this._allocatedWidth === sourceWidth &&\n this._allocatedHeight === sourceHeight &&\n sourceWidth > 0 &&\n sourceHeight > 0;\n\n if (canUseSubImage) {\n // 使用 texSubImage2D 仅更新数据,不重新分配内存(更快)\n glCtx.texSubImage2D(\n glCtx.TEXTURE_2D,\n 0,\n 0,\n 0,\n glCtx.RGBA,\n glCtx.UNSIGNED_BYTE,\n textureSource\n );\n } else {\n // 首次或尺寸变化时上传纹理数据\n // 对于 immutable texture(WebGL2 非视频,已用 texStorage2D 分配),必须用 texSubImage2D\n // 对于 mutable texture(WebGL1 或视频),使用 texImage2D 分配内存\n if (this._isImmutableTexture) {\n // Immutable texture: texStorage2D 已分配存储,只能用 texSubImage2D 更新数据\n glCtx.texSubImage2D(\n glCtx.TEXTURE_2D,\n 0,\n 0,\n 0,\n glCtx.RGBA,\n glCtx.UNSIGNED_BYTE,\n textureSource\n );\n } else {\n // Mutable texture: 使用 texImage2D 分配内存并上传数据\n glCtx.texImage2D(\n glCtx.TEXTURE_2D,\n 0,\n glCtx.RGBA,\n glCtx.RGBA,\n glCtx.UNSIGNED_BYTE,\n textureSource\n );\n }\n // 记录已分配的纹理尺寸\n this._textureAllocated = true;\n this._allocatedWidth = sourceWidth;\n this._allocatedHeight = sourceHeight;\n }\n\n this._initialized = true;\n if (!isVideo) {\n this.needsUpdate = false;\n }\n }\n\n /**\n * 获取当前生效的目标宽度(缩放被禁用时返回 0)\n * @hidden\n */\n public getEffectiveTargetWidth(): number {\n return this._targetWidth;\n }\n\n /**\n * 获取当前生效的目标高度(缩放被禁用时返回 0)\n * @hidden\n */\n public getEffectiveTargetHeight(): number {\n return this._targetHeight;\n }\n\n private _initScaleCanvas() {\n try {\n // 优先使用 OffscreenCanvas(性能更好,且 Worker 环境可用)\n // eslint-disable-next-line compat/compat\n this._scaleCanvas = new OffscreenCanvas(\n this._targetWidth,\n this._targetHeight\n );\n this._scaleCtx = this._scaleCanvas.getContext(\n \"2d\"\n ) as OffscreenCanvasRenderingContext2D;\n // 检查 getContext 是否成功\n if (!this._scaleCtx) {\n throw new Error(\"OffscreenCanvas getContext('2d') returned null\");\n }\n } catch (_e) {\n // 降级到普通 Canvas(仅在主线程且有 document 时可用)\n if (typeof document !== \"undefined\") {\n this._scaleCanvas = document.createElement(\"canvas\");\n this._scaleCanvas.width = this._targetWidth;\n this._scaleCanvas.height = this._targetHeight;\n this._scaleCtx = this._scaleCanvas.getContext(\"2d\");\n // 检查 getContext 是否成功\n if (!this._scaleCtx) {\n console.warn(\n \"[WideAngleRealtimeProjection] Canvas getContext('2d') returned null. Input scaling disabled.\"\n );\n this._scaleCanvas = null;\n this._targetWidth = 0;\n this._targetHeight = 0;\n }\n } else {\n // Worker/SSR 环境且 OffscreenCanvas 不可用,禁用缩放功能\n console.warn(\n \"[WideAngleRealtimeProjection] OffscreenCanvas not available and document is undefined (Worker/SSR). Input scaling disabled.\"\n );\n this._scaleCanvas = null;\n this._scaleCtx = null;\n // 重置目标尺寸,禁用缩放逻辑\n this._targetWidth = 0;\n this._targetHeight = 0;\n }\n }\n }\n\n private _uploadPlaceholder(\n glCtx: WebGLRenderingContext | WebGL2RenderingContext\n ) {\n if (this._initialized) {\n return;\n }\n\n // 视频未就绪时先用 1x1 占位纹理,避免不完整纹理导致渲染异常\n const pixel = new Uint8Array([0, 0, 0, 255]);\n glCtx.texImage2D(\n glCtx.TEXTURE_2D,\n 0,\n glCtx.RGBA,\n 1,\n 1,\n 0,\n glCtx.RGBA,\n glCtx.UNSIGNED_BYTE,\n pixel\n );\n\n if (this._imgSizeUniform) {\n const curSize = this._imgSizeUniform.val;\n if (curSize[0] <= 0 || curSize[1] <= 0) {\n this._imgSizeUniform.val = [1, 1];\n this._imgSizeUniform.needsUpdate = true;\n }\n }\n\n this._initialized = true;\n }\n}\n\n/**\n * 实时矫正 Projection 的 Uniforms 类型\n * @hidden\n */\ninterface RealtimeCorrectionUniforms {\n [key: string]: Uniform;\n uTexture: RealtimeCorrectionTextureUniform;\n uMode: UniformInt;\n uRotYPR: UniformVec3;\n uHFov: UniformFloat;\n uVFov: UniformFloat;\n uFisheyeFov: UniformFloat;\n uImgSize: UniformVec2;\n}\n\n/**\n * 实时宽角矫正 Projection\n * 直接在球体渲染时完成矫正,无需离屏渲染 Pass\n * 相比 WideAngleCorrectionProjection:\n * - 减少一次渲染 Pass,性能更好\n * - 无需配置输出分辨率\n * - 自动适配 canvas 分辨率,避免质量损失\n * @ko 실시간 와이드 앵글 보정 프로젝션. 오프스크린 렌더 패스 없이 구체 렌더링 시 직접 보정 완료.\n * @since 4.0.0\n * @category Projection\n */\nclass WideAngleRealtimeProjection extends Projection {\n private _mode: \"erp\" | \"fisheye\";\n private _flatProjection: boolean;\n private _yaw: number;\n private _pitch: number;\n private _roll: number;\n private _hfov: number;\n private _vfov: number;\n private _fisheyeFov: number;\n private _inputWidth: number;\n private _inputHeight: number;\n\n // uniforms 引用,用于运行时更新参数\n private _uniforms: Partial<RealtimeCorrectionUniforms> = {};\n\n /**\n * Create new instance\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor(options: WideAngleRealtimeOptions) {\n super(options);\n\n // 优先使用新的 correction 对象,若不存在则回退到旧版扁平参数(向后兼容)\n const correction = options.correction || {};\n this._mode = correction.mode ?? options.mode ?? \"erp\";\n this._flatProjection = options.flatProjection ?? false;\n this._yaw = correction.yaw ?? options.yaw ?? 0;\n this._pitch = correction.pitch ?? options.pitch ?? 0;\n this._roll = correction.roll ?? options.roll ?? 0;\n this._hfov = correction.hfov ?? options.hfov ?? 180;\n this._vfov = correction.vfov ?? options.vfov ?? 90;\n this._fisheyeFov = correction.fisheyeFov ?? options.fisheyeFov ?? 180;\n this._inputWidth = options.inputWidth ?? 0;\n this._inputHeight = options.inputHeight ?? 0;\n }\n\n // 属性 getter/setter,用于运行时动态更新参数\n public get mode() {\n return this._mode;\n }\n public set mode(val: \"erp\" | \"fisheye\") {\n this._mode = val;\n if (this._uniforms.uMode) {\n this._uniforms.uMode.val = val === \"fisheye\" ? 1 : 0;\n this._uniforms.uMode.needsUpdate = true;\n }\n }\n\n public get yaw() {\n return this._yaw;\n }\n public set yaw(val: number) {\n this._yaw = val;\n this._updateRotation();\n }\n\n public get pitch() {\n return this._pitch;\n }\n public set pitch(val: number) {\n this._pitch = val;\n this._updateRotation();\n }\n\n public get roll() {\n return this._roll;\n }\n public set roll(val: number) {\n this._roll = val;\n this._updateRotation();\n }\n\n public get hfov() {\n return this._hfov;\n }\n public set hfov(val: number) {\n this._hfov = val;\n if (this._uniforms.uHFov) {\n this._uniforms.uHFov.val = toRad(val);\n this._uniforms.uHFov.needsUpdate = true;\n }\n }\n\n public get vfov() {\n return this._vfov;\n }\n public set vfov(val: number) {\n this._vfov = val;\n if (this._uniforms.uVFov) {\n this._uniforms.uVFov.val = toRad(val);\n this._uniforms.uVFov.needsUpdate = true;\n }\n }\n\n public get fisheyeFov() {\n return this._fisheyeFov;\n }\n public set fisheyeFov(val: number) {\n this._fisheyeFov = val;\n if (this._uniforms.uFisheyeFov) {\n this._uniforms.uFisheyeFov.val = toRad(val);\n this._uniforms.uFisheyeFov.needsUpdate = true;\n }\n }\n\n public createMesh(ctx: WebGLContext, texture: Texture): TriangleMesh {\n if (texture.isCube()) {\n throw new Error(\n \"WideAngleRealtimeProjection 仅支持单张 2D 图像,不支持 Cubemap 纹理\"\n );\n }\n\n const tex2d = texture as Texture2D;\n\n // 纹理尺寸检查\n const maxSize = ctx.maxTextureSize;\n if (texture.width > maxSize || texture.height > maxSize) {\n throw new Error(\n \"输入纹理尺寸 (\" +\n texture.width +\n \"x\" +\n texture.height +\n \") 超过 GPU 最大纹理尺寸限制 (\" +\n maxSize +\n \"x\" +\n maxSize +\n \")。\" +\n \"请使用更小的图片或在支持更大纹理的设备上运行。\"\n );\n }\n\n // 判断是否启用输入缩放(必须同时设置 inputWidth 和 inputHeight)\n const useInputScaling = this._inputWidth > 0 && this._inputHeight > 0;\n\n if (ctx.debug) {\n // 确定实际使用的纹理尺寸\n const actualWidth = useInputScaling ? this._inputWidth : texture.width;\n const actualHeight = useInputScaling ? this._inputHeight : texture.height;\n console.info(\n \"WideAngleRealtimeProjection 实时矫正模式\",\n \"输入纹理尺寸:\",\n actualWidth,\n \"x\",\n actualHeight,\n useInputScaling\n ? \"(已缩放,原始: \" + texture.width + \" x \" + texture.height + \")\"\n : \"\",\n \"GPU 最大纹理尺寸:\",\n ctx.maxTextureSize\n );\n }\n\n // 创建 WebGL 纹理\n const webglTexture = ctx.createWebGLTexture(tex2d);\n\n // 判断是否为 immutable texture(WebGL2 且非视频,因为 createWebGLTexture 会用 texStorage2D)\n const isImmutableTexture = ctx.isWebGL2 && !tex2d.isVideo();\n\n // 创建纹理 uniform(传入目标尺寸用于缩放,以及 immutable 标记)\n const uTexture = new RealtimeCorrectionTextureUniform(\n tex2d,\n webglTexture,\n useInputScaling ? this._inputWidth : undefined,\n useInputScaling ? this._inputHeight : undefined,\n isImmutableTexture\n );\n\n // 创建所有 uniforms\n const uMode = new UniformInt(this._mode === \"fisheye\" ? 1 : 0);\n const uRotYPR = new UniformVec3(\n toRad(-this._yaw),\n toRad(-this._pitch),\n toRad(this._roll)\n );\n const uHFov = new UniformFloat(toRad(this._hfov));\n const uVFov = new UniformFloat(toRad(this._vfov));\n const uFisheyeFov = new UniformFloat(toRad(this._fisheyeFov));\n // 使用实际生效的缩放尺寸或原始尺寸\n // 注意:如果 _initScaleCanvas 中缩放被禁用,uTexture 的有效尺寸会被重置为 0\n const effectiveTargetWidth = uTexture.getEffectiveTargetWidth();\n const effectiveTargetHeight = uTexture.getEffectiveTargetHeight();\n const useScaling = effectiveTargetWidth > 0 && effectiveTargetHeight > 0;\n const imgWidth = useScaling ? effectiveTargetWidth : texture.width;\n const imgHeight = useScaling ? effectiveTargetHeight : texture.height;\n const uImgSize = new UniformVec2(imgWidth, imgHeight);\n\n if (ctx.debug) {\n console.info(\"[WideAngleRealtimeProjection] Uniforms:\", {\n mode: this._mode,\n yaw: this._yaw,\n yawRad: toRad(-this._yaw),\n pitch: this._pitch,\n pitchRad: toRad(-this._pitch),\n roll: this._roll,\n rollRad: toRad(this._roll),\n hfov: this._hfov,\n hfovRad: toRad(this._hfov),\n vfov: this._vfov,\n vfovRad: toRad(this._vfov),\n fisheyeFov: this._fisheyeFov,\n fisheyeFovRad: toRad(this._fisheyeFov),\n imgSize: [imgWidth, imgHeight],\n inputScale:\n this._inputWidth > 0\n ? `${this._inputWidth}x${this._inputHeight}`\n : \"none\",\n });\n }\n\n // 关联尺寸 uniform 到纹理 uniform,用于视频尺寸同步\n uTexture.setImgSizeUniform(uImgSize);\n\n // 保存 uniforms 引用\n this._uniforms = {\n uTexture,\n uMode,\n uRotYPR,\n uHFov,\n uVFov,\n uFisheyeFov,\n uImgSize,\n };\n\n const uniforms: RealtimeCorrectionUniforms = {\n uTexture,\n uMode,\n uRotYPR,\n uHFov,\n uVFov,\n uFisheyeFov,\n uImgSize,\n };\n\n // 根据配置选择几何体\n const geometry = this._flatProjection\n ? new PlaneGeometry(2, 1, -1) // 平面模式:2:1 比例平面\n : new SphereGeometry(); // 默认模式:球体\n\n const program = new ShaderProgram(ctx, vs, fs, uniforms);\n const vao = ctx.createVAO(geometry, program);\n const mesh = new TriangleMesh(vao, program);\n\n return mesh;\n }\n\n private _updateRotation() {\n if (this._uniforms.uRotYPR) {\n // 注意:yaw 和 pitch 取反,与用户调整参数的直觉一致\n this._uniforms.uRotYPR.val = [\n toRad(-this._yaw),\n toRad(-this._pitch),\n toRad(this._roll),\n ];\n this._uniforms.uRotYPR.needsUpdate = true;\n }\n }\n}\n\nexport default WideAngleRealtimeProjection;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Projection, { ProjectionOptions } from \"./Projection\";\nimport UniformTextureCube from \"../uniform/UniformTextureCube\";\nimport UniformCanvasCube from \"../uniform/UniformCanvasCube\";\nimport TriangleMesh from \"../core/TriangleMesh\";\nimport ShaderProgram from \"../core/ShaderProgram\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport Texture2D from \"../texture/Texture2D\";\nimport TextureCube from \"../texture/TextureCube\";\nimport CubeGeometry from \"../geometry/CubeGeometry\";\nimport vs from \"../shader/cube.vert\";\nimport fs from \"../shader/cube.frag\";\n\n/**\n * Options for {@link CubemapProjection}\n * @ko {@link CubemapProjection}의 옵션들\n * @since 4.0.0\n * @category Projection\n */\nexport interface CubemapProjectionOptions extends ProjectionOptions {\n /**\n * Order of the cubemap images.\n * @ko 큐브맵 이미지의 순서.\n * @since 4.0.0\n * @default \"RLUDFB\" (Right - Left - Up - Down - Front - Back)\n */\n cubemapOrder?: string;\n /**\n * Whether to flip cubemap image horizontally.\n * @ko 큐브맵 이미지를 좌우대칭할지 여부.\n * @since 4.0.0\n * @default false\n */\n cubemapFlipX?: boolean;\n}\n\n/**\n * Projection based on cubemap images, accepts both multiple or single images.\n * @ko 큐브맵 이미지 기반의 프로젝션, 단일 혹은 여러 장의 이미지를 모두 사용 가능합니다.\n * @since 4.0.0\n * @category Projection\n */\nclass CubemapProjection extends Projection {\n private _cubemapOrder: NonNullable<CubemapProjectionOptions[\"cubemapOrder\"]>;\n private _cubemapFlipX: NonNullable<CubemapProjectionOptions[\"cubemapFlipX\"]>;\n\n /**\n * Create new instance.\n * @ko 새 인스턴스를 생성합니다.\n * @param options Options {@ko Options}\n */\n public constructor(options: CubemapProjectionOptions) {\n super(options);\n\n const {\n cubemapOrder = \"RLUDFB\",\n cubemapFlipX = false\n } = options;\n\n this._cubemapOrder = cubemapOrder;\n this._cubemapFlipX = cubemapFlipX;\n }\n\n public createMesh(ctx: WebGLContext, texture: Texture2D) {\n const cubemapOrder = this._cubemapOrder;\n const cubemapFlipX = this._cubemapFlipX;\n const uniforms = {\n uTexture: texture.isCube()\n ? new UniformTextureCube(ctx, texture as TextureCube, cubemapOrder)\n : new UniformCanvasCube(ctx, texture as Texture2D, cubemapOrder)\n };\n\n const geometry = new CubeGeometry({\n order: cubemapOrder\n });\n const program = new ShaderProgram(ctx, vs, fs, uniforms);\n const vao = ctx.createVAO(geometry, program);\n const mesh = new TriangleMesh(vao, program);\n\n if (cubemapFlipX) {\n mesh.scale[0] = -1;\n }\n mesh.updateMatrix();\n\n return mesh;\n }\n}\n\nexport default CubemapProjection;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Projection, { ProjectionOptions } from \"./Projection\";\nimport TriangleMesh from \"../core/TriangleMesh\";\nimport ShaderProgram from \"../core/ShaderProgram\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport Texture2D from \"../texture/Texture2D\";\nimport UniformTexture2D from \"../uniform/UniformTexture2D\";\nimport CubeGeometry from \"../geometry/CubeGeometry\";\nimport vs from \"../shader/common.vert\";\nimport fs from \"../shader/common.frag\";\n\n/**\n * Options for {@link CubestripProjection}\n * @ko {@link CubestripProjection}의 옵션들\n * @since 4.0.0\n * @category Projection\n */\nexport interface CubestripProjectionOptions extends ProjectionOptions {\n /**\n * @copy CubemapProjectionOptions#cubemapOrder\n */\n cubemapOrder?: string;\n /**\n * @copy CubemapProjectionOptions#cubemapFlipX\n */\n cubemapFlipX?: boolean;\n}\n\n/**\n * Projection based on cubemap strip.\n * Slightly more efficient than {@link CubemapProjection} as it doesn't copy cubemap image to canvas while rendering.\n * Accepts only single image.\n * @ko 큐브맵 스트립 기반의 프로젝션.\n * {@link CubemapProjection}와 달리 렌더링하는 과정에 캔버스에 이미지를 복사하는 과정이 없기 때문에 살짝 더 효율적입니다.\n * 단일 이미지만 사용 가능합니다.\n * @since 4.0.0\n * @category Projection\n */\nclass CubestripProjection extends Projection {\n private _cubemapOrder: NonNullable<CubestripProjectionOptions[\"cubemapOrder\"]>;\n private _cubemapFlipX: NonNullable<CubestripProjectionOptions[\"cubemapFlipX\"]>;\n\n /**\n * Create new instance.\n * @ko 새 인스턴스를 생성합니다.\n * @param options Options {@ko Options}\n */\n public constructor(options: CubestripProjectionOptions) {\n super(options);\n\n const {\n cubemapOrder = \"RLUDFB\",\n cubemapFlipX = false\n } = options;\n\n this._cubemapOrder = cubemapOrder;\n this._cubemapFlipX = cubemapFlipX;\n }\n\n public createMesh(ctx: WebGLContext, texture: Texture2D) {\n const cubemapOrder = this._cubemapOrder;\n const cubemapFlipX = this._cubemapFlipX;\n const uniforms = {\n uTexture: new UniformTexture2D(ctx, texture)\n };\n const geometry = new CubeGeometry({\n order: cubemapOrder\n });\n const program = new ShaderProgram(ctx, vs, fs, uniforms);\n const vao = ctx.createVAO(geometry, program);\n const mesh = new TriangleMesh(vao, program);\n\n if (cubemapFlipX) {\n mesh.scale[0] = -1;\n }\n mesh.updateMatrix();\n\n return mesh;\n }\n}\n\nexport default CubestripProjection;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n*/\nimport { quat } from \"gl-matrix\";\nimport Projection, { ProjectionOptions } from \"./Projection\";\nimport UniformTexture2D from \"../uniform/UniformTexture2D\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport Texture2D from \"../texture/Texture2D\";\nimport CylinderGeometry from \"../geometry/CylinderGeometry\";\nimport Camera from \"../core/Camera\";\nimport ShaderProgram from \"../core/ShaderProgram\";\nimport { DEG_TO_RAD, RAD_TO_DEG } from \"../const/internal\";\nimport vs from \"../shader/common.vert\";\nimport fs from \"../shader/common.frag\";\nimport TriangleMesh from \"../core/TriangleMesh\";\n\n/**\n * Options for {@link CylindricalProjection}\n * @ko {@link CylindricalProjection}의 옵션들\n * @since 4.0.0\n * @category Projection\n */\nexport interface CylindricalProjectionOptions extends ProjectionOptions {\n src: string | HTMLElement;\n /**\n * Whether the panorama image covers full 360 degrees.\n * @ko 파노라마 이미지가 360도를 전부 커버하는지 여부\n * @since 4.0.0\n * @default false\n */\n partial?: boolean;\n}\n\n/**\n * Projection based on cylindrical projection.\n * This can show panorama images taken from smartphones.\n * @ko 원통 투영법 기반의 프로젝션.\n * 일반적인 스마트폰 파노라마 사진을 표시하는데 사용될 수 있습니다.\n * @since 4.0.0\n * @category Projection\n */\nclass CylindricalProjection extends Projection {\n private _partial: boolean;\n private _aspect: number;\n private _halfHeight: number;\n private _mesh: TriangleMesh | null;\n\n /**\n * Create new instance.\n * @ko 새 인스턴스를 생성합니다.\n * @param options Options {@ko Options}\n */\n public constructor(options: CylindricalProjectionOptions) {\n super(options);\n\n const {\n partial = false\n } = options;\n\n this._partial = partial;\n this._aspect = 1;\n this._halfHeight = 0;\n this._mesh = null;\n }\n\n public createMesh(ctx: WebGLContext, texture: Texture2D) {\n if (this._mesh) return this._mesh;\n\n const partial = this._partial;\n const { width, height } = texture;\n const aspect = width / height;\n const halfVFov = 180 / aspect;\n const cylinderHeight = partial\n ? 1\n : 2 * Math.tan(halfVFov * DEG_TO_RAD);\n const cylinderTheta = partial\n ? aspect\n : 2 * Math.PI;\n\n const geometry = new CylinderGeometry(cylinderTheta);\n const program = new ShaderProgram(ctx, vs, fs, {\n uTexture: new UniformTexture2D(ctx, texture)\n });\n const vao = ctx.createVAO(geometry, program);\n const mesh = new TriangleMesh(vao, program);\n\n mesh.scale[1] = cylinderHeight;\n quat.identity(mesh.rotation);\n quat.rotateY(mesh.rotation, mesh.rotation, -Math.PI / 2);\n mesh.updateMatrix();\n\n this._aspect = aspect;\n this._halfHeight = cylinderHeight * 0.5;\n this._mesh = mesh;\n\n return mesh;\n }\n\n public updateCamera(camera: Camera) {\n super.updateCamera(camera);\n\n const mesh = this._mesh;\n const aspect = this._aspect;\n const halfHeight = this._halfHeight;\n\n if (!mesh) return;\n\n if (this._partial) {\n const restrictedYaw = 0.5 * aspect * RAD_TO_DEG;\n camera.restrictYawRange(-restrictedYaw, restrictedYaw);\n }\n\n const restrictedPitch = Math.atan2(halfHeight, 1) * RAD_TO_DEG;\n const minZoom = Math.tan(camera.fov * DEG_TO_RAD * 0.5) / (halfHeight * camera.aspect);\n\n camera.restrictPitchRange(-restrictedPitch, restrictedPitch);\n camera.restrictZoomRange(minZoom, Infinity);\n camera.restrictRenderHeight(halfHeight * 2);\n }\n}\n\nexport default CylindricalProjection;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Projection, { ProjectionOptions } from \"./Projection\";\nimport TriangleMesh from \"../core/TriangleMesh\";\nimport ShaderProgram from \"../core/ShaderProgram\";\nimport UniformTexture2D from \"../uniform/UniformTexture2D\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport Texture2D from \"../texture/Texture2D\";\nimport CubeGeometry from \"../geometry/CubeGeometry\";\nimport vs from \"../shader/common.vert\";\nimport fs from \"../shader/eac.frag\";\nimport { ROTATE } from \"../const/internal\";\n\n/**\n * Options for {@link EquiangularProjection}\n * @ko {@link EquiangularProjection}의 옵션들\n * @since 4.0.0\n * @category Projection\n */\nexport interface EquiangularProjectionOptions extends ProjectionOptions {}\n\n/**\n * Equi-Angular Cubemap Projection.\n * This format is used by Youtube's 360 videos.\n * @ko Equi-Angular Cubemap 프로젝션.\n * 이 포맷은 주로 Youtube의 360 비디오에 사용됩니다.\n * @since 4.0.0\n * @category Projection\n */\nclass EquiangularProjection extends Projection {\n public createMesh(ctx: WebGLContext, texture: Texture2D) {\n const uniforms = {\n uTexture: new UniformTexture2D(ctx, texture)\n };\n const geometry = new CubeGeometry({\n order: \"LFRDBU\",\n rotateUV: [\n ROTATE.ZERO, ROTATE.ZERO, ROTATE.ZERO,\n ROTATE.CW_90, ROTATE.CCW_90, ROTATE.CW_90\n ]\n });\n const program = new ShaderProgram(ctx, vs, fs, uniforms);\n const vao = ctx.createVAO(geometry, program);\n const mesh = new TriangleMesh(vao, program);\n\n return mesh;\n }\n}\n\nexport default EquiangularProjection;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Projection, { ProjectionOptions } from \"./Projection\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport UniformTexture2D from \"../uniform/UniformTexture2D\";\nimport Texture2D from \"../texture/Texture2D\";\nimport ShaderProgram from \"../core/ShaderProgram\";\nimport SphereGeometry from \"../geometry/SphereGeometry\";\nimport TriangleMesh from \"../core/TriangleMesh\";\nimport vs from \"../shader/common.vert\";\nimport fs from \"../shader/common.frag\";\n\n/**\n * Options for {@link EquirectProjection}\n * @ko {@link EquirectProjection}의 옵션들\n * @since 4.0.0\n * @category Projection\n */\nexport interface EquirectProjectionOptions extends ProjectionOptions {\n src: string | HTMLElement;\n}\n\n/**\n * Projection based on equirectangular projection.\n * @ko 등 장방형 도법(Equirectangular projection) 기반의 프로젝션\n * @since 4.0.0\n * @category Projection\n */\nclass EquirectProjection extends Projection {\n /**\n * Create new instance\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor(options: EquirectProjectionOptions) {\n super(options);\n }\n\n public createMesh(ctx: WebGLContext, texture: Texture2D) {\n const uniforms = {\n uTexture: new UniformTexture2D(ctx, texture)\n };\n\n const geometry = new SphereGeometry();\n const program = new ShaderProgram(ctx, vs, fs, uniforms);\n\n const vao = ctx.createVAO(geometry, program);\n const mesh = new TriangleMesh(vao, program);\n\n return mesh;\n }\n}\n\nexport default EquirectProjection;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Projection, { ProjectionOptions } from \"./Projection\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport UniformTexture2D from \"../uniform/UniformTexture2D\";\nimport UniformFloat from \"../uniform/UniformFloat\";\nimport PanoControl from \"../control/PanoControl\";\nimport ShaderProgram from \"../core/ShaderProgram\";\nimport Texture2D from \"../texture/Texture2D\";\nimport PlaneGeometry from \"../geometry/PlaneGeometry\";\nimport vs from \"../shader/little-planet.vert\";\nimport fs from \"../shader/little-planet.frag\";\nimport TriangleMesh from \"../core/TriangleMesh\";\nimport { OBJECT_3D_EVENTS } from \"../const/internal\";\n\n/**\n * Options for {@link LittlePlanetProjection}\n * @ko {@link LittlePlanetProjection}의 옵션들\n * @since 4.0.0\n * @category Projection\n */\nexport interface LittlePlanetProjectionOptions extends ProjectionOptions {\n src: string | HTMLElement;\n}\n\n/**\n * Projection based on so-called \"Little planet\" or \"Tiny planet\" effect.\n * @ko \"Little planet\" 혹은 \"Tiny planet\"로 불리는 이펙트 기반의 프로젝션\n * @since 4.0.0\n * @category Projection\n */\nclass LittlePlanetProjection extends Projection {\n /**\n * Create new instance\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor(options: LittlePlanetProjectionOptions) {\n super(options);\n }\n\n public createMesh(ctx: WebGLContext, texture: Texture2D) {\n texture.wrapS = WebGLRenderingContext.REPEAT;\n texture.wrapT = WebGLRenderingContext.REPEAT;\n\n const uniforms = {\n uTexture: new UniformTexture2D(ctx, texture),\n uYaw: new UniformFloat(0),\n uPitch: new UniformFloat(0.5),\n uZoom: new UniformFloat(1)\n };\n\n const geometry = new PlaneGeometry();\n const program = new ShaderProgram(ctx, vs, fs, uniforms);\n\n const vao = ctx.createVAO(geometry, program);\n const mesh = new TriangleMesh(vao, program);\n\n mesh.on(OBJECT_3D_EVENTS.UPDATE, ({ camera }) => {\n const uniforms = mesh.program.uniforms;\n\n uniforms.uYaw.val = camera.yaw / 360;\n // Range from 0 ~ 1\n uniforms.uPitch.val = (camera.pitch / 180) + 0.5;\n uniforms.uZoom.val = camera.zoom;\n\n uniforms.uYaw.needsUpdate = true;\n uniforms.uPitch.needsUpdate = true;\n uniforms.uZoom.needsUpdate = true;\n });\n\n return mesh;\n }\n\n public updateControl(control: PanoControl) {\n control.ignoreZoomScale = true;\n }\n}\n\nexport default LittlePlanetProjection;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport Projection, { ProjectionOptions } from \"./Projection\";\nimport WebGLContext from \"../core/WebGLContext\";\nimport Texture from \"../texture/Texture\";\nimport Texture2D from \"../texture/Texture2D\";\nimport TriangleMesh from \"../core/TriangleMesh\";\nimport PlaneGeometry from \"../geometry/PlaneGeometry\";\nimport SphereGeometry from \"../geometry/SphereGeometry\";\nimport ShaderProgram from \"../core/ShaderProgram\";\nimport CorrectionPass, { CorrectionParams } from \"./CorrectionPass\";\nimport UniformTextureRenderTarget from \"../uniform/UniformTextureRenderTarget\";\nimport vs from \"../shader/common.vert\";\nimport fs from \"../shader/common.frag\";\n\n/**\n * Options for {@link WideAngleCorrectionProjection}\n * @ko {@link WideAngleCorrectionProjection}의 옵션들\n * @since 4.0.0\n * @category Projection\n */\nexport interface WideAngleCorrectionOptions extends ProjectionOptions {\n /**\n * 输入图像模式:erp(等距柱状) 或 fisheye(鱼眼)\n * @default \"erp\"\n */\n mode?: \"erp\" | \"fisheye\";\n /**\n * 是否使用平面投影模式展示结果(而非 360 球体)\n * @default false\n */\n flatProjection?: boolean;\n /**\n * Yaw 旋转角度(度)\n * @default 0\n */\n yaw?: number;\n /**\n * Pitch 旋转角度(度)\n * @default 0\n */\n pitch?: number;\n /**\n * Roll 旋转角度(度)\n * @default 0\n */\n roll?: number;\n /**\n * 输入图像水平 FOV(度)\n * @default 180\n */\n hfov?: number;\n /**\n * 输入图像垂直 FOV(度)\n * @default 90\n */\n vfov?: number;\n /**\n * 鱼眼模式 FOV(度)\n * @default 180\n */\n fisheyeFov?: number;\n /**\n * 输出纹理宽度\n * @default 4096\n */\n outputWidth?: number;\n /**\n * 输出纹理高度\n * @default 2048\n */\n outputHeight?: number;\n}\n\n/**\n * 超宽全景矫正 Projection\n * 将非标准全景输入(如 7680x2160)转换为标准 360° equirectangular 格式\n * 仅支持静态图像,矫正在 createMesh 时一次性完成\n * @ko 와이드 앵글 보정 프로젝션. 비표준 파노라마 입력(예: 7680x2160)을 표준 360° equirectangular 형식으로 변환합니다.\n * @since 4.0.0\n * @category Projection\n */\nclass WideAngleCorrectionProjection extends Projection {\n private _correctionParams: CorrectionParams;\n private _correctionPass: CorrectionPass | null = null;\n private _outputWidth: number;\n private _outputHeight: number;\n private _flatProjection: boolean;\n\n /**\n * Create new instance\n * @ko 새로운 인스턴스를 생성합니다.\n * @param options - Options {@ko 옵션들}\n */\n public constructor(options: WideAngleCorrectionOptions) {\n super(options);\n\n this._correctionParams = {\n mode: options.mode ?? \"erp\",\n yaw: options.yaw ?? 0,\n pitch: options.pitch ?? 0,\n roll: options.roll ?? 0,\n hfov: options.hfov ?? 180,\n vfov: options.vfov ?? 90,\n fisheyeFov: options.fisheyeFov ?? 180\n };\n\n this._outputWidth = options.outputWidth ?? 4096;\n this._outputHeight = options.outputHeight ?? 2048;\n this._flatProjection = options.flatProjection ?? false;\n }\n\n public createMesh(ctx: WebGLContext, texture: Texture): TriangleMesh {\n if (texture.isCube()) {\n throw new Error(\"WideAngleCorrectionProjection 仅支持单张 2D 图像,不支持 Cubemap 纹理\");\n }\n\n // 纹理尺寸检查\n const maxSize = ctx.maxTextureSize;\n if (texture.width > maxSize || texture.height > maxSize) {\n throw new Error(\n \"输入纹理尺寸 (\" + texture.width + \"x\" + texture.height + \") 超过 GPU 最大纹理尺寸限制 (\" + maxSize + \"x\" + maxSize + \")。\" +\n \"请使用更小的图片或在支持更大纹理的设备上运行。\"\n );\n }\n if (this._outputWidth > maxSize || this._outputHeight > maxSize) {\n throw new Error(\n \"输出纹理尺寸 (\" + this._outputWidth + \"x\" + this._outputHeight + \") 超过 GPU 最大纹理尺寸限制 (\" + maxSize + \"x\" + maxSize + \")。\" +\n \"请降低 outputWidth/outputHeight 参数值。\"\n );\n }\n\n const gl = ctx.gl;\n // 打印纹理尺寸与 GPU 限制,便于排查清晰度问题\n console.info(\"WideAngleCorrectionProjection 输出纹理尺寸:\", this._outputWidth, \"x\", this._outputHeight, \"输入纹理尺寸:\", texture.width, \"x\", texture.height, \"GPU 最大纹理尺寸:\", ctx.maxTextureSize);\n // 根据宽高比计算平面尺寸,保持高度为 1\n const aspect = this._outputWidth / this._outputHeight;\n\n if (texture.isVideo()) {\n const pass = new CorrectionPass(ctx, this._outputWidth, this._outputHeight);\n this._correctionPass = pass;\n\n const uniforms = {\n uTexture: this._createVideoUniform(texture as Texture2D, gl)\n };\n\n const geometry = this._flatProjection\n ? new PlaneGeometry(aspect, 1, -1) // 平面模式:宽高比平面\n : new SphereGeometry(); // 默认模式:球体\n \n const program = new ShaderProgram(ctx, vs, fs, uniforms);\n const vao = ctx.createVAO(geometry, program);\n const mesh = new TriangleMesh(vao, program);\n\n return mesh;\n }\n\n // 创建矫正 Pass\n const pass = new CorrectionPass(ctx, this._outputWidth, this._outputHeight);\n this._correctionPass = pass;\n\n // 获取输入纹理信息\n const tex2d = texture as Texture2D;\n const inputWidth = texture.width;\n const inputHeight = texture.height;\n\n // 手动创建普通纹理(非 immutable),避免 texStorage2D 导致的问题\n const inputTexture = gl.createTexture();\n if (!inputTexture) {\n throw new Error(\"无法创建输入纹理\");\n }\n\n gl.bindTexture(gl.TEXTURE_2D, inputTexture);\n // 与 app.js 保持一致:不翻转 Y 轴,图像已是正确方向\n // 注意:TextureLoader 默认 flipY: true,但矫正 shader 的坐标约定要求 flipY: false\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n // 使用 texImage2D 上传图像数据(普通 mutable texture)\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tex2d.source);\n\n // 执行矫正渲染(静态图像只需执行一次)\n pass.render(\n inputTexture,\n inputWidth,\n inputHeight,\n this._correctionParams\n );\n\n // 矫正完成后释放输入纹理\n gl.deleteTexture(inputTexture);\n\n // 使用矫正后的纹理创建标准 EquirectProjection 的 Mesh\n // 注意:离屏资源需要随 Mesh 销毁一起释放,因此把释放逻辑交给 uniform.destroy()\n const uniforms = {\n uTexture: new UniformTextureRenderTarget(pass.outputTexture, () => {\n pass.destroy();\n if (this._correctionPass === pass) {\n this._correctionPass = null;\n }\n })\n };\n\n const geometry = this._flatProjection\n ? new PlaneGeometry(aspect, 1, -1)\n : new SphereGeometry();\n \n const program = new ShaderProgram(ctx, vs, fs, uniforms);\n const vao = ctx.createVAO(geometry, program);\n const mesh = new TriangleMesh(vao, program);\n\n return mesh;\n }\n\n private _createVideoUniform(texture: Texture2D, gl: WebGLRenderingContext | WebGL2RenderingContext) {\n const pass = this._correctionPass;\n if (!pass) {\n throw new Error(\"矫正 Pass 未初始化\");\n }\n\n class UniformWideAngleCorrectedVideoTexture extends UniformTextureRenderTarget {\n public readonly sourceTexture: Texture2D;\n private _inputTexture: WebGLTexture;\n private _correctionPass: CorrectionPass;\n private _params: CorrectionParams;\n private _initialized: boolean;\n\n public constructor(correctionPass: CorrectionPass, tex: Texture2D, params: CorrectionParams, onDestroy: () => void) {\n super(correctionPass.outputTexture, onDestroy);\n this.sourceTexture = tex;\n this._correctionPass = correctionPass;\n this._params = params;\n this._initialized = false;\n\n const inputTexture = gl.createTexture();\n if (!inputTexture) {\n throw new Error(\"无法创建输入纹理\");\n }\n\n this._inputTexture = inputTexture;\n gl.bindTexture(gl.TEXTURE_2D, this._inputTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.bindTexture(gl.TEXTURE_2D, null);\n }\n\n public destroy(glCtx: WebGLRenderingContext | WebGL2RenderingContext): void {\n this.sourceTexture.destroy();\n glCtx.deleteTexture(this._inputTexture);\n super.destroy(glCtx);\n }\n\n public update(glCtx: WebGLRenderingContext | WebGL2RenderingContext, location: WebGLUniformLocation, isWebGL2: boolean) {\n const texture = this.sourceTexture;\n const isVideo = texture.isVideo();\n const prevFlipY = glCtx.getParameter(glCtx.UNPACK_FLIP_Y_WEBGL) as boolean;\n\n if (!isVideo || !texture.isPaused() || !this._initialized) {\n if (isVideo) {\n const videoEl = texture.source as HTMLVideoElement;\n if (videoEl.readyState < 2 || videoEl.videoWidth === 0 || videoEl.videoHeight === 0) {\n super.update(glCtx, location, isWebGL2);\n glCtx.pixelStorei(glCtx.UNPACK_FLIP_Y_WEBGL, prevFlipY);\n return;\n }\n }\n\n glCtx.pixelStorei(glCtx.UNPACK_FLIP_Y_WEBGL, 0);\n glCtx.activeTexture(glCtx.TEXTURE0);\n glCtx.bindTexture(glCtx.TEXTURE_2D, this._inputTexture);\n\n if (!isVideo && isWebGL2) {\n glCtx.texSubImage2D(glCtx.TEXTURE_2D, 0, 0, 0, glCtx.RGBA, glCtx.UNSIGNED_BYTE, texture.source);\n } else {\n glCtx.texImage2D(glCtx.TEXTURE_2D, 0, glCtx.RGBA, glCtx.RGBA, glCtx.UNSIGNED_BYTE, texture.source);\n }\n\n const src = texture.source as any;\n const inputWidth = isVideo ? (src.videoWidth || texture.width) : texture.width;\n const inputHeight = isVideo ? (src.videoHeight || texture.height) : texture.height;\n\n this._correctionPass.render(this._inputTexture, inputWidth, inputHeight, this._params);\n this._initialized = true;\n }\n\n super.update(glCtx, location, isWebGL2);\n glCtx.pixelStorei(glCtx.UNPACK_FLIP_Y_WEBGL, prevFlipY);\n }\n }\n\n return new UniformWideAngleCorrectedVideoTexture(pass, texture, this._correctionParams, () => {\n pass.destroy();\n if (this._correctionPass === pass) {\n this._correctionPass = null;\n }\n });\n }\n}\n\nexport default WideAngleCorrectionProjection;\n","/**\n * @hidden\n */\nexport const getValidProps = (propsObj: any) => {\n return Object.keys(propsObj).reduce((props, propName) => {\n if (propsObj[propName] != null) {\n props[propName] = propsObj[propName];\n }\n\n return props;\n }, {});\n};\n","export const VIEW360_METHODS = [\n \"destroy\",\n \"init\",\n \"load\",\n \"resize\",\n \"addPlugins\",\n \"removePlugins\",\n \"renderFrame\",\n // @egjs/component methods\n \"on\",\n \"hasOn\",\n \"once\",\n \"off\",\n \"trigger\"\n] as const;\n","import Component from \"@egjs/component\";\nimport View360 from \"../View360\";\n\n/**\n * @hidden\n */\nconst withMethods = (prototype: any, attr: string) => {\n [Component.prototype, View360.prototype].forEach(proto => {\n Object.getOwnPropertyNames(proto)\n .filter(name => name.charAt(0) !== \"_\" && name !== \"constructor\")\n .forEach((name: string) => {\n const descriptor = Object.getOwnPropertyDescriptor(proto, name)!;\n\n if (descriptor.value) {\n // Public Function\n Object.defineProperty(prototype, name, {\n value: function(...args) {\n return descriptor.value.call(this[attr], ...args);\n }\n });\n } else {\n const getterDescriptor: { get?: () => any; set?: (val: any) => void } = {};\n if (descriptor.get) {\n getterDescriptor.get = function() {\n return this[attr] && descriptor.get?.call(this[attr]);\n };\n }\n if (descriptor.set) {\n getterDescriptor.set = function(...args) {\n return descriptor.set?.call(this[attr], ...args);\n };\n }\n\n Object.defineProperty(prototype, name, getterDescriptor);\n }\n });\n });\n};\n\nexport default withMethods;\n","/*\n * Copyright (c) 2023-present NAVER Corp.\n * egjs projects are licensed under the MIT license\n */\nimport View360, * as modules from \"./index\";\nimport { merge } from \"./utils\";\n\nmerge(View360, modules);\n\nexport default View360;\n"],"names":["View360Error","Error","constructor","message","code","super","Object","setPrototypeOf","this","prototype","name","ERROR_CODES","WRONG_TYPE","WRONG_OPTION","ELEMENT_NOT_FOUND","CANVAS_NOT_FOUND","WEBGL_NOT_SUPPORTED","FAILED_CREATE_CONTEXT_2D","PROVIDE_PROJECTION_FIRST","FAILED_LINKING_PROGRAM","INSUFFICIENT_ARGS","ERROR","val","types","map","type","join","optionName","query","msg","shaderLog","EVENTS","EL_DIV","EL_BUTTON","MOUSE_BUTTON","CURSOR","KEY_DIRECTION","DIRECTION_KEY_CODE","DIRECTION_KEY_NAME","LEFT","UP","RIGHT","DOWN","FULLSCREEN_REQUEST","FULLSCREEN_ELEMENT","FULLSCREEN_EXIT","FULLSCREEN_CHANGE","DEFAULT_CLASS","CONTAINER","CANVAS","CTX_LOST","IN_VR","HOTSPOT_CONTAINER","HOTSPOT","HOTSPOT_VISIBLE","HOTSPOT_FLIP_X","HOTSPOT_FLIP_Y","READY","LOAD_START","LOAD","PROJECTION_CHANGE","RESIZE","BEFORE_RENDER","RENDER","INPUT_START","INPUT_END","VIEW_CHANGE","STATIC_CLICK","VR_START","VR_END","EASING","LINEAR","x","SINE_WAVE","Math","sin","PI","EASE_OUT_CUBIC","pow","EASE_OUT_BOUNCE","n1","d1","CAMERA_EVENTS","OBJECT_3D_EVENTS","CONTROL_EVENTS","DEG_TO_RAD","RAD_TO_DEG","DEFAULT_EASING","DEFAULT_ANIMATION_DURATION","INFINITE_RANGE","min","Infinity","max","DEFAULT_PITCH_RANGE","DEFAULT_ZOOM_RANGE","ROTATE","VIDEO_TIME_CHANGE_EVENT","SVG_NAMESPACE","SESSION_VR","XR_REFERENCE_SPACE","EPSILON","isString","createElement","className","tag","BROWSER","el","document","classList","add","getNullableElement","parent","targetEl","queryResult","querySelector","nodeType","Node","ELEMENT_NODE","clamp","lerp","a","b","t","circulate","size","abs","findIndex","array","checker","idx","length","getObjectOption","toVerticalFov","fovRadian","aspect","atan","tan","reorderCube","arr","order","defaultOrder","split","face","indexOf","index","isFullscreen","key","sensorCanBeEnabledIOS","hostname","window","location","protocol","DeviceMotionEvent","hfovToZoom","baseFov","fov","eulerToQuat","out","yaw","pitch","roll","quat","pitchClamped","quatToEuler","quaternion","y","z","w","unit","test","atan2","view","vec3","up","viewXZ","sqrt","Motion","_val","start","_start","end","_end","progress","_progress","activated","_activated","duration","_duration","loop","_loop","range","_range","easing","_easing","reset","update","deltaTime","prev","nextProgress","easedProgress","defaultVal","delta","setNewEndByDelta","setRange","CameraAnimation","_motion","camera","from","to","_camera","_from","_to","_finishPromise","Promise","resolve","_finish","getFinishPromise","motion","rotation","zoom","rotate","Camera","Component","_aspect","changed","_changed","yawRange","_initialYawRange","pitchRange","_initialPitchRange","zoomRange","_initialZoomRange","initialYaw","initialPitch","initialZoom","rollOffset","position","animation","_up","_yawRange","_pitchRange","_zoomRange","_updateQuaternion","viewMatrix","mat4","projectionMatrix","_maxRenderHeight","destroy","off","resize","width","height","prevAspect","updateMatrix","lookAt","prevQuaternion","prevZoom","zoomDiff","normalized","isSameRotation","animateTo","finishPromise","then","trigger","restrictYawRange","restrictPitchRange","restrictZoomRange","restrictRenderHeight","resetRange","getYawRange","yawLimit","maxRenderHeight","halfHFov","getHorizontalFov","minYaw","maxYaw","halfVFovRad","h","d","theta","getPitchRange","pitchLimit","minPitch","maxPitch","halfVFov","getVerticalFov","getZoomRange","limit","_a","minFov","maxFov","currentFov","current","_getZoomedHorizontalFov","hFov","fovToZoom","projMatrix","upDir","viewDir","vFov","onFrameRender","MouseInput","_onMouseDown","evt","_el","button","preventDefault","focus","_prevPos","clientX","clientY","addEventListener","_onMouseMove","_onMouseUp","srcEvent","isTouch","isKeyboard","prevPos","deltaX","deltaY","removeEventListener","scrolling","enable","element","disable","TouchInput","scrollable","_scrollable","_onTouchStart","touches","_scrolling","touch","_isFirstTouch","_onTouchMove","cancelable","_onTouchEnd","passive","KeyboardInput","active","pressed","_pressed","_onKeyDown","KeyboardEvent","DOM_KEY_LOCATION_STANDARD","_updateKeyPress","pressedCount","_getPressedKeyCount","repeat","_onKeyUp","_clearPressedKeys","_getDeltaByPressedKeys","reduce","obj","keyName","assign","event","isEnable","keyToUpdate","keyCode","filter","RotateControl","enabled","_enabled","enableBlocked","_enableBlocked","animating","_keyboardInput","_xMotion","_yMotion","_touchInput","pointerScale","_pointerScale","keyboardScale","_keyboardScale","disablePitch","_disablePitch","disableYaw","_disableYaw","disableKeyboard","_disableKeyboard","controlEl","_onInputStart","_changedWhileDragging","inputType","_onChange","invZoomScale","_zoomScale","screenScale","_screenScale","scale","scaledX","scaledY","_onInputEnd","_controlEl","_mouseInput","_bindInputs","xMotion","yMotion","keyboardInput","updateByCameraPath","updateRange","setZoomScale","hfov","vfov","control","updateCursor","sync","mouseInput","touchInput","on","WheelInput","_onWheel","stopPropagation","_inputTimer","_clearTimer","_baseScale","setTimeout","capture","clearTimeout","PinchInput","prevDistance","_prevDistance","diff","pageX","pageY","distance","ZoomControl","scaledDelta","_scale","_wheelInput","_pinchInput","wheelInput","pinchInput","ROTATE_CONSTANT","PITCH_DELTA","YAW_DELTA_BY_ROLL","YAW_DELTA_BY_YAW","targetAxis","meshPoint","GyroInput","orientationUpdated","_orientationUpdated","ignoreRoll","_ignoreRoll","_onDeviceOrientation","prevOrientation","_orientation","alpha","beta","gamma","_needsCalibrate","_calibrateSensor","_updateScreenOrientation","screen","orientation","undefined","angle","_screenOrientation","_yawOrigin","_yawOffset","_updateRotation","collectDelta","prevRotation","_toEulerDelta","setInitialRotation","yawOrigin","sensorYaw","screenAngle","world","cos","prevQuat","currentQuat","_getDeltaYaw","_getDeltaPitch","prvQ","curQ","yawDeltaByYaw","_getRotationDelta","_extractPitchFromQuat","prevQ","rotateKind","curQuaternion","prevPoint","curPoint","rotateDirection","meshPoint2","meshPoint3","vecU","vecV","vecN","coefficientA","coefficientB","coefficientC","projectedPrevPoint","trigonometricRatio","acos","crossVec","thetaDirection","baseV","GyroControl","_input","static","onDeviceMotionChange","race","res","rotationRate","available","requestPermission","permissionState","catch","_updateYawPitch","input","yawDelta","pitchDelta","PanoControl","useGrabCursor","_useGrabCursor","_setCursor","disableContextMenu","_disableContextMenu","_blockContextMenu","_restoreContextMenu","_rotateControl","wheelScrollable","_zoomControl","ignoreZoomScale","_ignoreZoomScale","gyro","_gyroControl","_preventContextMenu","_onEnable","_onDisable","_onCameraAnimationEnd","_bindEvents","isAvailable","rotateControl","zoomControl","gyroControl","zoomScale","newCursor","style","cursor","Texture","flipY","wrapS","WebGLRenderingContext","CLAMP_TO_EDGE","wrapT","isVideo","isCube","Texture2D","source","TextureVideo","hls","video","pause","removeAttribute","load","isPaused","paused","ended","readyState","hasAudio","audioTracks","webkitAudioDecodedByteCount","mozHasAudio","TextureCube","sources","TextureLoader","debug","pendingHls","_loadChecker","ImReady","_debug","src","loadVideo","Array","isArray","loadCubeImage","imgSrc","loadImage","images","_toImageArray","_load","image","naturalWidth","naturalHeight","videoConfig","config","autoplay","muted","volume","hlsConfig","hlsEnabled","hlsForce","force","hlsSource","_getHlsSource","shouldUseHls","_isM3u8Source","hlsModule","Hls","isSupported","hasHlsSupport","useHlsJs","useExistingVideo","HTMLVideoElement","_toVideoElement","_attachVideoDebugListeners","loadSource","attachMedia","console","info","canPlayType","_logVideoState","currentTime","playPromise","play","err","texture","videoWidth","videoHeight","content","onLoad","loader","reject","once","errorCount","check","imgEl","Image","crossOrigin","skipSource","playsInline","setAttribute","forEach","_appendSourceElement","querySelectorAll","handler","label","seekableStart","seekableEnd","seekable","currentSrc","HTMLSourceElement","sourceEl","appendChild","FrameAnimator","maxDeltaTime","context","_context","_rafId","_rafTimer","_lastUpdateTime","callback","_time","frame","time","Date","now","requestAnimationFrame","stop","cancelAnimationFrame","changeContext","AutoResizer","useResizeObserver","_useResizeObserver","onResize","_skipFirstResize","isFirstResize","_onResize","_resizeObserver","ResizeObserver","bbox","getBoundingClientRect","resizeImmediate","resizeObserver","observe","disconnect","Autoplay","playing","_interrupted","delay","_delay","delayOnMouseLeave","_delayOnMouseLeave","speed","_speed","pauseOnHover","_pauseOnHover","canInterrupt","_canInterrupt","disableOnInterrupt","_disableOnInterrupt","viewer","options","_clearTimeout","_setUninterruptedAfterDelay","_onGyroEnable","_onMouseEnter","_hovering","_onMouseLeave","_control","_element","_interruptionTimer","enableAfterDelay","CameraPath","fps","_fps","smoothing","_smoothing","Number","isFinite","hasFrames","_frameCount","_onVideoFrame","_now","metadata","_lastMediaTime","mediaTime","_video","_videoFrameCallbackId","requestVideoFrameCallback","_frames","_lastFrameIndex","_timeOffset","setFrames","frames","prevIndex","Float32Array","floor","count","data","i","base","newCount","setTimeOffset","offset","resetTimeOffset","clear","_stopVideoFrameCallback","updateByTime","maxIndex","rawIndex","frameIndex","clampFrameIndex","forceInstant","frameJumpThreshold","nextIndex","ratio","nextBase","fromYaw","fromPitch","fromZoom","targetYaw","lerpYaw","targetPitch","targetZoom","_applyTarget","updateFromVideo","_ensureVideoFrameCallback","_getVideoTime","isVideoFrameCallbackSupported","request","call","cancelVideoFrameCallback","targetChanged","yawMotion","pitchMotion","targetFov","prevYaw","yawJump","warn","toFixed","yawDiff","pitchDiff","epsilon","hasDiff","XRManager","ctx","exit","_onSessionEnd","_xrSession","_xrRefSpace","_ctx","_options","xr","navigator","isSessionSupported","enter","requestSensorPermission","requiredFeatures","makeXRCompatible","session","requestSession","bindXRLayer","refSpace","requestReferenceSpace","_setSession","xrSession","canRender","getViewerPose","getEyeParams","pose","glLayer","renderState","baseLayer","views","viewport","getViewport","vMatrix","transform","inverse","matrix","pMatrix","Hotspot","HotspotRenderer","rootEl","renderer","_containerEl","_renderer","_hotspots","_zoom","refresh","container","hotspotEls","slice","apply","_parseHotspot","render","hotspots","halfWidth","halfHeight","centerTransform","zoomTransform","hotspot","relPos","remove","screenPos","vec2","yawStr","dataset","pitchStr","positionStr","parseFloat","_yawPitchToVec3","pos","defaultPos","yawRad","pitchRad","VertexArrayObject","geometry","indicies","buffers","WebGLContext","canvas","_canvas","gl","_gl","maxTextureSize","_maxTextureSize","isWebGL2","_isWebGL2","supportVAO","_extensions","vao","lost","_contextLost","_onContextLost","_onContextRestore","loseContext","init","_getContext","getParameter","MAX_TEXTURE_SIZE","getExtension","bindBuffer","ARRAY_BUFFER","ELEMENT_ARRAY_BUFFER","forceLoseContext","extension","forceRestoreContext","restoreContext","COLOR_BUFFER_BIT","drawingBufferWidth","drawingBufferHeight","createVAO","shaderProgram","nativeVAO","_createNativeVAO","_createBuffer","uv","_bindNativeVAO","_supplyGeometryData","_unbindBuffers","draw","drawElements","TRIANGLES","UNSIGNED_SHORT","releaseVAO","_deleteNativeVAO","_deleteBuffer","getUniformLocations","program","uniforms","uniformLocations","keys","locations","getUniformLocation","_getCommonUniformLocations","updateCommonUniforms","entity","mvMatrix","uniformMatrix4fv","uMVMatrix","uPMatrix","updateVRUniforms","eyeIndex","uEye","uniform1f","updateUniforms","uniform","needsUpdate","releaseShaderResources","deleteProgram","useProgram","createProgram","vertexShader","fragmentShader","vs","_compileShader","VERTEX_SHADER","fs","FRAGMENT_SHADER","attachShader","bindAttribLocation","linkProgram","getProgramParameter","LINK_STATUS","getShaderParameter","COMPILE_STATUS","getShaderInfoLog","getProgramInfoLog","deleteShader","createWebGLTexture","texData","createTexture","bindTexture","TEXTURE_2D","texParameteri","TEXTURE_MIN_FILTER","TEXTURE_MAG_FILTER","TEXTURE_WRAP_S","TEXTURE_WRAP_T","gl2","texStorage2D","RGBA8","createWebGLCubeTexture","TEXTURE_CUBE_MAP","attributes","getContextAttributes","xrCompatible","xrLayer","XRWebGLLayer","updateRenderState","bindXRFrame","bindFramebuffer","FRAMEBUFFER","framebuffer","useDefaultFrameBuffer","createFramebuffer","texImage2D","RGBA","UNSIGNED_BYTE","framebufferTexture2D","COLOR_ATTACHMENT0","status","checkFramebufferStatus","FRAMEBUFFER_COMPLETE","deleteFramebuffer","fbo","deleteTexture","createBuffer","buffer","deleteBuffer","createVertexArray","ext","createVertexArrayOES","bindVertexArray","bindVertexArrayOES","deleteVertexArray","deleteVertexArrayOES","_supplyIndiciesData","_supplyAttributeData","vertices","uvs","bufferData","STATIC_DRAW","attribute","attribLocation","getAttribLocation","vertexAttribPointer","itemSize","FLOAT","enableVertexAttribArray","shader","createShader","shaderSource","compileShader","webglIdentifiers","contextAttributes","preserveDrawingBuffer","antialias","onWebglContextCreationError","e","statusMessage","identifier","getContext","WebGLRenderer","_elementSize","pixelRatio","_pixelRatio","renderWidth","_renderSize","renderHeight","canvasSize","devicePixelRatio","clientWidth","clientHeight","cssWidth","cssHeight","fixedWidth","fixedHeight","round","setRenderSize","normalizedWidth","normalizedHeight","mesh","renderVR","vr","eyeParams","eye","View360","_rootEl","_renderWidth","_renderHeight","cameraPath","_cameraPath","_earlyHls","_mesh","getTexture","_vr","_hotspot","plugins","_plugins","projection","_projection","_initialized","initialized","_autoplay","autoInit","_autoInit","autoResize","_autoResize","canvasSelector","_canvasSelector","tabIndex","_tabIndex","_animator","updateCamera","root","renderFrame","autoPlayer","useCameraPath","_emit","_cameraPathPaused","_renderFrameOnDemand","isVideoPaused","_renderVRFrame","_delta","_onVideoTimeUpdate","currentTarget","getElement","findCanvas","selector","_autoResizer","_videoEventTarget","_addEventHandlers","_unbindVideoEvents","plugin","animator","_bindComponentEvents","_resizeComponents","_loadTexture","_applyProjection","hasAttribute","addPlugins","push","removePlugins","pluginIdx","splice","eventName","params","evtParams","target","newMesh","createMesh","updateControl","_bindVideoEvents","contentLoader","loadPromise","events","evtName","VERSION","Object3D","LoadingSpinner","_startLoading","_container","_detachElements","parentElement","removeChild","_createElements","ring","RING","ControlBarItem","CONTROL_BAR_DEFAULT_CLASS","CONTROLS_ROOT","CONTROLS_BG","CONTROLS_MAIN","CONTROLS_TOP","CONTROLS_BOTTOM","CONTROLS_MID","CONTROLS_LEFT","CONTROLS_RIGHT","CONTROLS_FLOAT_LEFT","CONTROLS_FLOAT_RIGHT","CONTROLS_BUTTON","PROGRESS_ROOT","VOLUME_ROOT","RANGE_ROOT","RANGE_TRACK","RANGE_THUMB","RANGE_FILLER","PLAY_BUTTON","PAUSE_BUTTON","UNMUTED_BUTTON","MUTED_BUTTON","FULLSCREEN_BUTTON","FULLSCREEN_EXIT_BUTTON","VR_BUTTON","GYRO_ENABLED","GYRO_DISABLED","VIDEO_TIME_DISPLAY","PIEVIEW_ROOT","FIXED","UNAVAILABLE","HIDDEN","CONTROL_BAR_ITEM_POSITION","TOP_LEFT","TOP_RIGHT","MAIN_TOP","MAIN_BOTTOM","MAIN_LEFT","MAIN_RIGHT","RangeControl","_onHold","_bbox","elX","scrollX","pageXOffset","clamepdX","thumbEl","_fixedClass","_onRelease","track","thumb","filler","draggable","trackEl","fillerEl","left","right","bottom","top","updateStyle","clampedProgress","ProgressBar","_rangeControl","_onTimeUpdate","_currentTime","_onDurationChange","controlBar","_controlBar","dispatchEvent","CustomEvent","detail","_wasPaused","_playPromise","_onControl","rangeControl","unavailableClass","PlayButton","_onClick","_paused","_onPlay","title","_onPause","VolumeControl","_updateDisplay","disabled","_onVolumeChange","_buttonEl","containerEl","buttonEl","FullscreenButton","_targetEl","_exitFullscreen","_requestFullscreen","_onFullscreenChange","_fullscreenAvailable","_addFullscreenHandlers","_removeFullscreenHandlers","some","VideoTime","_onCustomTimeChange","timeMinute","timeSeconds","timeSecondsFormatted","durationMinute","durationSeconds","durationSecondsFormatted","innerText","PieView","resetCamera","_viewer","_updatePie","piePath","_piePathEl","rangeCircle","_rangeCircleEl","halfFov","pieRadius","pieDeg","pieOffset","radius","rangeDiff","_createPieElements","rootClass","pieSVG","createElementNS","VRButton","GyroButton","_updateStyle","enableButton","AutoHide","hidden","contains","_hiddenClass","initialDelay","idleDelay","activationDelay","_isCursorInside","show","_hideAfterDelay","_isFullscreen","showTemporaliy","_isGrabbing","pointerType","_onVideoPlay","_onVideoPause","_initialDelay","_idleDelay","_timer","hide","_clearHideTimer","VideoControl","videoEl","keyPressed","_changeVideoTime","_changeVideoVolume","_toggleVideo","forward","increase","ControlBar","backgroundEl","_bgEl","items","_items","customItems","_customItems","autoHide","showBackground","clickToPlay","keyboardControls","progressBar","playButton","volumeButton","fullscreenButton","videoTime","pieView","vrButton","gyroButton","_onStaticClick","autoHider","_autoHider","_onNewSrcLoad","_updateBackground","_updateAutoHide","_updateKeyboardHandler","item","_createPositionWrappers","POSITION","_videoControl","panoRoot","controlsRoot","defaultItems","_createDefaultItems","_addItem","_clearItemElements","category","wrapper","_wrapperEl","nextSiblingIndex","sibling","nextSibling","insertBefore","floatLeftEl","floatRightEl","topWrapper","bottomWrapper","midWrapper","leftControlsWrapper","rightControlsWrapper","firstChild","background","hiddenClass","_b","videoControl","Projection","Uniform","UniformTextureCube","cubemapOrder","_webglTexture","_cubemapOrder","pixelStorei","UNPACK_FLIP_Y_WEBGL","uniform1i","activeTexture","TEXTURE0","texSubImage2D","TEXTURE_CUBE_MAP_POSITIVE_X","CubeTexturePainter","_size","_renderingOrder","undef","_calcRenderingSize","surfaceIdx","row","_row","column","_column","renderingFace","drawImage","UniformCanvasCube","_painter","TriangleMesh","uTexture","sourceTexture","ShaderProgram","VertexData","Geometry","Uint16Array","CubeGeometry","rotateUV","oneThird","coords","r","c","coord","degree","ZERO","newOrder","CW_90","CCW_90","newCoords","uvIdx","acc","concat","UniformTexture2D","CylinderGeometry","maxTheta","heightSegments","invRadialSegments","angleConst","yIdx","lngIdx","u","v","SphereGeometry","ANGLE_CORRECTION_FOR_CENTER_ALIGN","latIdx","sinTheta","cosTheta","phi","sinPhi","UniformFloat","PlaneGeometry","UniformVector4Array","uniform4fv","vector","StereoEquiProjection","_mode","mode","leftEye","rightEye","MODE","LEFT_RIGHT","uTexScaleOffset","TOP_BOTTOM","TextureRenderTarget","glTexture","CorrectionPass","outputTexture","_outputTexture","outputWidth","outputHeight","_outputWidth","_outputHeight","_fbo","_program","_uniformLocations","uMode","uRotYPR","uHFov","uVFov","uFisheyeFov","uImgSize","quadBuffer","_quadBuffer","inputTexture","inputWidth","inputHeight","locs","prevFramebuffer","FRAMEBUFFER_BINDING","prevViewport","VIEWPORT","prevProgram","CURRENT_PROGRAM","prevClearColor","COLOR_CLEAR_VALUE","prevActiveTexture","ACTIVE_TEXTURE","prevTextureBinding2D","TEXTURE_BINDING_2D","prevArrayBuffer","ARRAY_BUFFER_BINDING","glAsAny","vaoExt","prevVAOBinding","VERTEX_ARRAY_BINDING","VERTEX_ARRAY_BINDING_OES","clearColor","toRad","deg","uniform3f","fisheyeFov","uniform2f","posLoc","drawArrays","TRIANGLE_STRIP","disableVertexAttribArray","UniformTextureRenderTarget","onDestroy","_onDestroy","_keepNeedsUpdateForDestroy","UniformInt","UniformVec2","UniformVec3","RealtimeCorrectionTextureUniform","tex","glTex","targetWidth","targetHeight","isImmutableTexture","_imgSizeUniform","_scaleCanvas","_scaleCtx","_textureAllocated","_allocatedWidth","_allocatedHeight","_isImmutableTexture","_targetWidth","_targetHeight","_initScaleCanvas","setImgSizeUniform","glCtx","_uploadPlaceholder","actualWidth","actualHeight","curSize","sourceWidth","sourceHeight","textureSource","getEffectiveTargetWidth","getEffectiveTargetHeight","OffscreenCanvas","_e","pixel","Uint8Array","cubemapFlipX","_cubemapFlipX","partial","_partial","_halfHeight","cylinderHeight","cylinderTheta","restrictedYaw","restrictedPitch","minZoom","REPEAT","uYaw","uPitch","uZoom","_correctionPass","_correctionParams","_c","_d","_f","_g","_h","_j","_flatProjection","_k","flatProjection","maxSize","pass","_createVideoUniform","tex2d","correctionPass","_params","_inputTexture","prevFlipY","_uniforms","correction","_yaw","_pitch","_roll","_hfov","_m","_l","_vfov","_p","_o","_fisheyeFov","_r","_q","_inputWidth","_s","_inputHeight","_t","useInputScaling","webglTexture","effectiveTargetWidth","effectiveTargetHeight","useScaling","imgWidth","imgHeight","rollRad","hfovRad","vfovRad","fisheyeFovRad","imgSize","inputScale","propsObj","props","propName","withMethods","attr","proto","getOwnPropertyNames","charAt","descriptor","getOwnPropertyDescriptor","value","defineProperty","args","getterDescriptor","get","set","merge","srcs","modules"],"mappings":"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"}