From 9ffd3f10890fc2f4fe1e6033ecf381db064a8841 Mon Sep 17 00:00:00 2001 From: maia arson crimew Date: Sun, 28 Dec 2025 23:24:24 +0100 Subject: [PATCH] add support for 360 panorama embeds yayyy using naver view360 --- .eleventy.js | 2 ++ src/_includes/components/view360.js | 24 ++++++++++++++++++++++ src/static/view360/view360.min.css | 1 + src/static/view360/view360.pkgd.min.js | 16 +++++++++++++++ src/static/view360/view360.pkgd.min.js.map | 1 + 5 files changed, 44 insertions(+) create mode 100644 src/_includes/components/view360.js create mode 100644 src/static/view360/view360.min.css create mode 100644 src/static/view360/view360.pkgd.min.js create mode 100644 src/static/view360/view360.pkgd.min.js.map diff --git a/.eleventy.js b/.eleventy.js index 1750ccf..66aa758 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -12,6 +12,7 @@ const footnotes = require('eleventy-plugin-footnotes'); const figure = require('./src/_includes/components/figure.js'); const bounce = require('./src/_includes/components/bounce.js'); +const view360 = require('./src/_includes/components/view360.js'); module.exports = function (eleventyConfig) { const isDev = (process.env.ELEVENTY_ENV || "dev") == "dev"; @@ -47,6 +48,7 @@ module.exports = function (eleventyConfig) { eleventyConfig.addShortcode('figure', figure(md)); eleventyConfig.addShortcode('bounce', bounce); + eleventyConfig.addShortcode('view360', view360); eleventyConfig.addPassthroughCopy({ "src/static": "/" }); eleventyConfig.addPassthroughCopy({ "node_modules/reveal.js/dist/reveal.css": "reveal.js/reveal.css" }); diff --git a/src/_includes/components/view360.js b/src/_includes/components/view360.js new file mode 100644 index 0000000..66c2fba --- /dev/null +++ b/src/_includes/components/view360.js @@ -0,0 +1,24 @@ +// for now this only supports one type of projection because i cant be bothered to implement all of them lol +module.exports = async ({ src, ratio = '16by9', autoplay = false, autoplaySpeed = .2 }) => ` + + + +
+ +
+ + +` \ No newline at end of file diff --git a/src/static/view360/view360.min.css b/src/static/view360/view360.min.css new file mode 100644 index 0000000..0f3bb21 --- /dev/null +++ b/src/static/view360/view360.min.css @@ -0,0 +1 @@ +.view360-container{position:relative;touch-action:pan-y;overflow:hidden}.view360-canvas{position:absolute;left:0;top:0;width:100%;height:100%;-ms-user-select:none;user-select:none;-webkit-user-drag:none}.view360-canvas.ctx-lost{text-indent:.001px}.view360-container.is-1by1,.view360-container.is-square{padding-top:100%}.view360-container.is-5by4{padding-top:80%}.view360-container.is-4by3{padding-top:75%}.view360-container.is-3by2{padding-top:66.6666%}.view360-container.is-5by3{padding-top:60%}.view360-container.is-16by9{padding-top:56.25%}.view360-container.is-2by1{padding-top:50%}.view360-container.is-3by1{padding-top:33.3333%}.view360-container.is-4by5{padding-top:125%}.view360-container.is-3by4{padding-top:133.3333%}.view360-container.is-2by3{padding-top:150%}.view360-container.is-3by5{padding-top:166.6666%}.view360-container.is-9by16{padding-top:177.7777%}.view360-container.is-1by2{padding-top:200%}.view360-container.is-1by3{padding-top:300%}.view360-container:-ms-fullscreen{padding-top:0}.view360-container:fullscreen{padding-top:0}.view360-controls{position:absolute;top:0;left:0;width:100%;height:100%;padding:0;margin:0;border:0;pointer-events:none;-ms-user-select:none;user-select:none;-webkit-user-drag:none;z-index:1}.view360-main.view360-vr-presenting .view360-controls{display:none}.view360-controls-float-left,.view360-controls-float-right{position:absolute;display:flex;flex-direction:column}.view360-controls-float-left{left:0;top:0}.view360-controls-float-right{right:0;top:0}.view360-controls-main{position:absolute;bottom:0;left:0;width:100%;opacity:1;transition:none}.view360-controls-main.view360-controls-hidden{opacity:0;transition:opacity .5s}.view360-controls-main.view360-controls-hidden *{pointer-events:none}.view360-controls-main.view360-controls-fixed{opacity:1}.view360-controls-background{width:100%;height:calc(100% + 32px);position:absolute;left:0;bottom:0;background-image:linear-gradient(0deg,#323232,rgba(50,50,50,0))}.view360-controls-background.view360-controls-hidden{display:none}.view360-controls-mid{display:flex;flex-direction:row;position:relative}.view360-controls-left{display:flex;flex:1;justify-content:flex-start;align-items:center;flex-direction:row}.view360-controls-right{display:flex;align-items:center;flex-direction:row}.view360-controls-bottom{display:flex;align-items:center;flex-direction:row}.view360-controls-button{display:inline-block;background-color:transparent;cursor:pointer;border:0;position:relative;background-size:24px 24px;background-origin:content-box;background-repeat:no-repeat;box-sizing:border-box;pointer-events:all;border-radius:20px;transition:opacity 250ms;width:40px;height:40px;margin:6px;padding:8px;opacity:.8}.view360-controls-button:hover{opacity:1}.view360-controls-button.view360-controls-vr{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='48' width='48' viewBox='0 0 100 100'%3E%3Cg%3E%3Cpath d='M5,30 L95,30 L95,80 L55,80 L50,70 L45,80 L5,80 L5,30' fill='transparent' stroke='%23fff' stroke-width='8' stroke-linejoin='round' stroke-linecap='round'/%3E%3Cpath d='M5,30 L15,10 L85,10 L95,30' fill='transparent' stroke='%23fff' stroke-width='8' stroke-linejoin='round' stroke-linecap='round'/%3E%3Ccircle cx='30' cy='55' r='10' stroke='%23fff' stroke-width='8' fill='transparent' /%3E%3Ccircle cx='70' cy='55' r='10' stroke='%23fff' stroke-width='8' fill='transparent' /%3E%3C/g%3E%3C/svg%3E")}.view360-controls-button.view360-controls-play{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' stroke-width='2' stroke='%23fff' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'%3E%3C/path%3E%3Cpath d='M7 4v16l13 -8z'%3E%3C/path%3E%3C/svg%3E")}.view360-controls-button.view360-controls-pause{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' stroke-width='2' stroke='%23fff' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'%3E%3C/path%3E%3Crect x='6' y='5' width='4' height='14' rx='1'%3E%3C/rect%3E%3Crect x='14' y='5' width='4' height='14' rx='1'%3E%3C/rect%3E%3C/svg%3E")}.view360-controls-button.view360-controls-unmuted{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' stroke-width='2' stroke='%23fff' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'%3E%3C/path%3E%3Cpath d='M15 8a5 5 0 0 1 0 8'%3E%3C/path%3E%3Cpath d='M17.7 5a9 9 0 0 1 0 14'%3E%3C/path%3E%3Cpath d='M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5'%3E%3C/path%3E%3C/svg%3E")}.view360-controls-button.view360-controls-muted{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' stroke-width='2' stroke='%23fff' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'%3E%3C/path%3E%3Cpath d='M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5'%3E%3C/path%3E%3Cpath d='M16 10l4 4m0 -4l-4 4'%3E%3C/path%3E%3C/svg%3E")}.view360-controls-button.view360-controls-fullscreen{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' stroke-width='2' stroke='%23fff' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'%3E%3C/path%3E%3Cpath d='M4 8v-2a2 2 0 0 1 2 -2h2'%3E%3C/path%3E%3Cpath d='M4 16v2a2 2 0 0 0 2 2h2'%3E%3C/path%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v2'%3E%3C/path%3E%3Cpath d='M16 20h2a2 2 0 0 0 2 -2v-2'%3E%3C/path%3E%3C/svg%3E")}.view360-controls-button.view360-controls-fullscreen-exit{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' stroke-width='2' stroke='%23fff' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'%3E%3C/path%3E%3Cpath d='M15 19v-2a2 2 0 0 1 2 -2h2'%3E%3C/path%3E%3Cpath d='M15 5v2a2 2 0 0 0 2 2h2'%3E%3C/path%3E%3Cpath d='M5 15h2a2 2 0 0 1 2 2v2'%3E%3C/path%3E%3Cpath d='M5 9h2a2 2 0 0 0 2 -2v-2'%3E%3C/path%3E%3C/svg%3E")}.view360-controls-button.view360-controls-gyro-enabled{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='48' width='48'%3E%3Cpath fill='%23fff' d='M22.5 7.6v2.95q-1 .15-1.975.475-.975.325-1.875.825L16.5 9.7q1.35-.9 2.875-1.4 1.525-.5 3.125-.7Zm15.35 15.35q-.2 1.6-.7 3.125-.5 1.525-1.4 2.875L33.6 26.8q.5-.9.825-1.875.325-.975.475-1.975Zm3.8 20.45L1.3 3.05 3.45.9 43.8 41.25ZM7 41.4q-1.25 0-2.125-.875T4 38.4v-8.6h3v8.6h8.6v3ZM41 13V4.4h-8.6v-3H41q1.25 0 2.125.875T44 4.4V13ZM4 13V4.4q0-.55.2-1.1t.6-1l2.1 2.1V13Zm28.4 28.4v-3h8.5l2.1 2.1q-.4.45-.925.675-.525.225-1.075.225Zm-21.2-37-3-3h7.4v3ZM44 37.2l-3-3v-4.4h3ZM10.15 22.95h2.95q.5 3.7 3.1 6.3 2.6 2.6 6.3 3.1v2.95q-4.9-.55-8.35-4-3.45-3.45-4-8.35Zm4-11.35 2.1 2.05q-1.3 1.3-2.1 2.9-.8 1.6-1.05 3.4h-2.95q.25-2.4 1.275-4.525Q12.45 13.3 14.15 11.6ZM31.8 29.2l2.05 2.1q-1.7 1.7-3.825 2.725Q27.9 35.05 25.5 35.3v-2.95q1.8-.25 3.4-1.05 1.6-.8 2.9-2.1ZM25.5 7.6q4.9.55 8.35 4 3.45 3.45 4 8.35H34.9q-.5-3.7-3.1-6.3-2.6-2.6-6.3-3.1Z'/%3E%3C/svg%3E")}.view360-controls-button.view360-controls-gyro-disabled{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='48' width='48'%3E%3Cpath fill='%23fff' d='M7 44q-1.2 0-2.1-.9Q4 42.2 4 41v-8.6h3V41h8.6v3ZM4 15.6V7q0-1.2.9-2.1Q5.8 4 7 4h8.6v3H7v8.6Zm18.5 22.25q-4.9-.55-8.35-4-3.45-3.45-4-8.35h2.95q.5 3.7 3.125 6.3 2.625 2.6 6.275 3.1ZM10.15 22.5q.55-4.9 4-8.35 3.45-3.45 8.35-4v2.95q-3.7.5-6.3 3.1-2.6 2.6-3.1 6.3Zm13.85 5q-1.45 0-2.475-1.025Q20.5 25.45 20.5 24q0-1.45 1.025-2.475Q22.55 20.5 24 20.5q1.45 0 2.475 1.025Q27.5 22.55 27.5 24q0 1.45-1.025 2.475Q25.45 27.5 24 27.5Zm1.5 10.35V34.9q3.7-.5 6.3-3.125 2.6-2.625 3.1-6.275h2.95q-.55 4.9-4 8.35-3.45 3.45-8.35 4Zm9.4-15.35q-.5-3.7-3.1-6.3-2.6-2.6-6.3-3.1v-2.95q4.9.55 8.35 4 3.45 3.45 4 8.35ZM32.4 44v-3H41v-8.6h3V41q0 1.2-.9 2.1-.9.9-2.1.9ZM41 15.6V7h-8.6V4H41q1.2 0 2.1.9.9.9.9 2.1v8.6Z'/%3E%3C/svg%3E")}.view360-controls-time{display:inline-block;vertical-align:top;white-space:nowrap;color:#fff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-weight:400;font-size:14px;z-index:1}.view360-controls-time:first-child{padding:0 16px}.view360-controls-progress{flex:1;width:100%;padding:0 16px;box-sizing:border-box}.view360-controls-progress:not(:first-child){padding-left:0}.view360-controls-bottom .view360-controls-progress{padding-bottom:20px}.view360-controls-volume{display:inline-flex;flex-direction:row;align-items:center;transition:width 250ms,background-color 250ms;overflow:hidden}.view360-controls-volume:not(:disabled).view360-controls-fixed,.view360-controls-volume:not(:disabled):hover{width:112px}.view360-controls-volume .view360-range{flex:1;height:100%;padding:0}.view360-controls-volume .view360-range .view360-range-track{width:calc(100% - 12px);transform:translateX(-4px)}.view360-controls-volume .view360-controls-button{margin:0;padding:0;width:24px;height:24px;flex-shrink:0}.view360-controls-volume:disabled{opacity:.5;pointer-events:none}.view360-controls-volume:disabled *{pointer-events:none}.view360-controls-pie{width:36px;height:36px;margin:6px;padding:0;border-radius:18px;opacity:.8;pointer-events:all;cursor:pointer;color:#fff;position:relative;transition:opacity 250ms}.view360-controls-pie>svg{position:absolute;top:0;left:0;width:100%;height:100%}.view360-controls-pie:hover{opacity:1}.view360-range{position:relative;cursor:pointer;pointer-events:all;display:flex;justify-content:center;align-items:center;touch-action:pan-y}.view360-range:hover .view360-range-thumb{opacity:1}.view360-range-track{width:100%;height:4px;border-radius:4px;position:relative;background-color:rgba(230,230,230,.4)}.view360-range-filler,.view360-range-load{position:absolute;left:0;top:0;width:0;height:100%;border-radius:4px}.view360-range-filler{background-color:#fff}.view360-range-load{background-color:#757575}.view360-range-thumb{width:13px;height:13px;position:absolute;top:-5px;left:-6.5px;border-radius:50%;background-color:#fff;box-sizing:border-box;transition:opacity 250ms;opacity:0}.view360-range-thumb.view360-controls-fixed{opacity:1}.view360-controls-unavailable{display:none!important}@media screen and (max-width:768px){.view360-controls-button{background-size:18px 18px;width:30px;height:30px;margin:4.5px;padding:6px;border-radius:15px}.view360-controls-volume .view360-controls-button{width:18px;height:18px}.view360-controls-volume:not(:disabled).view360-controls-fixed,.view360-controls-volume:not(:disabled):hover{width:84px}.view360-controls-pie{width:27px;height:27px;margin:4.5px;padding:0;border-radius:13.5px}}.view360-spinner{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;background-color:rgba(0,0,0,.15)}.view360-spinner-ring{top:0;left:0;padding:0;margin:0;width:64px;height:64px;box-sizing:content-box;background-color:transparent;border-style:solid;border-radius:50%;border-width:10px;border-color:#fff;border-bottom-color:transparent;animation:view360-spin-animation 1.2s linear infinite}@keyframes view360-spin-animation{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.view360-container.view360-vr-presenting{width:100vw;height:100vh;position:fixed;left:0;top:0;z-index:9999}.view360-hotspots{width:100%;height:100%;position:absolute;top:0;left:0;pointer-events:none}.view360-hotspot{pointer-events:none;visibility:hidden;position:absolute;top:0;left:0}.view360-hotspot-visible{visibility:visible;pointer-events:all} \ No newline at end of file diff --git a/src/static/view360/view360.pkgd.min.js b/src/static/view360/view360.pkgd.min.js new file mode 100644 index 0000000..30c20d3 --- /dev/null +++ b/src/static/view360/view360.pkgd.min.js @@ -0,0 +1,16 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).View360=e()}(this,(function(){"use strict";function t(t,e,i,s){return new(i||(i=Promise))((function(n,r){function o(t){try{h(s.next(t))}catch(t){r(t)}}function a(t){try{h(s.throw(t))}catch(t){r(t)}}function h(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(o,a)}h((s=s.apply(t,e||[])).next())}))} +/*! ***************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */function e(t){var e="function"==typeof Symbol&&Symbol.iterator,i=e&&t[e],s=0;if(i)return i.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&s>=t.length&&(t=void 0),{value:t&&t[s++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function i(t,e){var i="function"==typeof Symbol&&t[Symbol.iterator];if(!i)return t;var s,n,r=i.call(t),o=[];try{for(;(void 0===e||e-- >0)&&!(s=r.next()).done;)o.push(s.value)}catch(t){n={error:t}}finally{try{s&&!s.done&&(i=r.return)&&i.call(r)}finally{if(n)throw n.error}}return o}function s(){for(var t=[],e=0;e0&&(r=1/Math.sqrt(r)),t[0]=e[0]*r,t[1]=e[1]*r,t[2]=e[2]*r,t}function v(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function E(t,e,i){var s=e[0],n=e[1],r=e[2],o=i[0],a=i[1],h=i[2];return t[0]=n*h-r*a,t[1]=r*o-s*h,t[2]=s*a-n*o,t}function f(t,e,i){var s=e[0],n=e[1],r=e[2],o=i[3]*s+i[7]*n+i[11]*r+i[15];return o=o||1,t[0]=(i[0]*s+i[4]*n+i[8]*r+i[12])/o,t[1]=(i[1]*s+i[5]*n+i[9]*r+i[13])/o,t[2]=(i[2]*s+i[6]*n+i[10]*r+i[14])/o,t}function b(t,e,i){var s=i[0],n=i[1],r=i[2],o=i[3],a=e[0],h=e[1],l=e[2],c=n*l-r*h,u=r*a-s*l,_=s*h-n*a,d=n*_-r*u,m=r*c-s*_,p=s*u-n*c,g=2*o;return c*=g,u*=g,_*=g,d*=2,m*=2,p*=2,t[0]=a+c+d,t[1]=h+u+m,t[2]=l+_+p,t}function y(){var t=new l(4);return l!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t[3]=1,t}function T(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t}function R(t,e,i){var s=e[0],n=e[1],r=e[2],o=e[3],a=i[0],h=i[1],l=i[2],c=i[3];return t[0]=s*c+o*a+n*l-r*h,t[1]=n*c+o*h+r*a-s*l,t[2]=r*c+o*l+s*h-n*a,t[3]=o*c-s*a-n*h-r*l,t}function w(t,e,i){i*=.5;var s=e[0],n=e[1],r=e[2],o=e[3],a=Math.sin(i),h=Math.cos(i);return t[0]=s*h+o*a,t[1]=n*h+r*a,t[2]=r*h-n*a,t[3]=o*h-s*a,t}function C(t,e,i){i*=.5;var s=e[0],n=e[1],r=e[2],o=e[3],a=Math.sin(i),h=Math.cos(i);return t[0]=s*h-r*a,t[1]=n*h+o*a,t[2]=r*h+s*a,t[3]=o*h-n*a,t}function L(t,e,i){i*=.5;var s=e[0],n=e[1],r=e[2],o=e[3],a=Math.sin(i),h=Math.cos(i);return t[0]=s*h+n*a,t[1]=n*h-s*a,t[2]=r*h+o*a,t[3]=o*h-r*a,t}function x(t,e,i,s){var n,r,o,a,l,c=e[0],u=e[1],_=e[2],d=e[3],m=i[0],p=i[1],g=i[2],v=i[3];return(r=c*m+u*p+_*g+d*v)<0&&(r=-r,m=-m,p=-p,g=-g,v=-v),1-r>h?(n=Math.acos(r),o=Math.sin(n),a=Math.sin((1-s)*n)/o,l=Math.sin(s*n)/o):(a=1-s,l=s),t[0]=a*c+l*m,t[1]=a*u+l*p,t[2]=a*_+l*g,t[3]=a*d+l*v,t}d(),function(){var t,e=(t=new l(4),l!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[3]=0),t)}();var O,A=function(t){var e=new l(4);return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e},I=function(t,e,i,s){var n=new l(4);return n[0]=t,n[1]=e,n[2]=i,n[3]=s,n},S=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t},P=function(t,e,i,s,n){return t[0]=e,t[1]=i,t[2]=s,t[3]=n,t},M=function(t,e){var i=e[0],s=e[1],n=e[2],r=e[3],o=i*i+s*s+n*n+r*r;return o>0&&(o=1/Math.sqrt(o)),t[0]=i*o,t[1]=s*o,t[2]=n*o,t[3]=r*o,t},N=function(t,e){var i=t[0],s=t[1],n=t[2],r=t[3],o=e[0],a=e[1],l=e[2],c=e[3];return Math.abs(i-o)<=h*Math.max(1,Math.abs(i),Math.abs(o))&&Math.abs(s-a)<=h*Math.max(1,Math.abs(s),Math.abs(a))&&Math.abs(n-l)<=h*Math.max(1,Math.abs(n),Math.abs(l))&&Math.abs(r-c)<=h*Math.max(1,Math.abs(r),Math.abs(c))};d(),p(1,0,0),p(0,1,0),y(),y(),O=new l(9),l!=Float32Array&&(O[1]=0,O[2]=0,O[3]=0,O[5]=0,O[6]=0,O[7]=0),O[0]=1,O[4]=1,O[8]=1,function(){var t=function(){var t=new l(2);return l!=Float32Array&&(t[0]=0,t[1]=0),t}()}();class D extends Error{constructor(t,e){super(t),Object.setPrototypeOf(this,D.prototype),this.name="View360Error",this.code=e}}const U={WRONG_TYPE:0,WRONG_OPTION:1,ELEMENT_NOT_FOUND:2,CANVAS_NOT_FOUND:3,WEBGL_NOT_SUPPORTED:4,FAILED_CREATE_CONTEXT_2D:5,PROVIDE_PROJECTION_FIRST:6,FAILED_LINKING_PROGRAM:7,INSUFFICIENT_ARGS:8};var B=U,F={WRONG_TYPE:(t,e)=>`${typeof t} is not a ${e.map((t=>`"${t}"`)).join(" or ")}.`,WRONG_OPTION:(t,e)=>`Bad option: given "${t}" for option "${e}".`,ELEMENT_NOT_FOUND:t=>`Element with selector "${t}" not found.`,CANVAS_NOT_FOUND:"The canvas element was not found inside the given root element.",WEBGL_NOT_SUPPORTED:"WebGL is not supported on this browser.",FAILED_CREATE_CONTEXT_2D:"Failed to create canvas 2D context",PROVIDE_PROJECTION_FIRST:'"projection" should be provided before initialization.',FAILED_LINKING_PROGRAM:(t,e)=>`Failed linking WebGL program - "${t}\nShader compile Log: ${e}`,INSUFFICIENT_ARGS:(t,e)=>`Insufficient arguments: given "${t}" for "${e}".`};const z="mousedown",V="mousemove",k="mouseup",G="touchstart",H="touchmove",Y="touchend",W="wheel",X="resize",j="contextmenu",K="mouseenter",q="mouseleave",Z="keydown",$="keyup",J="click",Q="webglcontextcreationerror",tt="webglcontextlost",et="webglcontextrestored",it="deviceorientation",st="devicemotion",nt="orientationchange",rt="play",ot="pause",at="loadeddata",ht="volumechange",lt="timeupdate",ct="durationchange",ut="canplaythrough",_t="transitionend",dt="end",mt="div",pt="button";var gt;!function(t){t[t.LEFT=0]="LEFT",t[t.MIDDLE=1]="MIDDLE",t[t.RIGHT=2]="RIGHT"}(gt||(gt={}));const vt="grab",Et="grabbing",ft="",bt=["LEFT","UP","RIGHT","DOWN"];var yt;!function(t){t[t.LEFT=37]="LEFT",t[t.UP=38]="UP",t[t.RIGHT=39]="RIGHT",t[t.DOWN=40]="DOWN"}(yt||(yt={}));const Tt={LEFT:"ArrowLeft",UP:"ArrowUp",RIGHT:"ArrowRight",DOWN:"ArrowDown"},Rt=["requestFullscreen","webkitRequestFullscreen","webkitRequestFullScreen","webkitCancelFullScreen","mozRequestFullScreen","msRequestFullscreen"],wt=["fullscreenElement","webkitFullscreenElement","webkitCurrentFullScreenElement","mozFullScreenElement","msFullscreenElement"],Ct=["exitFullscreen","webkitExitFullscreen","webkitCancelFullScreen","mozCancelFullScreen","msExitFullscreen"],Lt=["fullscreenchange","webkitfullscreenchange","mozfullscreenchange","MSFullscreenChange"],xt={CONTAINER:"view360-container",CANVAS:"view360-canvas",CTX_LOST:"view360-ctx-lost",IN_VR:"view360-vr-presenting",HOTSPOT_CONTAINER:"view360-hotspots",HOTSPOT:"view360-hotspot",HOTSPOT_VISIBLE:"view360-hotspot-visible",HOTSPOT_FLIP_X:"view360-hotspot-flip-x",HOTSPOT_FLIP_Y:"view360-hotspot-flip-y"},Ot={READY:"ready",LOAD_START:"loadStart",LOAD:"load",PROJECTION_CHANGE:"projectionChange",RESIZE:"resize",BEFORE_RENDER:"beforeRender",RENDER:"render",INPUT_START:"inputStart",INPUT_END:"inputEnd",VIEW_CHANGE:"viewChange",STATIC_CLICK:"staticClick",VR_START:"vrStart",VR_END:"vrEnd"},At={LINEAR:t=>t,SINE_WAVE:t=>Math.sin(t*Math.PI*2),EASE_OUT_CUBIC:t=>1-Math.pow(1-t,3),EASE_OUT_BOUNCE:t=>{const e=7.5625,i=2.75;return t<1/i?e*t*t:t<2/i?e*(t-=1.5/i)*t+.75:t<2.5/i?e*(t-=2.25/i)*t+.9375:e*(t-=2.625/i)*t+.984375}};var It;const St="animationEnd",Pt="update",Mt="inputStart",Nt="change",Dt="inputEnd",Ut="enable",Bt="disable",Ft="staticClick",zt=Math.PI/180,Vt=180/Math.PI,kt=At.EASE_OUT_CUBIC,Gt=300,Ht={min:-1/0,max:1/0},Yt={min:-90,max:90},Wt={min:.6,max:10};var Xt;!function(t){t[t.ZERO=0]="ZERO",t[t.CW_90=1]="CW_90",t[t.CCW_90=2]="CCW_90",t[t.CW_180=3]="CW_180"}(Xt||(Xt={}));const jt="view360videotimechange",Kt="http://www.w3.org/2000/svg",qt="immersive-vr",Zt="local",$t=null!==(It=Number.EPSILON)&&void 0!==It?It:2220446049250313e-31,Jt=t=>"string"==typeof t,Qt=(t,e=mt)=>{const i=document.createElement(e);return i.classList.add(t),i},te=(t,e)=>{let i=null;if(Jt(t)){const s=(e||document).querySelector(t);if(!s)return null;i=s}else(s=t)&&s.nodeType===Node.ELEMENT_NODE&&(i=t);var s;return i},ee=(t,e,i)=>Math.max(Math.min(t,i),e),ie=(t,e,i)=>t*(1-i)+e*i,se=(t,e,i)=>{const s=Math.abs(i-e);if(ti){t=e+(t-i)%s}return t},ne=(t,e)=>{for(let i=0;i"object"==typeof t?t:{},oe=(t,e)=>2*Math.atan(Math.tan(.5*t)/e),ae=(t,e,i="RLUDFB")=>i.split("").map((t=>e.indexOf(t))).map((e=>t[e])),he=()=>{if(!document)return!1;for(const t of wt)if(document[t])return!0;return!1},le=()=>window.isSecureContext&&!!DeviceMotionEvent&&"requestPermission"in DeviceMotionEvent,ce=(t,e,i,s)=>{T(t);const n=ee(i,-89.99,89.99);return C(t,t,e*zt),w(t,t,n*zt),L(t,t,s*zt),t},ue=t=>{const e=t[0],i=t[1],s=t[2],n=t[3],r=e*e+i*i+s*s+n*n,o=e*n-i*s;let a,h;if(o>.499995*r)a=Math.PI/2,h=2*Math.atan2(i,e);else if(o<-.499995*r)a=-Math.PI/2,h=-2*Math.atan2(i,e);else{const e=p(0,0,1),i=p(0,1,0);b(e,e,t),b(i,i,t);const s=Math.sqrt(e[0]*e[0]+e[2]*e[2]);a=Math.atan2(-e[1],s),h=Math.atan2(e[0],e[2])}return{pitch:ee(a*Vt,-90,90),yaw:se(h*Vt,0,360)}};class _e{get val(){return this._val}get start(){return this._start}get end(){return this._end}get progress(){return this._progress}get activated(){return this._activated}get duration(){return this._duration}set duration(t){this._duration=t}get loop(){return this._loop}set loop(t){this._loop=t}get range(){return this._range}get easing(){return this._easing}set easing(t){this._easing=t}constructor({duration:t=300,loop:e=!1,range:i={min:0,max:1},easing:s=kt}={}){this._duration=t,this._loop=e,this._range=i,this._easing=s,this._activated=!1,this.reset(0)}update(t){if(!this._activated)return this._val=this._end,0;const e=this._start,i=this._end,s=this._duration,n=this._val,r=this._loop,o=this._progress+t/s;this._progress=r?se(o,0,1):ee(o,0,1);const a=this._easing(this._progress);return this._val=ie(e,i,a),!r&&this._progress>=1&&(this._activated=!1),this._val-n}reset(t){const e=this._range,i=ee(t,e.min,e.max);this._start=i,this._end=i,this._val=i,this._progress=0,this._activated=!1}add(t){const e=this._range;this._start=ee(this._start+t,e.min,e.max),this._end=ee(this._end+t,e.min,e.max),this._val=ee(this._val+t,e.min,e.max)}setNewEndByDelta(t){const e=this._range;this._start=this._val,this._end=ee(this._end+t,e.min,e.max),this._progress=0,this._activated=!0}setRange(t,e){this._start=ee(this._start,t,e),this._end=ee(this._end,t,e),this._range={min:t,max:e}}}class de{get duration(){return this._motion.duration}set duration(t){this._motion.duration=t}get easing(){return this._motion.easing}set easing(t){this._motion.easing=t}constructor(t,e,i,{duration:s=300,easing:n=kt}={}){this._camera=t,this._motion=new _e({duration:s,easing:n,range:{min:0,max:1}}),this._from=e,this._to=i,this._finishPromise=new Promise((t=>{this._finish=t})),this._motion.setNewEndByDelta(1)}getFinishPromise(){return this._finishPromise}update(t){const e=this._camera,i=this._from,s=this._to,n=this._motion;n.update(t);const r=n.val,o=y(),a=ie(i.zoom,s.zoom,r);x(o,i.rotation,s.rotation,r),e.rotate(o,a),r>=1&&this._finish()}}class me extends o{get aspect(){return this._aspect}get changed(){return this._changed}get yawRange(){return this._initialYawRange}set yawRange(t){this._initialYawRange=t}get pitchRange(){return this._initialPitchRange}set pitchRange(t){this._initialPitchRange=t}get zoomRange(){return this._initialZoomRange}set zoomRange(t){this._initialZoomRange=t}constructor({initialYaw:t,initialPitch:e,initialZoom:i,yawRange:s,pitchRange:n,zoomRange:r,fov:o}){super(),this.yaw=t,this.pitch=e,this.zoom=i,this.rollOffset=0,this.initialYaw=t,this.initialPitch=e,this.initialZoom=i,this.position=d(),this.animation=null,this._up=p(0,1,0),this._aspect=1,this._initialYawRange=s,this._initialPitchRange=n,this._initialZoomRange=r,this._yawRange=s,this._pitchRange=n,this._zoomRange=r,this.quaternion=y(),this._updateQuaternion(),this.viewMatrix=c(),this.projectionMatrix=c(),this.fov=o,this._maxRenderHeight=-1}destroy(){this.off()}resize(t,e){const i=this._aspect;this._aspect=t/e,this._aspect!==i&&this.updateMatrix()}lookAt({yaw:t=this.yaw,pitch:e=this.pitch,zoom:i=this.zoom}){const s=A(this.quaternion),n=this.zoom;this.yaw=se(t,0,360),this.pitch=ee(e,-90,90),this.zoom=i,this._updateQuaternion();const r=Math.abs(i-n);(!N(this.quaternion,s)||r>=10*$t)&&this.updateMatrix()}rotate(t,e=this.zoom){const i=M(y(),t),s=N(this.quaternion,i);S(this.quaternion,i);const n=this.zoom,{yaw:r,pitch:o}=ue(i);this.yaw=r,this.pitch=o,this.zoom=e;const a=Math.abs(e-n);(!s||a>=10*$t)&&this.updateMatrix()}animateTo({yaw:e=this.yaw,pitch:i=this.pitch,zoom:s=this.zoom,duration:n=0,easing:r=kt}={}){return t(this,void 0,void 0,(function*(){if(this.yaw===e&&this.pitch===i&&this.zoom===s)return;const t={rotation:A(this.quaternion),zoom:this.zoom},o={rotation:ce(y(),e,i,this.rollOffset),zoom:s},a=new de(this,t,o,{duration:n,easing:r}),h=a.getFinishPromise();return this.animation=a,h.then((()=>{this.animation=null,this.trigger(St,{animation:a})})),h}))}restrictYawRange(t,e){this._yawRange={min:t,max:e}}restrictPitchRange(t,e){this._pitchRange={min:t,max:e}}restrictZoomRange(t,e){this._zoomRange={min:t,max:e}}restrictRenderHeight(t){this._maxRenderHeight=t}resetRange(){this._yawRange=this._initialYawRange,this._pitchRange=this._initialPitchRange,this._zoomRange=this._initialZoomRange,this._maxRenderHeight=-1}getYawRange(t){const e=this._yawRange,i=this._maxRenderHeight;if(!e)return Ht;const s=.5*this.getHorizontalFov(t);let n=e.min,r=e.max;if(i>0){const t=oe(s*zt,this._aspect),o=.5*i,a=Math.tan(t),h=Math.sqrt((1+o*o)/(1+a*a)),l=Math.atan(Math.tan(s*zt)*h)*Vt;n=e.min+l,r=e.max-l}return n>r&&(n=0,r=0),{min:n,max:r}}getPitchRange(t){const e=this._pitchRange,i=this._maxRenderHeight;if(!e)return Yt;let s=e.min,n=e.max;if(i>0){const i=.5*this.getVerticalFov(t);s=e.min+i,n=e.max-i}return s>n&&(s=0,n=0),{min:Math.max(s,-90),max:Math.min(n,90)}}getZoomRange(){var t;const e=null!==(t=this._zoomRange)&&void 0!==t?t:Wt,i=this.getHorizontalFov(e.max),s=this.getHorizontalFov(e.min),n=this.getHorizontalFov(this.zoom);return{min:Math.max(i,1),max:Math.min(s,180),current:n}}getHorizontalFov(t=this.zoom){return this._getZoomedHorizontalFov(t)*Vt}getVerticalFov(t=this.zoom){const e=this._aspect,i=this._getZoomedHorizontalFov(t);return oe(i,e)*Vt}fovToZoom(t){const e=this.fov;return Math.tan(zt*e*.5)/Math.tan(zt*t*.5)}updateMatrix(){const t=this._up,e=this._aspect,i=this.viewMatrix,s=this.projectionMatrix,n=this.position,r=this.quaternion,o=d(),a=p(0,0,-1);b(a,a,r),b(o,t,r);const l=this._getZoomedHorizontalFov(),c=oe(l,e);!function(t,e,i,s){var n,r,o,a,l,c,u,_,d,m,p=e[0],g=e[1],v=e[2],E=s[0],f=s[1],b=s[2],y=i[0],T=i[1],R=i[2];Math.abs(p-y){const e=this._el;e&&t.button===gt.LEFT&&(t.preventDefault(),e.focus?e.focus():window.focus(),this._prevPos[0]=t.clientX,this._prevPos[1]=t.clientY,window.addEventListener(V,this._onMouseMove,!1),window.addEventListener(k,this._onMouseUp,!1),this.trigger(Mt,{srcEvent:t,isTouch:!1,isKeyboard:!1}))},this._onMouseMove=t=>{t.preventDefault();const e=t.clientX,i=t.clientY,s=this._prevPos,n=e-s[0],r=i-s[1];this.trigger(Nt,{delta:{x:n,y:r},isTouch:!1,isKeyboard:!1}),s[0]=e,s[1]=i},this._onMouseUp=()=>{this._prevPos[0]=0,this._prevPos[1]=0,window.removeEventListener(V,this._onMouseMove,!1),window.removeEventListener(k,this._onMouseUp,!1),this.trigger(Dt,{isTouch:!1,isKeyboard:!1,scrolling:!1})},this._el=null,this._prevPos=[0,0]}enable(t){this._el||(t.addEventListener(z,this._onMouseDown),this._el=t)}disable(){const t=this._el;t&&(t.removeEventListener(z,this._onMouseDown),window.removeEventListener(V,this._onMouseMove,!1),window.removeEventListener(k,this._onMouseUp,!1),this._el=null)}}class ge extends o{get scrollable(){return this._scrollable}set scrollable(t){this._scrollable=t}constructor(){super(),this._onTouchStart=t=>{if(t.touches.length>1||this._scrolling)return;const e=t.touches[0];this._isFirstTouch=!0,this._prevPos[0]=e.clientX,this._prevPos[1]=e.clientY,this.trigger(Mt,{srcEvent:t,isTouch:!0,isKeyboard:!1})},this._onTouchMove=t=>{if(t.touches.length>1||this._scrolling)return;const e=t.touches[0],i=this._scrollable,s=this._prevPos,n=e.clientX,r=e.clientY,o=n-s[0],a=r-s[1];if(this._isFirstTouch){if(i&&!he()&&Math.abs(a)>Math.abs(o))return void(this._scrolling=!0);this._isFirstTouch=!1}!1!==t.cancelable&&t.preventDefault(),this.trigger(Nt,{delta:{x:o,y:a},isTouch:!0,isKeyboard:!1}),s[0]=n,s[1]=r},this._onTouchEnd=t=>{if(0!==t.touches.length)return;const e=t.touches[0],i=this._prevPos;e?(i[0]=e.clientX,i[1]=e.clientY):(i[0]=0,i[1]=0,this.trigger(Dt,{isTouch:!0,isKeyboard:!1,scrolling:this._scrolling})),!1!==t.cancelable&&t.preventDefault(),this._scrolling=!1},this._el=null,this._prevPos=[0,0],this._isFirstTouch=!1,this._scrolling=!1,this._scrollable=!1}enable(t){this._el||(t.addEventListener(G,this._onTouchStart,{passive:!1}),t.addEventListener(H,this._onTouchMove,{passive:!1}),t.addEventListener(Y,this._onTouchEnd),this._el=t)}disable(){const t=this._el;t&&(t.removeEventListener(G,this._onTouchStart),t.removeEventListener(H,this._onTouchMove),t.removeEventListener(Y,this._onTouchEnd),this._el=null)}}class ve extends o{get active(){const t=this._pressed;return t.LEFT||t.UP||t.RIGHT||t.DOWN}constructor(){super(),this._onKeyDown=t=>{if(t.location!==KeyboardEvent.DOM_KEY_LOCATION_STANDARD)return;this._updateKeyPress(t,!0);const e=this._getPressedKeyCount();e<=0||(t.preventDefault(),1!==e||t.repeat||this.trigger(Mt,{srcEvent:t,isTouch:!1,isKeyboard:!0}))},this._onKeyUp=t=>{if(t.location!==KeyboardEvent.DOM_KEY_LOCATION_STANDARD)return;this._updateKeyPress(t,!1);this._getPressedKeyCount()>0||this.trigger(Dt,{isTouch:!1,isKeyboard:!0,scrolling:!1})},this._el=null,this._clearPressedKeys()}enable(t){this._el||(t.addEventListener(Z,this._onKeyDown),t.addEventListener($,this._onKeyUp),this._el=t,this._clearPressedKeys())}disable(){const t=this._el;t&&(t.removeEventListener(Z,this._onKeyDown),t.removeEventListener($,this._onKeyUp),this._el=null,this._clearPressedKeys())}update(){const t=this._getDeltaByPressedKeys();0===t.x&&0===t.y||this.trigger(Nt,{delta:t,isTouch:!1,isKeyboard:!0})}_clearPressedKeys(){this._pressed=bt.reduce(((t,e)=>Object.assign(Object.assign({},t),{[e]:!1})),{})}_updateKeyPress(t,e){const i=this._pressed,s=null!=t.keyCode?yt[t.keyCode]:Tt[t.key];s&&(i[s]=e)}_getPressedKeyCount(){return bt.filter((t=>this._pressed[t])).length}_getDeltaByPressedKeys(){const t=this._pressed;let e=0,i=0;return t.LEFT&&(e+=1),t.RIGHT&&(e-=1),t.UP&&(i+=1),t.DOWN&&(i-=1),{x:e,y:i}}}class Ee extends o{get enabled(){return this._enabled}get enableBlocked(){return this._enableBlocked}get animating(){return this._keyboardInput.active||this._xMotion.activated||this._yMotion.activated}get yaw(){return this._xMotion}get pitch(){return this._yMotion}get scrollable(){return this._touchInput.scrollable}set scrollable(t){this._touchInput.scrollable=t}get pointerScale(){return this._pointerScale}set pointerScale(t){this._pointerScale=t}get keyboardScale(){return this._keyboardScale}set keyboardScale(t){this._keyboardScale=t}get duration(){return this._duration}set duration(t){this._duration=t,this._xMotion.duration=t,this._yMotion.duration=t}get easing(){return this._easing}set easing(t){this._easing=t,this._xMotion.easing=t,this._yMotion.easing=t}get disablePitch(){return this._disablePitch}set disablePitch(t){this._disablePitch=t}get disableYaw(){return this._disableYaw}set disableYaw(t){this._disableYaw=t}get disableKeyboard(){return this._disableKeyboard}set disableKeyboard(t){this._disableKeyboard=t}constructor(t,e,{duration:i=300,easing:s=kt,pointerScale:n=[1,1],keyboardScale:r=[1,1],disablePitch:o=!1,disableYaw:a=!1,disableKeyboard:h=!1}={}){super(),this._onInputStart=t=>{this._changedWhileDragging=!1,this.trigger(Mt,Object.assign(Object.assign({},t),{inputType:"rotate"}))},this._onChange=t=>{const e=t.delta,i=1/this._zoomScale,s=this._screenScale,n=this._keyboardScale,r=this._pointerScale;let o;o=t.isKeyboard?[n[0]*i,n[1]*i]:[r[0]*s[0]*i,r[1]*s[1]*i];const a=e.x*o[0],h=e.y*o[1];this._xMotion.setNewEndByDelta(a),this._yMotion.setNewEndByDelta(h),this._changedWhileDragging=!0},this._onInputEnd=t=>{this.trigger(Dt,Object.assign(Object.assign({},t),{inputType:"rotate"})),this._changedWhileDragging||t.isKeyboard||t.scrolling||this.trigger(Ft,{isTouch:t.isTouch}),this._changedWhileDragging=!1},this._controlEl=t,this._pointerScale=n,this._keyboardScale=r,this._duration=i,this._easing=s,this._disablePitch=o,this._disableYaw=a,this._disableKeyboard=h,this._enableBlocked=e,this._mouseInput=new pe,this._touchInput=new ge,this._keyboardInput=new ve,this._xMotion=new _e({duration:i,range:Ht,easing:s}),this._yMotion=new _e({duration:i,range:Yt,easing:s}),this._screenScale=[1,1],this._zoomScale=1,this._enabled=!1,this._changedWhileDragging=!1,this._bindInputs()}destroy(){this.disable(),this._mouseInput.off(),this._touchInput.off(),this._keyboardInput.off(),this.off(),this._changedWhileDragging=!1}update(t){if(!this._enabled)return;const e=this._xMotion,i=this._yMotion,s=this._keyboardInput;this._disableKeyboard||s.update(),this._disablePitch||i.update(t),this._disableYaw||e.update(t)}updateRange(t,e){const i=t.getYawRange(e),s=t.getPitchRange(e);this._xMotion.setRange(i.min,i.max),this._yMotion.setRange(s.min,s.max)}setZoomScale(t){this._zoomScale=t}resize(t,e,i,s){const n=oe(t*zt,e)*Vt;this._screenScale[0]=t/i,this._screenScale[1]=n/s}enable(){if(this._enabled)return;const t=this._controlEl;this._mouseInput.enable(t),this._touchInput.enable(t),this._keyboardInput.enable(t),this._enabled=!0,this._enableBlocked=!1,this.trigger(Ut,{control:this,updateCursor:!0})}disable(){this._enabled&&(this._mouseInput.disable(),this._touchInput.disable(),this._keyboardInput.disable(),this._enabled=!1,this.trigger(Bt,{updateCursor:!0}))}sync(t){this.updateRange(t,t.zoom),this._xMotion.reset(t.yaw),this._yMotion.reset(t.pitch)}_bindInputs(){const t=this._mouseInput,e=this._touchInput,i=this._keyboardInput;t.on(Mt,this._onInputStart),t.on(Nt,this._onChange),t.on(Dt,this._onInputEnd),e.on(Mt,this._onInputStart),e.on(Nt,this._onChange),e.on(Dt,this._onInputEnd),i.on(Mt,this._onInputStart),i.on(Nt,this._onChange),i.on(Dt,this._onInputEnd)}}class fe extends o{get scrollable(){return this._scrollable}set scrollable(t){this._scrollable=t}constructor(){super(),this._onWheel=t=>{const e=this._scrollable;if(0===t.deltaY||e)return;t.preventDefault(),t.stopPropagation(),this._inputTimer<0?this.trigger(Mt,{srcEvent:t,isTouch:!1,isKeyboard:!1}):this._clearTimer();const i=this._baseScale*t.deltaY;this.trigger(Nt,{delta:i,isTouch:!1,isKeyboard:!1}),this._inputTimer=window.setTimeout((()=>{this.trigger(Dt,{isTouch:!1,isKeyboard:!1,scrolling:!1}),this._inputTimer=-1}),Gt)},this._el=null,this._baseScale=.04,this._scrollable=!1,this._inputTimer=-1}enable(t){this._el||(t.addEventListener(W,this._onWheel,{passive:!1,capture:!1}),this._el=t,this._clearTimer())}disable(){const t=this._el;t&&(t.removeEventListener(W,this._onWheel,!1),this._el=null,this._clearTimer())}_clearTimer(){window.clearTimeout(this._inputTimer),this._inputTimer=-1}}class be extends o{constructor(){super(),this._onTouchMove=t=>{const e=t.touches;if(2!==e.length)return;if(!t.cancelable)return;t.preventDefault(),t.stopPropagation();const i=this._prevDistance,s=[e[0].pageX-e[1].pageX,e[0].pageY-e[1].pageY],n=Math.sqrt(s[0]*s[0]+s[1]*s[1])*this._baseScale,r=this._isFirstTouch?0:n-i;this._isFirstTouch&&this.trigger(Mt,{srcEvent:t,isTouch:!0,isKeyboard:!1}),this._prevDistance=n,this._isFirstTouch=!1,this.trigger(Nt,{delta:r,isTouch:!0,isKeyboard:!1})},this._onTouchEnd=t=>{0===t.touches.length&&(this._isFirstTouch||this.trigger(Dt,{isTouch:!0,isKeyboard:!1,scrolling:!1}),this._prevDistance=-1,this._isFirstTouch=!0)},this._el=null,this._baseScale=-.2,this._prevDistance=-1,this._isFirstTouch=!0}enable(t){this._el||(t.addEventListener(H,this._onTouchMove,{passive:!1,capture:!1}),t.addEventListener(Y,this._onTouchEnd),this._el=t,this._prevDistance=-1,this._isFirstTouch=!0)}disable(){const t=this._el;t&&(t.removeEventListener(H,this._onTouchMove,!1),t.removeEventListener(Y,this._onTouchEnd),this._el=null)}}class ye extends o{get enabled(){return this._enabled}get enableBlocked(){return this._enableBlocked}get animating(){return this._motion.activated}get zoom(){return this._motion.val}get scrollable(){return this._wheelInput.scrollable}set scrollable(t){this._wheelInput.scrollable=t}get range(){return this._motion.range}get scale(){return this._scale}set scale(t){this._scale=t}get duration(){return this._motion.duration}get easing(){return this._motion.easing}constructor(t,e,{scale:i=1,duration:s=300,easing:n=kt}={}){super(),this._onInputStart=t=>{this.trigger(Mt,Object.assign(Object.assign({},t),{inputType:"zoom"}))},this._onChange=({delta:t})=>{const e=t*this._scale;this._motion.setNewEndByDelta(e)},this._onInputEnd=t=>{this.trigger(Dt,Object.assign(Object.assign({},t),{inputType:"zoom"}))},this._scale=i,this._controlEl=t,this._enableBlocked=e,this._wheelInput=new fe,this._pinchInput=new be,this._motion=new _e({duration:s,easing:n,range:Ht}),this._enabled=!1,this._bindInputs()}destroy(){this.disable(),this._wheelInput.off(),this._pinchInput.off(),this.off()}update(t){if(!this._enabled)return;this._motion.update(t)}enable(){if(this._enabled)return;const t=this._controlEl;this._wheelInput.enable(t),this._pinchInput.enable(t),this._enabled=!0,this._enableBlocked=!1,this.trigger(Ut,{control:this,updateCursor:!1})}disable(){this._enabled&&(this._wheelInput.disable(),this._pinchInput.disable(),this._enabled=!1,this.trigger(Bt,{updateCursor:!1}))}sync(t){const e=this._motion,i=t.getZoomRange();e.setRange(i.min,i.max),e.reset(i.current)}_bindInputs(){const t=this._wheelInput,e=this._pinchInput;t.on(Mt,this._onInputStart),t.on(Nt,this._onChange),t.on(Dt,this._onInputEnd),e.on(Mt,this._onInputStart),e.on(Nt,this._onChange),e.on(Dt,this._onInputEnd)}}const Te={PITCH_DELTA:1,YAW_DELTA_BY_ROLL:2,YAW_DELTA_BY_YAW:3};Te[Te.PITCH_DELTA]={targetAxis:[0,1,0],meshPoint:[0,0,1]},Te[Te.YAW_DELTA_BY_ROLL]={targetAxis:[0,1,0],meshPoint:[1,0,0]},Te[Te.YAW_DELTA_BY_YAW]={targetAxis:[1,0,0],meshPoint:[0,0,1]};class Re extends o{get enabled(){return this._enabled}get orientationUpdated(){return this._orientationUpdated}get ignoreRoll(){return this._ignoreRoll}set ignoreRoll(t){this._ignoreRoll=t}constructor(){super(),this._onDeviceOrientation=t=>{const e=this._orientation,{alpha:i,beta:s,gamma:n}=t;null!=i&&null!=s&&null!=n&&(e.alpha=i,e.beta=s,e.gamma=n,this._orientationUpdated=!0,this._needsCalibrate&&(this._needsCalibrate=!1,this._calibrateSensor()))},this._updateScreenOrientation=()=>{window.screen&&window.screen.orientation&&void 0!==window.screen.orientation.angle?this._screenOrientation=screen.orientation.angle:void 0!==window.orientation?this._screenOrientation=window.orientation>=0?window.orientation:360+window.orientation:this._screenOrientation=0},this.quaternion=y(),this._orientation={alpha:0,beta:90,gamma:0},this._yawOrigin=0,this._yawOffset=0,this._orientationUpdated=!1,this._screenOrientation=0,this._needsCalibrate=!0,this._enabled=!1}enable(){this._enabled||(window.addEventListener(it,this._onDeviceOrientation),window.addEventListener(nt,this._updateScreenOrientation),this._updateScreenOrientation(),this._orientationUpdated=!1,this._needsCalibrate=!0,this._enabled=!0)}disable(){this._enabled&&(window.removeEventListener(it,this._onDeviceOrientation),window.removeEventListener(nt,this._updateScreenOrientation),this._enabled=!1)}update(){this._updateRotation(),this._orientationUpdated=!1}collectDelta(){if(!this._orientationUpdated)return{pitch:0,yaw:0};const t=A(this.quaternion);return this._updateRotation(),this._orientationUpdated=!1,this._toEulerDelta(t,this.quaternion)}setInitialRotation(t){this._yawOrigin=t}_calibrateSensor(){const t=this._yawOrigin,e=this.quaternion;this._yawOffset=0,this._updateRotation();const{yaw:i}=ue(e);this._yawOffset=i-t,this._updateRotation(),this._needsCalibrate=!1}_updateRotation(){const t=this.quaternion,{alpha:e,beta:i,gamma:s}=this._orientation;T(t),C(t,t,(e-this._yawOffset)*zt),w(t,t,i*zt),L(t,t,-s*zt);const n=y(),r=.5*-this._screenOrientation*zt,o=I(-Math.sqrt(.5),0,0,Math.sqrt(.5));P(n,0,Math.sin(r),0,Math.cos(r)),R(t,t,n),R(t,t,o),M(t,t)}_toEulerDelta(t,e){return{yaw:this._getDeltaYaw(t,e),pitch:this._getDeltaPitch(t,e)}}_getDeltaYaw(t,e){const i=this._getRotationDelta(t,e,Te.YAW_DELTA_BY_YAW);return this._getRotationDelta(t,e,Te.YAW_DELTA_BY_ROLL)*Math.sin(this._extractPitchFromQuat(e))+i}_getDeltaPitch(t,e){return this._getRotationDelta(t,e,Te.PITCH_DELTA)}_getRotationDelta(t,e,i){const s=p(Te[i].targetAxis[0],Te[i].targetAxis[1],Te[i].targetAxis[2]),n=Te[i].meshPoint,r=A(t),o=A(e);M(r,r),M(o,o);let a=p(0,0,1),h=p(0,0,1);b(a,a,r),b(h,h,o),b(s,s,o);const l=v(s,E(d(),a,h))>0?1:-1,c=p(n[0],n[1],n[2]);let u;u=i!==Te.YAW_DELTA_BY_YAW?p(0,l,0):p(l,0,0),b(c,c,o),b(u,u,o);const _=c,f=u,y=d();E(y,_,f),g(y,y);const T=y[0],R=y[1],w=y[2];h=p(n[0],n[1],n[2]),b(h,h,o),a=p(n[0],n[1],n[2]),b(a,a,r);let C=Math.abs(a[0]*T+a[1]*R+a[2]*w);const L=d();!function(t,e,i){t[0]=e[0]-i[0],t[1]=e[1]-i[1],t[2]=e[2]-i[2]}(L,a,function(t,e,i){return t[0]=e[0]*i,t[1]=e[1]*i,t[2]=e[2]*i,t}(d(),y,C));let x=(L[0]*h[0]+L[1]*h[1]+L[2]*h[2])/(m(L)*m(h));x>1&&(x=1);const O=Math.acos(x),I=E(d(),h,L);let S;C=T*I[0]+R*I[1]+w*I[2],S=i!==Te.YAW_DELTA_BY_YAW?C>0?1:-1:C<0?1:-1;return O*S*l*Vt}_extractPitchFromQuat(t){const e=p(0,0,1);return b(e,e,t),-1*Math.atan2(e[1],Math.sqrt(Math.pow(e[0],2)+Math.pow(e[2],2)))}}class we extends o{get enabled(){return this._input.enabled}get enableBlocked(){return this._enableBlocked}get animating(){return this._input.enabled&&this._input.orientationUpdated}get ignoreRoll(){return this._ignoreRoll}set ignoreRoll(t){this._ignoreRoll=t}static isAvailable(){return t(this,void 0,void 0,(function*(){if(!DeviceMotionEvent)return!1;let t;return Promise.race([new Promise((e=>{t=t=>{e(t.rotationRate&&null!=t.rotationRate.alpha)},window.addEventListener(st,t)})),new Promise((t=>{setTimeout((()=>t(!1)),1e3)}))]).then((e=>(window.removeEventListener(st,t),e)))}))}static requestSensorPermission(){return t(this,void 0,void 0,(function*(){return!le()||DeviceMotionEvent.requestPermission().then((t=>"granted"===t)).catch((()=>!1))}))}constructor(t,{ignoreRoll:e=!0}={}){super(),this._enableBlocked=t,this._ignoreRoll=e,this._input=new Re}destroy(){this.disable(),this._input.off(),this.off()}update(t,e,i,s){this._ignoreRoll?this._updateYawPitch(t,e,i,s):this._updateQuaternion(t,s)}enable(){this._input.enabled||(this._input.enable(),this._enableBlocked=!1,this.trigger(Ut,{control:this,updateCursor:!1}))}disable(){this._input.enabled&&(this._input.disable(),this.trigger(Bt,{updateCursor:!1}))}sync(){}_updateYawPitch(t,e,i,s){const n=this._input;if(!n.enabled)return;const{yaw:r,pitch:o}=n.collectDelta();e.add(r),i.add(o),t.lookAt({yaw:e.val,pitch:i.val,zoom:s})}_updateQuaternion(t,e){const i=this._input;i.enabled&&(i.update(),t.rotate(i.quaternion,e))}}class Ce{get useGrabCursor(){return this._useGrabCursor}set useGrabCursor(t){t!==this._useGrabCursor&&(this._useGrabCursor=t,t&&this._enabled?this._setCursor(vt):t||this._setCursor(ft))}get disableContextMenu(){return this._disableContextMenu}set disableContextMenu(t){t!==this._disableContextMenu&&(this._disableContextMenu=t,t&&this._enabled?this._blockContextMenu():t||this._restoreContextMenu())}get scrollable(){return this._rotateControl.scrollable}set scrollable(t){this._rotateControl.scrollable=t}get wheelScrollable(){return this._zoomControl.scrollable}set wheelScrollable(t){this._zoomControl.scrollable=t}get ignoreZoomScale(){return this._ignoreZoomScale}set ignoreZoomScale(t){this._ignoreZoomScale=t}get enabled(){return this._enabled}get rotate(){return this._rotateControl}get zoom(){return this._zoomControl}get gyro(){return this._gyroControl}get animating(){return this._rotateControl.animating||this._zoomControl.animating||this._gyroControl.animating}constructor(t,e,{useGrabCursor:i,scrollable:s,wheelScrollable:n,disableContextMenu:r,rotate:o,zoom:a,gyro:h}){this._preventContextMenu=t=>{t.preventDefault()},this._onInputStart=t=>{this._useGrabCursor&&!t.isKeyboard&&this._setCursor(Et)},this._onInputEnd=t=>{this._useGrabCursor&&!t.isKeyboard&&this._setCursor(vt)},this._onEnable=({control:t,updateCursor:e})=>{e&&this._useGrabCursor&&this._setCursor(vt),t.sync(this._camera)},this._onDisable=({updateCursor:t})=>{t&&this._setCursor(ft)},this._onCameraAnimationEnd=({animation:t})=>{t.getFinishPromise().then((()=>{this.sync()}))},this._useGrabCursor=i,this._disableContextMenu=r,this._camera=e,this._controlEl=t,this._ignoreZoomScale=!1,this._enabled=!1,this._rotateControl=new Ee(t,!o,re(o)),this._zoomControl=new ye(t,!a,re(a)),this._gyroControl=new we(!h,re(h)),this._rotateControl.scrollable=s,this._zoomControl.scrollable=n,this._bindEvents()}destroy(){this.disable(),this._rotateControl.destroy(),this._zoomControl.destroy(),this._setCursor(ft)}resize(t,e){const i=this._camera;this._rotateControl.resize(i.fov,i.aspect,t,e)}enable(){return t(this,void 0,void 0,(function*(){this._enabled||(this._rotateControl.enableBlocked||this._rotateControl.enable(),this._zoomControl.enableBlocked||this._zoomControl.enable(),this._gyroControl.enableBlocked||(yield we.isAvailable())&&this._gyroControl.enable(),this.sync(),this._disableContextMenu&&this._blockContextMenu(),this._enabled=!0)}))}disable(){this._enabled&&(this._rotateControl.disable(),this._zoomControl.disable(),this._gyroControl.disable(),this._restoreContextMenu(),this._enabled=!1)}update(t){const e=this._camera,i=this._rotateControl,s=this._zoomControl,n=this._gyroControl;s.update(t);const r=(o=e.fov,a=s.zoom,Math.tan(zt*o*.5)/Math.tan(zt*a*.5));var o,a;const h=this._ignoreZoomScale?1:Math.max(r,1);i.setZoomScale(h),i.updateRange(e,r),i.update(t);const l=i.yaw,c=i.pitch;n.enabled?n.update(e,l,c,r):e.lookAt({yaw:l.val,pitch:c.val,zoom:r})}sync(){const t=this._camera;this._zoomControl.sync(t),this._rotateControl.sync(t)}_blockContextMenu(){this._controlEl.addEventListener(j,this._preventContextMenu)}_restoreContextMenu(){this._controlEl.removeEventListener(j,this._preventContextMenu)}_setCursor(t){if(!this._useGrabCursor&&t!==ft)return;this._controlEl.style.cursor=t}_bindEvents(){const t=this._rotateControl,e=this._zoomControl;t.on(Mt,this._onInputStart),t.on(Dt,this._onInputEnd),t.on(Ut,this._onEnable),t.on(Bt,this._onDisable),e.on(Ut,this._onEnable),e.on(Bt,this._onDisable),this._camera.on(St,this._onCameraAnimationEnd)}}var Le=function(t,e){return Le=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i])},Le(t,e)};function xe(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function i(){this.constructor=t}Le(t,e),t.prototype=null===e?Object.create(e):(i.prototype=e.prototype,new i)}var Oe=function(){return Oe=Object.assign||function(t){for(var e,i=1,s=arguments.length;i0},i.clear=function(){this.isPreReadyOver=!1,this.totalCount=0,this.preReadyCount=0,this.readyCount=0,this.totalErrorCount=0,this.elementInfos.forEach((function(t){t.loader&&t.loader.destroy()})),this.elementInfos=[]},i.destroy=function(){this.clear(),this.off()},i.getLoader=function(t,e){var i=this,s=t.tagName.toLowerCase(),n=this.options.loaders,r=e.prefix,o=Object.keys(n);if(n[s])return new n[s](t,e);var a=new Ke(t,e),h=Be(t.querySelectorAll(o.join(", ")));a.setHasLoading(h.some((function(t){return Fe(t,r)})));var l=!1,c=this.clone().on("error",(function(t){a.onError(t.target)})).on("ready",(function(){a.onReady(l)}));return a.on("requestChildren",(function(){var e=Ge(t,o,i.options.prefix);c.check(e).on("preReady",(function(t){(l=t.isReady)||a.onPreReady()}))})).on("reqeustReadyChildren",(function(){c.check(h)})).on("requestDestroy",(function(){c.destroy()})),a},i.clone=function(){return new e(Oe({},this.options))},i.checkPreReady=function(t){return this.elementInfos[t].isPreReady=!0,++this.preReadyCount,!(this.preReadyCount=1)&&(t.error?(this.onAlreadyError(t),!1):(this.addEvents(),!0))},e.EVENTS=["loadedmetadata","error"],e}(je),Je=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Oe({loaders:{img:Ze,video:$e}},e))||this}return xe(e,t),e}(qe);class Qe{constructor({width:t,height:e,flipY:i}){this.width=t,this.height=e,this.flipY=i,this.wrapS=WebGLRenderingContext.CLAMP_TO_EDGE,this.wrapT=WebGLRenderingContext.CLAMP_TO_EDGE}destroy(){}isVideo(){return!1}isCube(){return!1}}class ti extends Qe{constructor({source:t,width:e,height:i,flipY:s}){super({width:e,height:i,flipY:s}),this.source=t}}class ei extends ti{destroy(){const t=this.source;t.pause(),t.removeAttribute("src"),t.load()}isVideo(){return!0}isPaused(){const t=this.source;return t.paused||t.ended||t.readyState<=2}hasAudio(){const t=this.source;return t.audioTracks?t.audioTracks.length>0:null!=t.webkitAudioDecodedByteCount?t.webkitAudioDecodedByteCount>0:null==t.mozHasAudio||t.mozHasAudio}}class ii extends Qe{constructor({sources:t,width:e,height:i,flipY:s}){super({width:e,height:i,flipY:s}),this.sources=t}isCube(){return!0}}class si{constructor(){this._loadChecker=new Je}load(e,i){return t(this,void 0,void 0,(function*(){if(i)return this.loadVideo(e,re(i));if(Array.isArray(e)&&e.length>1)return this.loadCubeImage(e);{const t=Array.isArray(e)?e[0]:e;return this.loadImage(t)}}))}loadImage(e){return t(this,void 0,void 0,(function*(){const t=this._toImageArray(e);return this._load(t,(e=>{const i=t[0];e(new ti({source:i,width:i.naturalWidth,height:i.naturalHeight,flipY:!0}))}))}))}loadCubeImage(e){return t(this,void 0,void 0,(function*(){const t=this._toImageArray(e);return this._load(t,(e=>{e(new ii({sources:t,width:t[0].naturalWidth,height:t[0].naturalHeight,flipY:!1}))}))}))}loadVideo(e,i){return t(this,void 0,void 0,(function*(){const t=Object.assign({autoplay:!0,muted:!0,loop:!1,volume:1},i),s=this._toVideoElement(e,t);return this._load([s],(e=>{const{autoplay:i,muted:n}=t;s.currentTime=0,i&&n&&s.play().catch((()=>{})),e(new ei({source:s,width:s.videoWidth,height:s.videoHeight,flipY:!0}))}))}))}_load(t,e){const i=this._loadChecker;return new Promise(((s,n)=>{i.once("ready",(t=>{t.errorCount>0||e(s)})),i.once("error",n),i.check(t)}))}_toImageArray(t){return(Array.isArray(t)?t:[t]).map((t=>{if(Jt(t)){const e=new Image;return e.crossOrigin="anonymous",e.src=t,e}return t}))}_toVideoElement(t,{muted:e,loop:i,volume:s}){if(t instanceof HTMLVideoElement)return t;const n=document.createElement("video");n.crossOrigin="anonymous",n.playsInline=!0,n.setAttribute("webkit-playsinline",""),n.muted=e,n.volume=s,n.loop=i,Array.isArray(t)?t.forEach((t=>this._appendSourceElement(n,t))):this._appendSourceElement(n,t);return n.querySelectorAll("source").length>0&&n.readyState<1&&n.load(),n}_appendSourceElement(t,e){if(e instanceof HTMLSourceElement)return e;const i=document.createElement("source");i.src=e,t.appendChild(i)}}class ni{constructor(t,e=window){this.maxDeltaTime=t,this._context=e,this._rafId=-1,this._rafTimer=-1,this._lastUpdateTime=-1}start(t){const e=this._context;if(!e||!t)return;if(this._rafId>=0||this._rafTimer>=0)return;const i=(s,n)=>{const r=Date.now(),o=Math.min(r-this._lastUpdateTime,1e3*this.maxDeltaTime);t(o,n),this._lastUpdateTime=r,this._rafId=e.requestAnimationFrame(i)};this._lastUpdateTime=Date.now(),this._rafId=e.requestAnimationFrame(i)}stop(){this._rafId>=0&&this._context.cancelAnimationFrame(this._rafId),this._rafTimer>=0&&clearTimeout(this._rafTimer),this._rafId=-1,this._rafTimer=-1}changeContext(t){this.stop(),this._context=t}}class ri{get useResizeObserver(){return this._useResizeObserver}get enabled(){return this._enabled}constructor(t,e){this._skipFirstResize=(()=>{let t=!0;return()=>{t?t=!1:this._onResize()}})(),this._useResizeObserver=t,this._enabled=!1,this._resizeObserver=null,this._onResize=e}enable(t){if(this._enabled&&this.disable(),this._useResizeObserver&&window.ResizeObserver){const e=t.getBoundingClientRect(),i=0!==e.width||0!==e.height,s=new ResizeObserver(i?this._skipFirstResize:this._onResize);s.observe(t),this._resizeObserver=s}else window.addEventListener(X,this._onResize);return this._enabled=!0,this}disable(){if(!this._enabled)return this;const t=this._resizeObserver;return t?(t.disconnect(),this._resizeObserver=null):window.removeEventListener(X,this._onResize),this._enabled=!1,this}}class oi{get enabled(){return this._enabled}get enableBlocked(){return this._enableBlocked}get playing(){return this._enabled&&!this._interrupted}get delay(){return this._delay}set delay(t){this._delay=t}get delayOnMouseLeave(){return this._delayOnMouseLeave}set delayOnMouseLeave(t){this._delayOnMouseLeave=t}get speed(){return this._speed}set speed(t){this._speed=t}get pauseOnHover(){return this._pauseOnHover}set pauseOnHover(t){this._pauseOnHover=t}get canInterrupt(){return this._canInterrupt}set canInterrupt(t){this._canInterrupt=t}get disableOnInterrupt(){return this._disableOnInterrupt}set disableOnInterrupt(t){this._disableOnInterrupt=t}constructor(t,e,i){this._onInputStart=()=>{this._canInterrupt&&(this._interrupted=!0,this._clearTimeout())},this._onInputEnd=()=>{this._setUninterruptedAfterDelay(this._delay)},this._onGyroEnable=()=>{this.disable()},this._onMouseEnter=()=>{this._pauseOnHover&&(this._interrupted=!0,this._hovering=!0)},this._onMouseLeave=()=>{this._pauseOnHover&&(this._hovering=!1,this._setUninterruptedAfterDelay(this._delayOnMouseLeave))},this._camera=t.camera,this._control=t.control,this._element=e,this._enabled=!1,this._interrupted=!1,this._interruptionTimer=-1,this._hovering=!1;const{delay:s=2e3,delayOnMouseLeave:n=0,speed:r=1,pauseOnHover:o=!1,canInterrupt:a=!0,disableOnInterrupt:h=!1}=re(i);this._enableBlocked=!i,this._delay=s,this._delayOnMouseLeave=n,this._speed=r,this._pauseOnHover=o,this._canInterrupt=a,this._disableOnInterrupt=h}destroy(){this.disable()}update(t){if(!this._enabled)return;if(this._interrupted)return void(this._disableOnInterrupt&&this.disable());const e=this._camera,i=-this._speed*t/100;e.yaw=se(e.yaw+i,0,360)}enable(){const t=this._control,e=this._element;this._enabled||t.gyro.enabled||(t.rotate.on(Mt,this._onInputStart),t.rotate.on(Dt,this._onInputEnd),t.zoom.on(Mt,this._onInputStart),t.zoom.on(Dt,this._onInputEnd),t.gyro.on(Ut,this._onGyroEnable),e.addEventListener(K,this._onMouseEnter,!1),e.addEventListener(q,this._onMouseLeave,!1),this._enabled=!0,this._enableBlocked=!1)}enableAfterDelay(){this.enable(),this._interrupted=!0,this._setUninterruptedAfterDelay(this._delay)}disable(){if(!this._enabled)return;const t=this._control,e=this._element;t.rotate.off(Mt,this._onInputStart),t.rotate.off(Dt,this._onInputEnd),t.zoom.off(Mt,this._onInputStart),t.zoom.off(Dt,this._onInputEnd),t.gyro.off(Ut,this._onGyroEnable),e.removeEventListener(K,this._onMouseEnter,!1),e.removeEventListener(q,this._onMouseLeave,!1),this._enabled=!1,this._interrupted=!1,this._hovering=!1,this._clearTimeout()}_setUninterruptedAfterDelay(t){this._hovering||(this._clearTimeout(),t>0?this._interruptionTimer=window.setTimeout((()=>{this._interrupted=!1,this._interruptionTimer=-1}),t):(this._interrupted=!1,this._interruptionTimer=-1))}_clearTimeout(){this._interruptionTimer>=0&&(window.clearTimeout(this._interruptionTimer),this._interruptionTimer=-1)}}class ai extends o{constructor(t,e={}){super(),this.destroy=()=>{this.exit(),this.off()},this._onSessionEnd=()=>{this.exit(),this.trigger(Ot.VR_END)},this._xrSession=null,this._xrRefSpace=null,this._ctx=t,this._options=e}isAvailable(){return t(this,void 0,void 0,(function*(){const t=window.navigator.xr;return!!t&&t.isSessionSupported(qt).then((t=>t)).catch((()=>!1))}))}enter(){return t(this,void 0,void 0,(function*(){const t=this._ctx,e=window.navigator.xr;if(!e)return;yield we.requestSensorPermission();const i=Object.assign({requiredFeatures:[Zt]},this._options);yield t.makeXRCompatible();const s=yield e.requestSession(qt,i);t.bindXRLayer(s);const n=yield s.requestReferenceSpace(Zt);this._setSession(s,n),this.trigger(Ot.VR_START,{session:s})}))}exit(){const t=this._xrSession;t&&t.end().catch((()=>{})),this._xrSession=null,this._xrRefSpace=null}canRender(t){const e=this._xrRefSpace;if(!e)return!1;return!!t.getViewerPose(e)}getEyeParams(t){const e=t.session,i=t.getViewerPose(this._xrRefSpace);if(!i)return null;const s=e.renderState.baseLayer;return s?i.views.map((t=>({viewport:s.getViewport(t),vMatrix:t.transform.inverse.matrix,pMatrix:t.projectionMatrix}))):null}_setSession(t,e){this._xrSession=t,this._xrRefSpace=e,t.addEventListener(dt,this._onSessionEnd)}}class hi{constructor(t,e){this.element=t,this.position=e}}class li{constructor(t,e,{zoom:i=!1}){this._containerEl=te(`.${xt.HOTSPOT_CONTAINER}`,t),this._renderer=e,this._hotspots=[],this._zoom=i}refresh(){const t=this._containerEl;if(!t)return;const e=[].slice.apply(t.querySelectorAll(`.${xt.HOTSPOT}`));this._hotspots=e.map((t=>this._parseHotspot(t)))}render(t){const e=this._hotspots,i=.5*this._renderer.width,s=.5*this._renderer.height,n=t.zoom,r="translate(-50%, -50%)",o=this._zoom?`scale(${n})`:"";e.forEach((e=>{const n=e.position,a=d();if(function(t,e){t[0]=e[0],t[1]=e[1],t[2]=e[2]}(a,n),f(a,a,t.viewMatrix),f(a,a,t.projectionMatrix),a[2]>1||a[2]<0)return void e.element.classList.remove(xt.HOTSPOT_VISIBLE);const h=function(t,e){var i=new l(2);return i[0]=t,i[1]=e,i}(a[0]*i+i,-a[1]*s+s);e.element.classList.add(xt.HOTSPOT_VISIBLE),e.element.style.transform=[r,`translate(${h[0]}px, ${h[1]}px)`,o].join(" ")}))}_parseHotspot(t){const e=t.dataset.yaw,i=t.dataset.pitch,s=t.dataset.position;if(e||i){const s=e?parseFloat(e):0,n=i?parseFloat(i):0,r=this._yawPitchToVec3(s,n);return new hi(t,r)}if(s){const e=s.split(" ").map((t=>parseFloat(t)));if(e.length<3)throw new D(F.INSUFFICIENT_ARGS(s,'hotspot attribute "data-position"'),B.INSUFFICIENT_ARGS);return new hi(t,p(e[0],e[1],e[2]))}{const e=p(0,0,-1);return new hi(t,e)}}_yawPitchToVec3(t,e){const i=t*zt,s=e*zt,n=d();return n[1]=Math.sin(s),n[2]=Math.cos(s),n[0]=n[2]*Math.sin(-i),n[2]=-n[2]*Math.cos(-i),n}}class ci{get count(){return this.geometry.indicies.count}constructor(t,e,i){this.obj=t,this.geometry=e,this.buffers=i}}class ui{get canvas(){return this._canvas}get maxTextureSize(){return this._maxTextureSize}get isWebGL2(){return this._isWebGL2}get supportVAO(){return this._isWebGL2||!!this._extensions.vao}get lost(){return this._contextLost}get debug(){return this._debug}constructor(t,e){this._onContextLost=()=>{this._canvas.classList.add(xt.CTX_LOST),this._contextLost=!0},this._onContextRestore=()=>{this._canvas.classList.remove(xt.CTX_LOST),this._contextLost=!1},this._canvas=t,this._contextLost=!1,this._debug=e,this._extensions={vao:null,loseContext:null}}init(){const t=this._canvas,{gl:e,isWebGL2:i}=this._getContext(t);this._gl=e,this._maxTextureSize=e.getParameter(e.MAX_TEXTURE_SIZE),this._isWebGL2=i,this._isWebGL2||(this._extensions.vao=e.getExtension("OES_vertex_array_object")),this._extensions.loseContext=e.getExtension("WEBGL_lose_context"),t.addEventListener(tt,this._onContextLost),t.addEventListener(et,this._onContextRestore)}destroy(){const t=this._gl,e=this._canvas;t&&(t.bindBuffer(t.ARRAY_BUFFER,null),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,null)),e.removeEventListener(tt,this._onContextLost),e.removeEventListener(et,this._onContextRestore)}forceLoseContext(){const t=this._extensions.loseContext;t&&t.loseContext()}forceRestoreContext(){const t=this._extensions.loseContext;t&&t.restoreContext()}clear(){const t=this._gl;t.clear(t.COLOR_BUFFER_BIT)}resize(){const t=this._gl;t.viewport(0,0,t.drawingBufferWidth,t.drawingBufferHeight)}viewport(t,e,i,s){this._gl.viewport(t,e,i,s)}createVAO(t,e){const i=this._createNativeVAO(),s=new ci(i,t,{indicies:this._createBuffer(),position:this._createBuffer(),uv:this._createBuffer()});return i&&(this._bindNativeVAO(i),this._supplyGeometryData(s,e),this._bindNativeVAO(null),this._unbindBuffers()),s}draw(t,e){const i=this._gl;t.obj?this._bindNativeVAO(t.obj):this._supplyGeometryData(t,e),i.drawElements(i.TRIANGLES,t.count,i.UNSIGNED_SHORT,0),t.obj?this._bindNativeVAO(null):this._unbindBuffers()}releaseVAO(t){t.obj&&this._deleteNativeVAO(t.obj),this._deleteBuffer(t.buffers.indicies),this._deleteBuffer(t.buffers.position),this._deleteBuffer(t.buffers.uv)}getUniformLocations(t,e){const i=this._gl,s=Object.keys(e).reduce(((e,s)=>(e[s]=i.getUniformLocation(t,s),e)),{});return Object.assign(Object.assign({},this._getCommonUniformLocations(t)),s)}updateCommonUniforms(t,e,i){const s=this._gl,n=i.uniformLocations,r=t.matrix,o=c();u(o,e.viewMatrix,r),s.uniformMatrix4fv(n.uMVMatrix,!1,o),s.uniformMatrix4fv(n.uPMatrix,!1,e.projectionMatrix)}updateVRUniforms(t,e,i,s){const n=this._gl,r=t.uniformLocations;n.uniformMatrix4fv(r.uMVMatrix,!1,e),n.uniformMatrix4fv(r.uPMatrix,!1,i),r.uEye&&n.uniform1f(r.uEye,s)}updateUniforms(t){const e=this._gl,i=t.uniforms,s=t.uniformLocations;for(const t in i){const n=i[t],r=s[t];n&&(n.needsUpdate&&n.update(e,r,this._isWebGL2))}}releaseShaderResources(t){const e=this._gl,i=t.uniforms;for(const t in i){const s=i[t];s&&(s.needsUpdate&&s.destroy(e))}e.deleteProgram(t.program)}useProgram(t){this._gl.useProgram(t.program)}createProgram(t,e){const i=this._gl,s=i.createProgram(),n=this._compileShader(i.VERTEX_SHADER,t),r=this._compileShader(i.FRAGMENT_SHADER,e);if(i.attachShader(s,n),i.attachShader(s,r),i.bindAttribLocation(s,0,"position"),i.bindAttribLocation(s,1,"uv"),i.linkProgram(s),this._debug&&!i.getProgramParameter(s,i.LINK_STATUS)){let t=null;throw i.getShaderParameter(n,i.COMPILE_STATUS)?i.getShaderParameter(r,i.COMPILE_STATUS)||(t=i.getShaderInfoLog(r)):t=i.getShaderInfoLog(n),new D(F.FAILED_LINKING_PROGRAM(i.getProgramInfoLog(s),t),B.FAILED_LINKING_PROGRAM)}return i.deleteShader(n),i.deleteShader(r),s}createWebGLTexture(t){const e=this._gl,i=e.createTexture();if(e.bindTexture(e.TEXTURE_2D,i),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,t.wrapS),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,t.wrapT),!t.isVideo()&&this._isWebGL2){const i=e;i.texStorage2D(i.TEXTURE_2D,1,i.RGBA8,t.width,t.height)}return i}createWebGLCubeTexture(t,e){const i=this._gl,s=i.createTexture();if(i.bindTexture(i.TEXTURE_CUBE_MAP,s),i.texParameteri(i.TEXTURE_CUBE_MAP,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_CUBE_MAP,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_CUBE_MAP,i.TEXTURE_WRAP_S,t.wrapS),i.texParameteri(i.TEXTURE_CUBE_MAP,i.TEXTURE_WRAP_T,t.wrapT),this._isWebGL2){const t=i;t.texStorage2D(t.TEXTURE_CUBE_MAP,1,t.RGBA8,e,e)}return s}makeXRCompatible(){return t(this,void 0,void 0,(function*(){const t=this._gl,e=t.getContextAttributes();e&&!0!==e.xrCompatible&&(yield t.makeXRCompatible())}))}bindXRLayer(t){const e=this._gl,i=new XRWebGLLayer(t,e);t.updateRenderState({baseLayer:i})}bindXRFrame(t){const e=this._gl,i=t.session.renderState.baseLayer;e.bindFramebuffer(e.FRAMEBUFFER,i.framebuffer)}useDefaultFrameBuffer(){const t=this._gl;t.bindFramebuffer(t.FRAMEBUFFER,null)}_createBuffer(){return this._gl.createBuffer()}_deleteBuffer(t){return this._gl.deleteBuffer(t)}_createNativeVAO(){const t=this._gl;if(this._isWebGL2)return t.createVertexArray();{const t=this._extensions.vao;return(null==t?void 0:t.createVertexArrayOES())||null}}_bindNativeVAO(t){const e=this._gl;if(this._isWebGL2)e.bindVertexArray(t);else{const e=this._extensions.vao;null==e||e.bindVertexArrayOES(t)}}_deleteNativeVAO(t){const e=this._gl;if(this._isWebGL2)e.deleteVertexArray(t);else{const e=this._extensions.vao;null==e||e.deleteVertexArrayOES(t)}}_supplyGeometryData(t,e){const i=t.geometry;this._supplyIndiciesData(i.indicies,t.buffers.indicies),this._supplyAttributeData(i.vertices,e.program,"position",t.buffers.position),this._supplyAttributeData(i.uvs,e.program,"uv",t.buffers.uv)}_unbindBuffers(){const t=this._gl;t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,null),t.bindBuffer(t.ARRAY_BUFFER,null)}_supplyIndiciesData(t,e){const i=this._gl;i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e),i.bufferData(i.ELEMENT_ARRAY_BUFFER,t.data,i.STATIC_DRAW)}_supplyAttributeData(t,e,i,s){const n=this._gl,r=n.getAttribLocation(e,i);r<0||(n.bindBuffer(n.ARRAY_BUFFER,s),n.bufferData(n.ARRAY_BUFFER,t.data,n.STATIC_DRAW),n.vertexAttribPointer(r,t.itemSize,n.FLOAT,!1,0,0),n.enableVertexAttribArray(r))}_compileShader(t,e){const i=this._gl,s=i.createShader(t);return i.shaderSource(s,e),i.compileShader(s),s}_getCommonUniformLocations(t){const e=this._gl;return{uMVMatrix:e.getUniformLocation(t,"uMVMatrix"),uPMatrix:e.getUniformLocation(t,"uPMatrix")}}_getContext(t){const e=["webgl2","webgl","experimental-webgl","webkit-3d","moz-webgl"];let i=null,s=!1;const n={preserveDrawingBuffer:!1,antialias:!1},r=t=>t.statusMessage;t.addEventListener(Q,r);for(const r of e){try{i=t.getContext(r,n),s="webgl2"===r}catch(t){}if(i)break}if(t.removeEventListener(Q,r),!i)throw new D(F.WEBGL_NOT_SUPPORTED,B.WEBGL_NOT_SUPPORTED);return{gl:i,isWebGL2:s}}}class _i{get canvas(){return this._canvas}get width(){return this._elementSize.x}get height(){return this._elementSize.y}get pixelRatio(){return this._pixelRatio}get aspect(){return this._elementSize.x/this._elementSize.y}constructor(t,e){this._canvas=t,this._elementSize={x:0,y:0},this._pixelRatio=1,this.ctx=new ui(t,e)}destroy(){const t=this._canvas;this.ctx.destroy(),t.width=1,t.height=1}resize(){const t=this._canvas,e=this._elementSize,i=window.devicePixelRatio;e.x=t.clientWidth,e.y=t.clientHeight,t.width=e.x*i,t.height=e.y*i,this._pixelRatio=i,this.ctx.resize()}render(t,e){const i=this.ctx;i.lost||(i.clear(),i.useProgram(t.program),i.updateCommonUniforms(t,e,t.program),t.update({camera:e}),i.updateUniforms(t.program),i.draw(t.vao,t.program))}renderVR(t,e,i){const s=this.ctx,n=e.getEyeParams(i);n&&t&&(s.bindXRFrame(i),s.useProgram(t.program),s.updateUniforms(t.program),n.forEach(((e,i)=>{const n=e.viewport,r=u(c(),e.vMatrix,t.matrix);s.viewport(n.x,n.y,n.width,n.height),s.updateVRUniforms(t.program,r,e.pMatrix,i),s.draw(t.vao,t.program)})))}}class di extends o{get rootEl(){return this._rootEl}get renderer(){return this._renderer}get camera(){return this._camera}get control(){return this._control}get vr(){return this._vr}get hotspot(){return this._hotspot}get plugins(){return this._plugins}get projection(){return this._projection}set projection(t){this._initialized&&t?this.load(t):this._projection=t}get mesh(){return this._mesh}get initialized(){return this._initialized}get autoplay(){return this._autoplay}get autoInit(){return this._autoInit}get autoResize(){return this._autoResize}get canvasSelector(){return this._canvasSelector}get useResizeObserver(){return this._useResizeObserver}get tabIndex(){return this._tabIndex}set tabIndex(t){const e=this._renderer.canvas;this._tabIndex=t,null!=t?e.tabIndex=t:e.removeAttribute("tabindex")}get maxDeltaTime(){return this._animator.maxDeltaTime}set maxDeltaTime(t){this._animator.maxDeltaTime=t}get debug(){return this._debug}set debug(t){this._debug=t}get initialYaw(){return this._camera.initialYaw}set initialYaw(t){this._camera.initialYaw=t}get initialPitch(){return this._camera.initialPitch}set initialPitch(t){this._camera.initialPitch=t}get initialZoom(){return this._camera.initialZoom}set initialZoom(t){this._camera.initialZoom=t}get yawRange(){return this._camera.yawRange}set yawRange(t){this._camera.yawRange=t,this._projection&&this._projection.updateCamera(this._camera)}get pitchRange(){return this._camera.pitchRange}set pitchRange(t){this._camera.pitchRange=t,this._projection&&this._projection.updateCamera(this._camera)}get zoomRange(){return this._camera.zoomRange}set zoomRange(t){this._camera.zoomRange=t,this._projection&&this._projection.updateCamera(this._camera)}get fov(){return this._camera.fov}set fov(t){const e=this._camera,i=this._control;e.fov=t,e.updateMatrix(),i.sync()}get rotate(){return this._control.rotate}get zoom(){return this._control.zoom}get gyro(){return this._control.gyro}get useGrabCursor(){return this._control.useGrabCursor}set useGrabCursor(t){this._control.useGrabCursor=t}get disableContextMenu(){return this._control.disableContextMenu}set disableContextMenu(t){this._control.disableContextMenu=t}get scrollable(){return this._control.scrollable}set scrollable(t){this._control.scrollable=t}get wheelScrollable(){return this._control.wheelScrollable}set wheelScrollable(t){this._control.wheelScrollable=t}constructor(t,{projection:e=null,initialYaw:i=0,initialPitch:s=0,initialZoom:n=1,yawRange:r=null,pitchRange:o=null,zoomRange:a=null,fov:h=90,useGrabCursor:l=!0,disableContextMenu:c=!1,rotate:u=!0,zoom:_=!0,gyro:d=!1,scrollable:m=!0,wheelScrollable:p=!1,autoplay:g=!1,hotspot:v={},autoInit:E=!0,autoResize:f=!0,canvasSelector:b="canvas",useResizeObserver:y=!0,on:T={},plugins:R=[],maxDeltaTime:w=1/30,tabIndex:C=0,debug:L=!1}={}){super(),this.renderFrame=t=>{const e=this._camera,i=this._renderer,s=this._control,n=this._hotspot,r=this._autoplay,o=this._mesh;o&&(this._emit(Ot.BEFORE_RENDER),r.playing&&(r.update(t),s.sync()),e.animation?e.animation.update(t):s.update(t),i.render(o,e),n.render(e),e.changed&&this._emit(Ot.VIEW_CHANGE,{yaw:e.yaw,pitch:e.pitch,zoom:e.zoom,quaternion:[e.quaternion[0],e.quaternion[1],e.quaternion[2],e.quaternion[3]]}),e.onFrameRender(),this._emit(Ot.RENDER))},this._renderFrameOnDemand=t=>{const e=this._camera,i=this._control,s=this._autoplay,n=this._mesh,r=null==n?void 0:n.getTexture();this._initialized&&r&&(e.animation||i.animating||s.playing||r.isVideo())&&this.renderFrame(t)},this._renderVRFrame=(t,e)=>{const i=this._vr,s=this._mesh,n=this._renderer;s&&(this._emit(Ot.BEFORE_RENDER),n.renderVR(s,i,e),this._emit(Ot.RENDER))},this._rootEl=((t,e)=>{const i=te(t,e);if(!i)throw Jt(t)?new D(F.ELEMENT_NOT_FOUND(t),B.ELEMENT_NOT_FOUND):new D(F.WRONG_TYPE(t,["HTMLElement","string"]),B.WRONG_TYPE);return i})(t),this._plugins=R,this._initialized=!1,this._autoInit=E,this._autoResize=f,this._canvasSelector=b,this._useResizeObserver=y,this._tabIndex=C,this._debug=L;const x=((t,e)=>{const i=t.querySelector(e);if(!i)throw new D(F.CANVAS_NOT_FOUND,B.CANVAS_NOT_FOUND);return i})(this._rootEl,b);this._renderer=new _i(x,L),this._camera=new me({initialYaw:i,initialPitch:s,initialZoom:n,fov:h,yawRange:r,pitchRange:o,zoomRange:a}),this._control=new Ce(x,this._camera,{useGrabCursor:l,scrollable:m,wheelScrollable:p,disableContextMenu:c,rotate:u,zoom:_,gyro:d}),this._animator=new ni(w),this._autoplay=new oi(this,x,g),this._projection=e,this._mesh=null,this._autoResizer=new ri(y,(()=>this.resize())),this._vr=new ai(this._renderer.ctx),this._hotspot=new li(this._rootEl,this._renderer,v),this._addEventHandlers(T),e&&E&&this.init()}destroy(){this._camera.destroy(),this._animator.stop(),this._renderer.destroy(),this._control.destroy(),this._autoResizer.disable(),this._mesh&&(this._mesh.destroy(this._renderer.ctx),this._mesh=null),this._plugins.forEach((t=>t.destroy(this))),this._initialized=!1}init(){return t(this,void 0,void 0,(function*(){if(!this._projection)throw new D(F.PROVIDE_PROJECTION_FIRST,B.PROVIDE_PROJECTION_FIRST);const t=this._renderer,e=this._camera,i=this._control,s=this._animator,n=this._hotspot,r=this._projection,o=t.canvas;this._bindComponentEvents(),t.ctx.init(),this._resizeComponents(),e.updateMatrix(),this._autoResize&&this._autoResizer.enable(o),this._autoplay.enableBlocked||this._autoplay.enable(),this._plugins.forEach((t=>{t.init(this)}));const a=yield this._loadTexture(r);this._applyProjection(r,a),n.refresh(),s.start(this._renderFrameOnDemand),yield i.enable(),null==this._tabIndex||o.hasAttribute("tabIndex")||(o.tabIndex=this._tabIndex),this._initialized=!0,this.renderFrame(0),this._emit(Ot.READY)}))}load(e){return t(this,void 0,void 0,(function*(){if(!e)return!1;if(this._initialized){const t=yield this._loadTexture(e);this._applyProjection(e,t),this.renderFrame(0)}else this._projection=e,this.init();return!0}))}resize(){if(!this._initialized)return;this._resizeComponents(),this.renderFrame(0);const{width:t,height:e}=this._renderer;this._emit(Ot.RESIZE,{width:t,height:e})}addPlugins(...t){this._initialized&&t.forEach((t=>{t.init(this)})),this._plugins.push(...t)}removePlugins(...t){t.forEach((t=>{const e=this._plugins.indexOf(t);e<0||(t.destroy(this),this._plugins.splice(e,1))}))}_emit(t,...e){const i=e?e[0]:{};this.trigger(t,Object.assign({type:t,target:this},i))}_applyProjection(t,e){const i=this._camera,s=this._control,n=this._renderer,r=this._mesh;r&&r.destroy(n.ctx);const o=t.createMesh(n.ctx,e);t.updateCamera(i),t.updateControl(s),this._mesh=o,this._emit(Ot.PROJECTION_CHANGE,{projection:t})}_loadTexture(e){return t(this,void 0,void 0,(function*(){const t=new si,{src:i,video:s}=e;this._emit(Ot.LOAD_START,{src:i,video:s});const n=yield t.load(i,s);return this._emit(Ot.LOAD,{src:i,video:s}),n}))}_resizeComponents(){const t=this._renderer,e=this._camera,i=this._control;t.resize(),e.resize(t.width,t.height),i.resize(t.width,t.height)}_addEventHandlers(t){Object.keys(t).forEach((e=>{this.on(e,t[e])}))}_bindComponentEvents(){const t=this._rootEl,e=this._control,i=this._animator,s=this._renderer,n=this._vr;[Ft,Mt,Dt].forEach((t=>{e.rotate.on(t,(e=>{this._emit(t,e)})),e.zoom.on(t,(e=>{this._emit(t,e)}))})),n.on(Ot.VR_START,(e=>{t.classList.add(xt.IN_VR),i.changeContext(e.session),i.start(this._renderVRFrame),this._emit(Ot.VR_START)})),n.on(Ot.VR_END,(()=>{t.classList.remove(xt.IN_VR),s.ctx.useDefaultFrameBuffer(),i.changeContext(window),i.start(this._renderFrameOnDemand),this.resize(),this._emit(Ot.VR_END)}))}}di.VERSION="4.0.0-beta.7";class mi extends o{constructor(){super(),this.matrix=c(),this.rotation=y(),this.position=p(0,0,0),this.scale=p(1,1,1)}updateMatrix(){!function(t,e,i,s){var n=e[0],r=e[1],o=e[2],a=e[3],h=n+n,l=r+r,c=o+o,u=n*h,_=n*l,d=n*c,m=r*l,p=r*c,g=o*c,v=a*h,E=a*l,f=a*c,b=s[0],y=s[1],T=s[2];t[0]=(1-(m+g))*b,t[1]=(_+f)*b,t[2]=(d-E)*b,t[3]=0,t[4]=(_-f)*y,t[5]=(1-(u+g))*y,t[6]=(p+v)*y,t[7]=0,t[8]=(d+E)*T,t[9]=(p-v)*T,t[10]=(1-(u+m))*T,t[11]=0,t[12]=i[0],t[13]=i[1],t[14]=i[2],t[15]=1}(this.matrix,this.rotation,this.position,this.scale)}update(t){this.trigger(Pt,t)}}class pi{constructor({className:t={}}={}){this._startLoading=({target:t})=>{t.rootEl.appendChild(this._container),t.initialized?t.once(Ot.LOAD,this._detachElements):t.once(Ot.READY,this._detachElements)},this._detachElements=({target:t})=>{const e=this._container;e&&e.parentElement===t.rootEl&&t.rootEl.removeChild(e)},this.className=t,this._container=this._createElements()}init(t){t.on(Ot.LOAD_START,this._startLoading)}destroy(t){t.off(Ot.LOAD_START,this._startLoading),this._detachElements({target:t})}_createElements(){const t=Object.assign(Object.assign({},this.className),pi.DEFAULT_CLASS),e=Qt(t.CONTAINER),i=Qt(t.RING);return e.appendChild(i),e}}pi.DEFAULT_CLASS={CONTAINER:"view360-spinner",RING:"view360-spinner-ring"};class gi{constructor(t){this.position=t.position,this.order=t.order}}const vi={CONTROLS_ROOT:"view360-controls",CONTROLS_BG:"view360-controls-background",CONTROLS_MAIN:"view360-controls-main",CONTROLS_TOP:"view360-controls-top",CONTROLS_BOTTOM:"view360-controls-bottom",CONTROLS_MID:"view360-controls-mid",CONTROLS_LEFT:"view360-controls-left",CONTROLS_RIGHT:"view360-controls-right",CONTROLS_FLOAT_LEFT:"view360-controls-float-left",CONTROLS_FLOAT_RIGHT:"view360-controls-float-right",CONTROLS_BUTTON:"view360-controls-button",PROGRESS_ROOT:"view360-controls-progress",VOLUME_ROOT:"view360-controls-volume",RANGE_ROOT:"view360-range",RANGE_TRACK:"view360-range-track",RANGE_THUMB:"view360-range-thumb",RANGE_FILLER:"view360-range-filler",PLAY_BUTTON:"view360-controls-play",PAUSE_BUTTON:"view360-controls-pause",UNMUTED_BUTTON:"view360-controls-unmuted",MUTED_BUTTON:"view360-controls-muted",FULLSCREEN_BUTTON:"view360-controls-fullscreen",FULLSCREEN_EXIT_BUTTON:"view360-controls-fullscreen-exit",VR_BUTTON:"view360-controls-vr",GYRO_ENABLED:"view360-controls-gyro-enabled",GYRO_DISABLED:"view360-controls-gyro-disabled",VIDEO_TIME_DISPLAY:"view360-controls-time",PIEVIEW_ROOT:"view360-controls-pie",FIXED:"view360-controls-fixed",UNAVAILABLE:"view360-controls-unavailable",HIDDEN:"view360-controls-hidden"},Ei={TOP_LEFT:"top-left",TOP_RIGHT:"top-right",MAIN_TOP:"main-top",MAIN_BOTTOM:"main-bottom",MAIN_LEFT:"main-left",MAIN_RIGHT:"main-right"};class fi extends o{constructor(){super(),this._onHold=({srcEvent:t,isTouch:e})=>{var i;const s=this._bbox;if(!s)return;const n=e?t.touches[0].pageX:t.pageX,r=s.x+(null!==(i=window.scrollX)&&void 0!==i?i:window.pageXOffset),o=ee(n,r,r+s.width),a=(o-r)/s.width;this._motion.reset(o),this.thumbEl.classList.add(this._fixedClass),this.trigger(Mt,a)},this._onChange=({delta:t})=>{var e;const i=this._motion,s=this._bbox;if(!s)return;i.setNewEndByDelta(t.x),i.update(1);const n=s.x+(null!==(e=window.scrollX)&&void 0!==e?e:window.pageXOffset),r=(ee(i.val,n,n+s.width)-n)/s.width;this.trigger(Nt,r)},this._onRelease=()=>{this._bbox&&(this.thumbEl.classList.remove(this._fixedClass),this.trigger(Dt))};const t=document.createElement(mt),e=document.createElement(mt),i=document.createElement(mt),s=document.createElement(mt);t.draggable=!1,e.appendChild(s),e.appendChild(i),t.appendChild(e),this.rootEl=t,this.trackEl=e,this.thumbEl=i,this.fillerEl=s,this._mouseInput=new pe,this._touchInput=new ge,this._motion=new _e({duration:1,range:Ht,easing:t=>t}),this._bbox={x:0,y:0,width:0,height:0,left:0,right:0,bottom:0,top:0},this._fixedClass=vi.FIXED}init(t){const e=this._mouseInput,i=this._touchInput;this.rootEl.classList.add(t.RANGE_ROOT),this.trackEl.classList.add(t.RANGE_TRACK),this.thumbEl.classList.add(t.RANGE_THUMB),this.fillerEl.classList.add(t.RANGE_FILLER),this._fixedClass=t.FIXED,e.on(Mt,this._onHold),i.on(Mt,this._onHold),e.on(Dt,this._onRelease),i.on(Dt,this._onRelease),e.on(Nt,this._onChange),i.on(Nt,this._onChange),e.enable(this.rootEl),i.enable(this.rootEl),this.resize()}destroy(){const t=this._mouseInput,e=this._touchInput;this.rootEl.className="",this.trackEl.className="",this.thumbEl.className="",this.fillerEl.className="",t.off(),e.off(),t.disable(),e.disable()}resize(){this._bbox=this.trackEl.getBoundingClientRect()}updateStyle(t){const e=this._bbox.width,i=ee(t,0,1);this.fillerEl.style.width=100*i+"%",this.thumbEl.style.transform=`translateX(${i*e}px)`}}class bi extends gi{get element(){return this._rangeControl.rootEl}constructor({position:t=Ei.MAIN_TOP,order:e=9999}={}){super({position:t,order:e}),this._onResize=()=>{this._rangeControl.resize()},this._onTimeUpdate=()=>{const t=this._video;t&&(this._currentTime=t.source.currentTime,this._rangeControl.updateStyle(this._currentTime/this._duration))},this._onDurationChange=()=>{const t=this._video;t&&(this._duration=t.source.duration,this._rangeControl.updateStyle(this._currentTime/this._duration))},this._onHold=t=>{const e=this._video,i=this._controlBar;if(!e||!i)return;const s=e.isPaused();e.source.pause();const n=e.source.duration*t;e.source.currentTime=n,e.source.dispatchEvent(new CustomEvent(jt,{detail:{time:n}})),i.rootEl.classList.add(i.className.FIXED),this._wasPaused=!this._playPromise&&s},this._onControl=t=>{const e=this._video;if(!e)return;const i=e.source.duration*t;e.source.currentTime=i,e.source.dispatchEvent(new CustomEvent(jt,{detail:{time:i}}))},this._onRelease=()=>{const t=this._video,e=this._controlBar;t&&e&&(this._wasPaused||this._playPromise||(this._playPromise=t.source.play().catch((()=>{})),this._playPromise.then((()=>{this._playPromise=null})),e.rootEl.classList.remove(e.className.FIXED))),this._wasPaused=!1},this.position=t,this.order=e,this._controlBar=null,this._rangeControl=new fi,this._video=null,this._wasPaused=!1,this._currentTime=0,this._duration=0,this._playPromise=null}init(t,e){var i;const s=null===(i=t.mesh)||void 0===i?void 0:i.getTexture(),n=this.element,r=this._rangeControl,o=e.className.UNAVAILABLE;s&&s.isVideo()?(n.classList.remove(o),n.classList.add(e.className.PROGRESS_ROOT),t.on(Ot.RESIZE,this._onResize),s.source.addEventListener(lt,this._onTimeUpdate),s.source.addEventListener(ct,this._onDurationChange),s.source.addEventListener(jt,this._onTimeUpdate),r.init(e.className),r.on(Mt,this._onHold),r.on(Nt,this._onControl),r.on(Dt,this._onRelease),this._video=s,this._currentTime=s.source.currentTime,this._duration=s.source.duration,this._controlBar=e,r.updateStyle(this._currentTime/this._duration)):n.classList.add(o)}destroy(t){const e=this._video;t.off(Ot.RESIZE,this._onResize),e&&(e.source.removeEventListener(lt,this._onTimeUpdate),e.source.removeEventListener(ct,this._onDurationChange),e.source.removeEventListener(jt,this._onTimeUpdate)),this._rangeControl.destroy(),this._video=null,this._playPromise=null}}class yi extends gi{constructor({position:t=Ei.MAIN_LEFT,order:e=9999}={}){super({position:t,order:e}),this._onClick=()=>{const t=this._video;t&&(this._paused?t.source.play():t.source.pause())},this._onPlay=()=>{if(!this._controlBar)return;const t=this.element,e=this._controlBar.className;t.classList.add(e.PAUSE_BUTTON),t.classList.remove(e.PLAY_BUTTON),t.title="Pause Video",this._paused=!1},this._onPause=()=>{if(!this._controlBar)return;const t=this.element,e=this._controlBar.className;t.classList.add(e.PLAY_BUTTON),t.classList.remove(e.PAUSE_BUTTON),t.title="Play Video",this._paused=!0},this.element=document.createElement(pt),this._video=null,this._paused=!0,this._controlBar=null}init(t,e){var i;const s=this.element,n=null===(i=t.mesh)||void 0===i?void 0:i.getTexture(),r=e.className,o=r.UNAVAILABLE;if(!n||!n.isVideo())return void s.classList.add(o);s.classList.add(r.CONTROLS_BUTTON),s.classList.remove(o);const a=n.isPaused();this._video=n,this._paused=a,this._controlBar=e,a?this._onPause():this._onPlay(),s.addEventListener(J,this._onClick),n.source.addEventListener(rt,this._onPlay),n.source.addEventListener(ot,this._onPause)}destroy(){const t=this._video,e=this.element;t&&(e.className="",e.removeEventListener(J,this._onClick),t.source.removeEventListener(rt,this._onPlay),t.source.removeEventListener(ot,this._onPause),this._video=null,this._paused=!0,this._controlBar=null)}}class Ti extends gi{get element(){return this._rootEl}constructor({position:t=Ei.MAIN_RIGHT,order:e=9999}={}){super({position:t,order:e}),this._onResize=()=>{this._rangeControl.resize(),this._updateDisplay()},this._onClick=()=>{const t=this._video;t&&!this._rootEl.disabled&&(t.source.muted=!t.source.muted)},this._onVolumeChange=()=>{const t=this._buttonEl,e=this._video,i=this._controlBar;if(!e||!i)return;const s=i.className;e.source.muted||0===e.source.volume?(t.classList.add(s.MUTED_BUTTON),t.classList.remove(s.UNMUTED_BUTTON)):(t.classList.add(s.UNMUTED_BUTTON),t.classList.remove(s.MUTED_BUTTON)),this._updateDisplay()},this._onHold=t=>{const e=this._video,i=this._controlBar;if(!e||!i)return;const s=i.className;e.source.volume=t,this._rootEl.classList.add(s.FIXED),i.containerEl.classList.add(s.FIXED),this._updateDisplay()},this._onChange=t=>{const e=this._video;e&&(e.source.volume=t,e.source.muted=!(t>0),this._updateDisplay())},this._onRelease=()=>{const t=this._controlBar;if(!t)return;const e=t.className;this._rootEl.classList.remove(e.FIXED),t.containerEl.classList.remove(e.FIXED)},this._updateDisplay=()=>{const t=this._video,e=this._rootEl;if(!t)return;if(!t.hasAudio())return void(e.disabled=!0);e.disabled=!1;const i=t.source.muted?0:t.source.volume;this._rangeControl.updateStyle(i)},this._controlBar=null,this._rangeControl=new fi,this._createElements(),this._video=null}init(t,e){var i;const s=null===(i=t.mesh)||void 0===i?void 0:i.getTexture(),n=this._rootEl,r=this._buttonEl,o=this._rangeControl,a=e.className,h=a.UNAVAILABLE;s&&s.isVideo()?(n.classList.remove(h),n.classList.add(a.CONTROLS_BUTTON),n.classList.add(a.VOLUME_ROOT),r.classList.add(a.CONTROLS_BUTTON),s.source.muted?r.classList.add(a.MUTED_BUTTON):r.classList.add(a.UNMUTED_BUTTON),t.on(Ot.RESIZE,this._onResize),n.addEventListener(_t,this._onResize),r.addEventListener(J,this._onClick),s.source.addEventListener(ht,this._onVolumeChange),s.source.addEventListener(at,this._updateDisplay),s.source.addEventListener(ut,this._updateDisplay),o.init(a),o.on(Mt,this._onHold),o.on(Nt,this._onChange),o.on(Dt,this._onRelease),this._controlBar=e,this._video=s,this._updateDisplay()):n.classList.add(h)}destroy(t){const e=this._video,i=this._buttonEl,s=this._rootEl;s.className="",i.className="",t.off(Ot.RESIZE,this._onResize),s.removeEventListener(_t,this._onResize),i.removeEventListener(J,this._onClick),e&&(e.source.removeEventListener(ht,this._onVolumeChange),e.source.removeEventListener(at,this._updateDisplay),e.source.removeEventListener(ut,this._updateDisplay)),this._controlBar=null,this._rangeControl.destroy(),this._video=null}_createElements(){const t=document.createElement(pt),e=document.createElement(mt);t.appendChild(this._rangeControl.rootEl),t.appendChild(e),t.title="Toggle Mute",this._rootEl=t,this._buttonEl=e}}class Ri extends gi{constructor({position:t=Ei.MAIN_RIGHT,order:e=9999}={}){super({position:t,order:e}),this._onClick=()=>{const t=this._targetEl;t&&(he()?this._exitFullscreen():this._requestFullscreen(t))},this._onFullscreenChange=()=>{const t=this.element,e=this._controlBar;if(!e)return;const i=e.className;he()?(t.classList.add(i.FULLSCREEN_EXIT_BUTTON),t.classList.remove(i.FULLSCREEN_BUTTON)):(t.classList.add(i.FULLSCREEN_BUTTON),t.classList.remove(i.FULLSCREEN_EXIT_BUTTON))},this.element=document.createElement(pt),this.element.title="Toggle Fullscreen",this._controlBar=null,this._targetEl=null}init(t,e){const i=this.element,s=e.className;this._fullscreenAvailable()?(i.classList.add(s.CONTROLS_BUTTON),i.classList.remove(s.UNAVAILABLE),i.addEventListener(J,this._onClick),this._addFullscreenHandlers(),he()?i.classList.add(s.FULLSCREEN_EXIT_BUTTON):i.classList.add(s.FULLSCREEN_BUTTON),this._controlBar=e,this._targetEl=t.rootEl):i.classList.add(s.UNAVAILABLE)}destroy(){const t=this.element;t.className="",t.removeEventListener(J,this._onClick),this._removeFullscreenHandlers(),this._controlBar=null,this._targetEl=null}_fullscreenAvailable(){return Rt.some((t=>!!document[t]))}_requestFullscreen(t){for(const e of Rt){const i=t[e];if(i)return void i.call(t)}}_exitFullscreen(){for(const t of Ct){const e=document[t];if(e)return void e.call(document)}}_addFullscreenHandlers(){Lt.forEach((t=>{document.addEventListener(t,this._onFullscreenChange)}))}_removeFullscreenHandlers(){Lt.forEach((t=>{document.removeEventListener(t,this._onFullscreenChange)}))}}class wi extends gi{constructor({position:t=Ei.MAIN_LEFT,order:e=9999}={}){super({position:t,order:e}),this._onTimeUpdate=()=>{const t=this._video;t&&(this._currentTime=t.source.currentTime,this._updateDisplay())},this._onDurationChange=()=>{const t=this._video;t&&(this._duration=t.source.duration,this._updateDisplay())},this._onCustomTimeChange=t=>{this._currentTime=t.detail.time,this._updateDisplay()},this.element=document.createElement(mt),this._video=null,this._currentTime=0,this._duration=0}init(t,e){var i;const s=null===(i=t.mesh)||void 0===i?void 0:i.getTexture(),n=this.element,r=e.className;s&&s.isVideo()?(n.classList.add(r.VIDEO_TIME_DISPLAY),n.classList.remove(r.UNAVAILABLE),s.source.addEventListener(lt,this._onTimeUpdate),s.source.addEventListener(ct,this._onDurationChange),s.source.addEventListener(jt,this._onCustomTimeChange),this._video=s,this._currentTime=s.source.currentTime,this._duration=s.source.duration,this._updateDisplay()):n.classList.add(r.UNAVAILABLE)}destroy(){const t=this._video;t&&(this.element.className="",t.source.removeEventListener(lt,this._onTimeUpdate),t.source.removeEventListener(ct,this._onDurationChange),t.source.removeEventListener(jt,this._onCustomTimeChange),this._video=null)}_updateDisplay(){const t=this._currentTime,e=Math.floor(t/60),i=Math.floor(t-60*e),s=i<10?`0${i}`:i,n=this._duration,r=Math.floor(n/60),o=Math.floor(n-60*r),a=o<10?`0${o}`:o;this.element.innerText=`${e}:${s} / ${r}:${a}`}}class Ci extends gi{constructor({resetCamera:t=!0,position:e=Ei.TOP_RIGHT,order:i=9999}={}){super({position:e,order:i}),this._onClick=()=>{const t=this._viewer,e=this.resetCamera;if(!t||!e)return;const{yaw:i=t.initialYaw,pitch:s=t.initialPitch,zoom:n=t.initialZoom,duration:r=500}=re(e);t.camera.animateTo({yaw:i,pitch:s,zoom:n,duration:r})},this._updatePie=({target:t})=>{const e=this._piePathEl,i=this._rangeCircleEl,s=t.camera,n=s.getHorizontalFov(),r=s.getYawRange(s.zoom),o=.5*n,a=24*Math.PI,h=a*n/360,l=a*(s.yaw+o+90)/360;if(e.setAttribute("stroke-dasharray",`${h} ${a-h}`),e.setAttribute("stroke-dashoffset",`${l}`),isFinite(r.min)&&isFinite(r.max)){const t=45*Math.PI,e=(se(r.min,-180,180)-o)/360,s=(se(r.max,-180,180)+o)/360,n=t*Math.abs(s-e),a=-t*(e-.25);i.setAttribute("stroke-dasharray",`${n} ${t-n}`),i.setAttribute("stroke-dashoffset",`${a}`)}else i.setAttribute("stroke-dasharray",""),i.setAttribute("stroke-dashoffset","")},this.element=document.createElement(mt),this.element.title="Reset view",this.resetCamera=t,this._createPieElements(),this._viewer=null}init(t,e){const i=this.element;t.initialized?this._updatePie({target:t}):t.once(Ot.READY,this._updatePie);const s=e.className.PIEVIEW_ROOT;i.classList.add(s),this.resetCamera&&i.addEventListener(J,this._onClick),t.on(Ot.VIEW_CHANGE,this._updatePie),this._viewer=t}destroy(t){const e=this.element;e.removeEventListener(J,this._onClick),e.className="",t.off(Ot.READY,this._updatePie),t.off(Ot.VIEW_CHANGE,this._updatePie),this._viewer=null}_createPieElements(){const t=this.element,e=document.createElementNS(Kt,"svg");e.setAttribute("viewBox","0 0 48 48"),e.setAttribute("width","100%"),e.setAttribute("height","100%");const i=document.createElementNS(Kt,"circle");i.setAttribute("stroke","currentColor"),i.setAttribute("fill","transparent"),i.setAttribute("cx","24"),i.setAttribute("cy","24"),i.setAttribute("r","12"),i.setAttribute("stroke-width","24"),e.appendChild(i);const s=document.createElementNS(Kt,"circle");s.setAttribute("stroke","currentColor"),s.setAttribute("fill","transparent"),s.setAttribute("cx","24"),s.setAttribute("cy","24"),s.setAttribute("r","22.5"),s.setAttribute("stroke-width","3"),e.appendChild(s),t.appendChild(e),this._piePathEl=i,this._rangeCircleEl=s}}class Li extends gi{constructor({position:t=Ei.MAIN_RIGHT,order:e=9999}={}){super({position:t,order:e}),this._onClick=()=>{const t=this._viewer;t&&t.vr.enter()},this.element=document.createElement(pt),this.element.title="Enter VR",this._viewer=null}init(t,e){const i=this.element,s=e.className;i.classList.add(s.UNAVAILABLE),i.classList.add(s.VR_BUTTON),i.classList.add(s.CONTROLS_BUTTON),t.vr.isAvailable().then((t=>{t&&i.classList.remove(s.UNAVAILABLE)})),i.addEventListener(J,this._onClick),this._viewer=t}destroy(){const t=this.element;t.className="",t.removeEventListener(J,this._onClick),this._viewer=null}}class xi extends gi{constructor({position:t=Ei.MAIN_RIGHT,order:e=9999}={}){super({position:t,order:e}),this._onClick=()=>{const t=this._viewer,e=this._controlBar;if(!t||!e)return;const i=t.control.gyro;i.enabled?i.disable():we.requestSensorPermission().then((t=>{t?i.enable():this.element.classList.add(e.className.UNAVAILABLE)}))},this._updateStyle=()=>{const t=this.element,e=this._viewer,i=this._controlBar;if(!e||!i)return;const s=e.control.gyro,n=i.className;s.enabled?(t.classList.add(n.GYRO_ENABLED),t.classList.remove(n.GYRO_DISABLED)):(t.classList.add(n.GYRO_DISABLED),t.classList.remove(n.GYRO_ENABLED))},this.element=document.createElement(mt),this.element.title="Toggle gyroscope control"}init(t,e){const i=this.element,s=e.className;i.addEventListener(J,this._onClick),i.classList.add(s.CONTROLS_BUTTON),i.classList.add(s.UNAVAILABLE);const n=()=>{i.classList.remove(s.UNAVAILABLE),t.control.gyro.on(Ut,this._updateStyle),t.control.gyro.on(Bt,this._updateStyle)};le()?n():we.isAvailable().then((t=>{t&&n()})),this._controlBar=e,this._viewer=t,this._updateStyle()}destroy(t){const e=this.element;t.control.gyro.off(Ut,this._updateStyle),t.control.gyro.off(Bt,this._updateStyle),e.removeEventListener(J,this._onClick),e.className="",this._controlBar=null,this._viewer=null}}class Oi{get enabled(){return!!this._targetEl}get hidden(){return this._controlBar.containerEl.classList.contains(this._hiddenClass)}get _hiddenClass(){return this._controlBar.className.HIDDEN}get _fixedClass(){return this._controlBar.className.FIXED}constructor(t,{initialDelay:e=3e3,delay:i=0,idleDelay:s=3e3}){this._onMouseEnter=()=>{this._isCursorInside=!0,this.show()},this._onMouseLeave=()=>{this._isCursorInside=!1,this._hideAfterDelay()},this._onMouseMove=()=>{this._isFullscreen&&this.showTemporaliy()},this._onHold=t=>{this._isGrabbing=!0,"mouse"===t.pointerType&&(this._isCursorInside=!0),window.addEventListener(k,this._onRelease),this.show()},this._onRelease=()=>{this._isGrabbing=!1,window.removeEventListener(k,this._onRelease),this._hideAfterDelay()},this._onVideoPlay=()=>{this._targetEl&&this._controlBar.containerEl.classList.remove(this._fixedClass)},this._onVideoPause=()=>{this._targetEl&&this._controlBar.containerEl.classList.add(this._fixedClass)},this._onFullscreenChange=()=>{this._isFullscreen=he(),this._isFullscreen&&this._hideAfterDelay()},this._controlBar=t,this._initialDelay=e,this._delay=i,this._idleDelay=s,this._timer=-1,this._isCursorInside=!1,this._isGrabbing=!1,this._isFullscreen=!1,this._video=null,this._targetEl=null}enable(t){var e;this._targetEl&&this.disable(t);const i=this._initialDelay,s=t.rootEl;this._targetEl=t.rootEl,this._timer=window.setTimeout((()=>{this.hide()}),i),s.addEventListener(z,this._onHold),s.addEventListener(K,this._onMouseEnter),s.addEventListener(V,this._onMouseMove),s.addEventListener(q,this._onMouseLeave),this._addFullscreenHandlers();const n=null===(e=t.mesh)||void 0===e?void 0:e.getTexture();n&&n.isVideo()&&(n.isPaused()&&this._controlBar.containerEl.classList.add(this._fixedClass),n.source.addEventListener(rt,this._onVideoPlay),n.source.addEventListener(ot,this._onVideoPause),this._video=n)}disable(t){if(!this._targetEl)return;const e=this._controlBar,i=t.rootEl,s=this._video;i.removeEventListener(z,this._onHold),window.removeEventListener(k,this._onRelease),i.removeEventListener(K,this._onMouseEnter),i.removeEventListener(V,this._onMouseMove),i.removeEventListener(q,this._onMouseLeave),this._removeFullscreenHandlers(),window.clearTimeout(this._timer),e.containerEl.classList.remove(this._fixedClass),s&&(s.source.removeEventListener(rt,this._onVideoPlay),s.source.removeEventListener(ot,this._onVideoPause)),this._isCursorInside=!1,this._isGrabbing=!1,this._video=null,this._targetEl=null}show(){this._clearHideTimer(),this._controlBar.containerEl.classList.remove(this._hiddenClass)}showTemporaliy(){this.show(),this._hideAfterDelay(this._idleDelay)}hide(){this._clearHideTimer(),this._controlBar.containerEl.classList.add(this._hiddenClass)}_clearHideTimer(){this._timer&&(window.clearTimeout(this._timer),this._timer=-1)}_hideAfterDelay(t=this._delay){this._isGrabbing||!this._isFullscreen&&this._isCursorInside||(this._clearHideTimer(),t<=0?this.hide():this._timer=window.setTimeout((()=>{this.hide()}),t))}_addFullscreenHandlers(){Lt.forEach((t=>{document.addEventListener(t,this._onFullscreenChange)}))}_removeFullscreenHandlers(){Lt.forEach((t=>{document.removeEventListener(t,this._onFullscreenChange)}))}}class Ai{constructor(){this._onKeyDown=t=>{const e=this._video;if(!e)return;t.preventDefault(),t.stopPropagation();const i=e.source,s=null!=t.keyCode?yt[t.keyCode]:Tt[t.key];switch(s){case"LEFT":case"RIGHT":return this._changeVideoTime(i,"RIGHT"===s);case"UP":case"DOWN":return this._changeVideoVolume(i,"UP"===s)}(32===t.keyCode||" "===t.key)&&this._toggleVideo(e)}}enable(t,e){this._video=e,t.addEventListener(Z,this._onKeyDown,!0)}disable(t){this._video=null,t.removeEventListener(Z,this._onKeyDown,!0)}_changeVideoTime(t,e){const i=e?5:-5;t.currentTime+=i,t.dispatchEvent(new CustomEvent(jt,{detail:{time:t.currentTime}}))}_changeVideoVolume(t,e){const i=e?.1:-.1;t.muted?t.volume=ee(i,0,1):t.volume=ee(t.volume+i,0,1),t.volume>0?t.muted=!1:t.muted=!0}_toggleVideo(t){t.isPaused()?t.source.play():t.source.pause()}}class Ii{get rootEl(){return this._rootEl}get containerEl(){return this._containerEl}get backgroundEl(){return this._bgEl}get items(){return this._items}get customItems(){return this._customItems}constructor({autoHide:t,showBackground:e,clickToPlay:i=!0,keyboardControls:s=!0,progressBar:n=!0,playButton:r=!0,volumeButton:o=!0,fullscreenButton:a=!0,videoTime:h=!0,pieView:l=!0,vrButton:c=!0,gyroButton:u=!0,className:_={},customItems:d=[]}={}){var m;this._onStaticClick=({target:t,isTouch:e})=>{var i;const s=this._autoHider;if(e){if(!s.enabled)return;s.hidden?s.showTemporaliy():s.hide()}else{if(!this.clickToPlay)return;const e=null===(i=t.mesh)||void 0===i?void 0:i.getTexture();if(!e||!e.isVideo())return;e.isPaused()?e.source.play():e.source.pause()}},this._onNewSrcLoad=({target:t})=>{const e=this._items;this._updateBackground(t),this._updateAutoHide(t),this._updateKeyboardHandler(t),Object.keys(e).forEach((i=>{e[i].forEach((e=>{e.destroy(t,this),e.init(t,this)}))}))},this.autoHide=t,this.showBackground=e,this.clickToPlay=i,this.keyboardControls=s,this.progressBar=n,this.playButton=r,this.volumeButton=o,this.fullscreenButton=a,this.videoTime=h,this.pieView=l,this.vrButton=c,this.gyroButton=u,this.className=Object.assign(Object.assign({},Ii.DEFAULT_CLASS),_);const p=null!==(m=_.CONTROLS_ROOT)&&void 0!==m?m:Ii.DEFAULT_CLASS.CONTROLS_ROOT;this._rootEl=Qt(p),this._createPositionWrappers(),this._items=Object.keys(Ii.POSITION).reduce(((t,e)=>(t[Ii.POSITION[e]]=[],t)),{}),this._customItems=d,this._autoHider=new Oi(this,re(t)),this._videoControl=new Ai,d.forEach((t=>{this._items[t.position].push(t)}))}init(t){const e=t.rootEl,i=this._rootEl,s=this._createDefaultItems();this._updateBackground(t),this._updateAutoHide(t),this._updateKeyboardHandler(t),e.appendChild(i),this._addItem(t,s),this._addItem(t,this._customItems),t.on(Ot.PROJECTION_CHANGE,this._onNewSrcLoad),t.on(Ot.STATIC_CLICK,this._onStaticClick)}destroy(t){const e=t.rootEl,i=this._rootEl,s=this._items;i.parentElement===e&&e.removeChild(i),Object.keys(s).forEach((e=>{s[e].forEach((e=>{e.destroy(t,this)})),s[e]=[]})),this._clearItemElements(),this._autoHider.disable(t),this._videoControl.disable(e),t.off(Ot.PROJECTION_CHANGE,this._onNewSrcLoad),t.off(Ot.STATIC_CLICK,this._onStaticClick)}_addItem(t,e){for(const i of e){const e=this._items[i.position],s=this._wrapperEl[i.position],n=ne(e,(t=>t.order>i.order));if(n>=0){const t=e[n].element;e.splice(n,0,i),s.insertBefore(i.element,t)}else e.push(i),s.appendChild(i.element);i.init(t,this)}}_createPositionWrappers(){const t=Object.assign(Object.assign({},Ii.DEFAULT_CLASS),this.className),e=this._rootEl,i=Qt(t.CONTROLS_BG),s=Qt(t.CONTROLS_FLOAT_LEFT),n=Qt(t.CONTROLS_FLOAT_RIGHT);e.appendChild(s),e.appendChild(n);const r=Qt(t.CONTROLS_MAIN),o=Qt(t.CONTROLS_TOP),a=Qt(t.CONTROLS_BOTTOM),h=Qt(t.CONTROLS_MID),l=Qt(t.CONTROLS_LEFT),c=Qt(t.CONTROLS_RIGHT);h.appendChild(l),h.appendChild(c),r.appendChild(i),r.appendChild(o),r.appendChild(h),r.appendChild(a),e.appendChild(r),this._bgEl=i,this._containerEl=r,this._wrapperEl={[Ii.POSITION.MAIN_TOP]:o,[Ii.POSITION.MAIN_LEFT]:l,[Ii.POSITION.MAIN_RIGHT]:c,[Ii.POSITION.MAIN_BOTTOM]:a,[Ii.POSITION.TOP_LEFT]:s,[Ii.POSITION.TOP_RIGHT]:n}}_clearItemElements(){Object.keys(Ii.POSITION).map((t=>Ii.POSITION[t])).map((t=>this._wrapperEl[t])).forEach((t=>{for(;t.firstChild;)t.removeChild(t.firstChild)}))}_updateAutoHide(t){var e;const i=this.autoHide,s=this._autoHider;if(null!=i)i?s.enable(t):s.disable(t);else{const i=null===(e=t.mesh)||void 0===e?void 0:e.getTexture();i&&i.isVideo()?s.enable(t):s.disable(t)}}_updateBackground(t){var e,i;const s=this._bgEl,n=this.showBackground,r=null!==(e=this.className.HIDDEN)&&void 0!==e?e:Ii.DEFAULT_CLASS.HIDDEN;if(null!=n)n?s.classList.remove(r):s.classList.add(r);else{const e=null===(i=t.mesh)||void 0===i?void 0:i.getTexture();e&&e.isVideo()?s.classList.remove(r):s.classList.add(r)}}_updateKeyboardHandler(t){var e;const i=t.rootEl,s=this._videoControl,n=null===(e=t.mesh)||void 0===e?void 0:e.getTexture();this.keyboardControls&&n&&n.isVideo()?s.enable(i,n):s.disable(i)}_createDefaultItems(){const t=[];return this.progressBar&&t.push(new bi(re(this.progressBar))),this.playButton&&t.push(new yi(re(this.playButton))),this.volumeButton&&t.push(new Ti(re(this.volumeButton))),this.gyroButton&&t.push(new xi(re(this.gyroButton))),this.vrButton&&t.push(new Li(re(this.vrButton))),this.fullscreenButton&&t.push(new Ri(re(this.fullscreenButton))),this.videoTime&&t.push(new wi(re(this.videoTime))),this.pieView&&t.push(new Ci(re(this.pieView))),t}}Ii.DEFAULT_CLASS=vi,Ii.POSITION=Ei;class Si{constructor({src:t,video:e=!1}){this.src=t,this.video=e}updateCamera(t){t.resetRange()}updateControl(t){t.ignoreZoomScale=!1}}class Pi{constructor(){this.needsUpdate=!0}destroy(t){}}class Mi extends Pi{constructor(t,e,i){super(),this.texture=e,this._webglTexture=t.createWebGLCubeTexture(e,e.width),this._cubemapOrder=i}destroy(t){this.texture.destroy(),t.deleteTexture(this._webglTexture)}update(t,e,i){const s=this.texture;t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,s.flipY),t.uniform1i(e,0),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_CUBE_MAP,this._webglTexture);ae(s.sources,this._cubemapOrder).forEach(((e,s)=>{i?t.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+s,0,0,0,t.RGBA,t.UNSIGNED_BYTE,e):t.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+s,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e)})),s.isVideo()||(this.needsUpdate=!1)}}class Ni{get size(){return this._size}constructor(t,e){var i;this.texture=t,this._renderingOrder=ae(!(i=6)||i<=0?[]:Array.apply(0,Array(i)).map(((t,e)=>e)),e);const s=document.createElement("canvas");this._calcRenderingSize(),s.width=this._size,s.height=this._size,this._canvas=s,this._ctx=s.getContext("2d")}destroy(){const t=this._canvas;t.width=1,t.height=1,this._canvas=null}draw(t,e){const i=this._size,s=this.texture;let n=0;for(let r=0;r=0;t--)for(let e=0;e<3;e++){const n=[e*i,.5*t,(e+1)*i,.5*t,(e+1)*i,.5*(t+1),e*i,.5*(t+1)];s.push(n)}e&&e.forEach(((t,e)=>{if(t===Xt.ZERO)return;const i=s[e];let n;n=t===Xt.CW_90?[1,2,3,0]:t===Xt.CCW_90?[3,0,1,2]:[2,3,0,1];const r=Array(i.length);for(let t=0;tt.concat(e)),[]))}}class ki extends Pi{constructor(t,e){super(),this.texture=e,this._webglTexture=t.createWebGLTexture(e)}destroy(t){this.texture.destroy(),t.deleteTexture(this._webglTexture)}update(t,e,i){const s=this.texture,n=s.isVideo();t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,s.flipY),t.uniform1i(e,0),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this._webglTexture),!n&&i?t.texSubImage2D(t.TEXTURE_2D,0,0,0,t.RGBA,t.UNSIGNED_BYTE,s.source):t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,s.source),n||(this.needsUpdate=!1)}}var Gi="#define GLSLIFY 1\nattribute vec3 position;attribute vec2 uv;uniform mat4 uMVMatrix;uniform mat4 uPMatrix;varying highp vec2 vUV;void main(){vUV=uv;gl_Position=uPMatrix*uMVMatrix*vec4(position,1.0);}",Hi="#define GLSLIFY 1\nuniform sampler2D uTexture;varying highp vec2 vUV;void main(){gl_FragColor=texture2D(uTexture,vUV.st);}";class Yi extends zi{constructor(t){const e=[],i=[],s=[],n=[-.5,.5],r=1/60,o=t*r;for(let a=0;a<2;a++){const h=n[a];for(let n=0;n<=60;n++){const l=n*o+Math.PI-.5*t,c=Math.cos(l),u=Math.sin(l),_=n*r,d=a;if(s.push(_,d),e.push(c,h,u),0===a&&n<60){const t=n,e=t+60+1;i.push(t,e,t+1,e,e+1,t+1)}}}super(e,i,s)}}class Wi extends zi{constructor(){const t=60,e=-.5*Math.PI,i=[],s=[],n=[];let r,o;for(r=0;r<=60;r++){const a=(r/60-.5)*Math.PI,h=Math.sin(a),l=Math.cos(a);for(o=0;o<=t;o++){const a=2*(o/t-.5)*Math.PI+e,c=Math.sin(a),u=Math.cos(a)*l,_=h,d=c*l,m=o/t,p=r/60;if(i.push(m,p),s.push(u,_,d),o!==t&&60!==r){const e=61*r+o,i=e+t+1;n.push(e,e+1,i,i,e+1,i+1)}}}super(s,n,i)}}class Xi extends Pi{constructor(t){super(),this.val=t}update(t,e){t.uniform1f(e,this.val),this.needsUpdate=!1}}class ji extends zi{constructor(t=2,e=2,i=-1){const s=.5*t,n=.5*e;super([-s,-n,i,s,-n,i,-s,n,i,s,n,i],[0,1,2,2,1,3],[0,0,1,0,0,1,1,1])}}class Ki extends Pi{constructor(t){super(),this.val=t}update(t,e){t.uniform4fv(e,this.val.reduce(((t,e)=>[...t,...e]),[])),this.needsUpdate=!1}}class qi extends Si{constructor(t){super(t),this._mode=t.mode}createMesh(t,e){let i,s;if(this._mode===qi.MODE.LEFT_RIGHT)i=[.5,1,0,0],s=[.5,1,.5,0];else i=[1,.5,0,0],s=[1,.5,0,.5];const n={uTexture:new ki(t,e),uEye:new Xi(0),uTexScaleOffset:new Ki([i,s])},r=new Wi,o=new Bi(t,"#define GLSLIFY 1\nattribute vec3 position;attribute vec2 uv;uniform mat4 uMVMatrix;uniform mat4 uPMatrix;uniform vec4 uTexScaleOffset[2];uniform float uEye;varying highp vec2 vUV;void main(){vec4 scaleOffset=uTexScaleOffset[int(uEye)];vUV=uv.xy*scaleOffset.xy+scaleOffset.zw;gl_Position=uPMatrix*uMVMatrix*vec4(position,1.0);}",Hi,n),a=t.createVAO(r,o);return new Ui(a,o)}}qi.MODE={LEFT_RIGHT:"left_right",TOP_BOTTOM:"top_bottom"};var Zi={__proto__:null,default:di,Autoplay:oi,AutoResizer:ri,Camera:me,CameraAnimation:de,Motion:_e,Object3D:mi,View360Error:D,WebGLRenderer:_i,XRManager:ai,PanoControl:Ce,RotateControl:Ee,ZoomControl:ye,GyroControl:we,ControlBar:Ii,ControlBarItem:gi,FullscreenButton:Ri,PieView:Ci,PlayButton:yi,ProgressBar:bi,VideoTime:wi,VolumeControl:Ti,LoadingSpinner:pi,Projection:Si,CubemapProjection:class extends Si{constructor(t){super(t);const{cubemapOrder:e="RLUDFB",cubemapFlipX:i=!1}=t;this._cubemapOrder=e,this._cubemapFlipX=i}createMesh(t,e){const i=this._cubemapOrder,s=this._cubemapFlipX,n={uTexture:e.isCube()?new Mi(t,e,i):new Di(t,e,i)},r=new Vi({order:i}),o=new Bi(t,"#define GLSLIFY 1\nattribute vec3 position;attribute vec2 uv;uniform mat4 uMVMatrix;uniform mat4 uPMatrix;varying highp vec3 vPos;void main(){vPos=position;gl_Position=uPMatrix*uMVMatrix*vec4(position,1.0);}","#define GLSLIFY 1\nuniform samplerCube uTexture;varying highp vec3 vPos;void main(){gl_FragColor=textureCube(uTexture,vec3(vPos.x,vPos.y,-vPos.z));}",n),a=t.createVAO(r,o),h=new Ui(a,o);return s&&(h.scale[0]=-1),h.updateMatrix(),h}},CubestripProjection:class extends Si{constructor(t){super(t);const{cubemapOrder:e="RLUDFB",cubemapFlipX:i=!1}=t;this._cubemapOrder=e,this._cubemapFlipX=i}createMesh(t,e){const i=this._cubemapOrder,s=this._cubemapFlipX,n={uTexture:new ki(t,e)},r=new Vi({order:i}),o=new Bi(t,Gi,Hi,n),a=t.createVAO(r,o),h=new Ui(a,o);return s&&(h.scale[0]=-1),h.updateMatrix(),h}},CylindricalProjection:class extends Si{constructor(t){super(t);const{partial:e=!1}=t;this._partial=e,this._aspect=1,this._halfHeight=0,this._mesh=null}createMesh(t,e){if(this._mesh)return this._mesh;const i=this._partial,{width:s,height:n}=e,r=s/n,o=180/r,a=i?1:2*Math.tan(o*zt),h=i?r:2*Math.PI,l=new Yi(h),c=new Bi(t,Gi,Hi,{uTexture:new ki(t,e)}),u=t.createVAO(l,c),_=new Ui(u,c);return _.scale[1]=a,T(_.rotation),C(_.rotation,_.rotation,-Math.PI/2),_.updateMatrix(),this._aspect=r,this._halfHeight=.5*a,this._mesh=_,_}updateCamera(t){super.updateCamera(t);const e=this._mesh,i=this._aspect,s=this._halfHeight;if(!e)return;if(this._partial){const e=.5*i*Vt;t.restrictYawRange(-e,e)}const n=Math.atan2(s,1)*Vt,r=Math.tan(t.fov*zt*.5)/(s*t.aspect);t.restrictPitchRange(-n,n),t.restrictZoomRange(r,1/0),t.restrictRenderHeight(2*s)}},EquiangularProjection:class extends Si{createMesh(t,e){const i={uTexture:new ki(t,e)},s=new Vi({order:"LFRDBU",rotateUV:[Xt.ZERO,Xt.ZERO,Xt.ZERO,Xt.CW_90,Xt.CCW_90,Xt.CW_90]}),n=new Bi(t,Gi,"#define PI 3.14159265359\nprecision mediump float;\n#define GLSLIFY 1\nuniform sampler2D uTexture;varying highp vec2 vUV;const vec2 OPERATE_COORDS_RANGE=vec2(-1.0,1.0);const vec2 TEXTURE_COORDS_RANGE=vec2(0.0,1.0);const float ONE_THIRD=1.0/3.0;const float EAC_CONST=2.0/PI;float scale(vec2 domainRange,vec2 targetRange,float val){float unit=1.0/(domainRange[1]-domainRange[0]);return targetRange[0]+(targetRange[1]-targetRange[0])*(val-domainRange[0])*unit;}void main(void){float transformedCoordX;float transformedCoordY;float texRangeXStart=floor(vUV.s*3.)*ONE_THIRD;float texRangeYStart=floor(vUV.t*2.)*0.5;vec2 orgTextureRangeX=vec2(texRangeXStart,texRangeXStart+ONE_THIRD);vec2 orgTextureRangeY=vec2(texRangeYStart,texRangeYStart+0.5);float px=scale(orgTextureRangeX,OPERATE_COORDS_RANGE,vUV.s);float py=scale(orgTextureRangeY,OPERATE_COORDS_RANGE,vUV.t);float qu=EAC_CONST*atan(px)+0.5;float qv=EAC_CONST*atan(py)+0.5;transformedCoordX=scale(TEXTURE_COORDS_RANGE,orgTextureRangeX,qu);transformedCoordY=scale(TEXTURE_COORDS_RANGE,orgTextureRangeY,qv);gl_FragColor=texture2D(uTexture,vec2(transformedCoordX,transformedCoordY));}",i),r=t.createVAO(s,n);return new Ui(r,n)}},EquirectProjection:class extends Si{constructor(t){super(t)}createMesh(t,e){const i={uTexture:new ki(t,e)},s=new Wi,n=new Bi(t,Gi,Hi,i),r=t.createVAO(s,n);return new Ui(r,n)}},LittlePlanetProjection:class extends Si{constructor(t){super(t)}createMesh(t,e){e.wrapS=WebGLRenderingContext.REPEAT,e.wrapT=WebGLRenderingContext.REPEAT;const i={uTexture:new ki(t,e),uYaw:new Xi(0),uPitch:new Xi(.5),uZoom:new Xi(1)},s=new ji,n=new Bi(t,"#define GLSLIFY 1\nattribute vec3 position;attribute vec2 uv;uniform mat4 uMVMatrix;uniform mat4 uPMatrix;varying highp vec2 vUV;void main(){vUV=uv;gl_Position=vec4(position,1.0);}","precision mediump float;\n#define GLSLIFY 1\nuniform sampler2D uTexture;uniform float uYaw;uniform float uPitch;uniform float uZoom;varying highp vec2 vUV;const float PI=3.1415926536;const float PI_2=PI*0.5;vec2 toStereographicUV(in vec2 uv,in vec2 center){float R=1.*uZoom;vec2 texLatLon=(uv*2.-1.)*vec2(PI,PI_2);vec2 central=(center*2.-1.)*vec2(PI,PI_2)+vec2(PI,0);float x=texLatLon.x;float y=texLatLon.y;float rou=sqrt(x*x+y*y);float c=2.0*atan(rou,R*0.5);float sin_c=sin(c);float cos_c=cos(c);float sin_cy=sin(central.y);float cos_cy=cos(central.y);float lat=asin(cos_c*sin_cy+(y*sin_c*cos_cy)/rou);float lon=central.x+atan(x*sin_c,rou*cos_cy*cos_c-y*sin_cy*sin_c);float u=(lon/PI+1.0)*0.5;float v=(lat/PI_2+1.0)*0.5;return vec2(u,v);}void main(){vec2 central=vec2(uYaw,uPitch);vec2 uv=toStereographicUV(vUV,central);gl_FragColor=texture2D(uTexture,uv);}",i),r=t.createVAO(s,n),o=new Ui(r,n);return o.on(Pt,(({camera:t})=>{const e=o.program.uniforms;e.uYaw.val=t.yaw/360,e.uPitch.val=t.pitch/180+.5,e.uZoom.val=t.zoom,e.uYaw.needsUpdate=!0,e.uPitch.needsUpdate=!0,e.uZoom.needsUpdate=!0})),o}updateControl(t){t.ignoreZoomScale=!0}},StereoEquiProjection:qi,Hotspot:hi,HotspotRenderer:li,ERROR_CODES:U,DEFAULT_CLASS:xt,EVENTS:Ot,EASING:At,getValidProps:t=>Object.keys(t).reduce(((e,i)=>(null!=t[i]&&(e[i]=t[i]),e)),{}),VIEW360_METHODS:["destroy","init","load","resize","addPlugins","removePlugins","renderFrame","on","hasOn","once","off","trigger"],withMethods:(t,e)=>{[o.prototype,di.prototype].forEach((i=>{Object.getOwnPropertyNames(i).filter((t=>"_"!==t.charAt(0)&&"constructor"!==t)).forEach((s=>{const n=Object.getOwnPropertyDescriptor(i,s);if(n.value)Object.defineProperty(t,s,{value:function(...t){return n.value.call(this[e],...t)}});else{const i={};n.get&&(i.get=function(){var t;return this[e]&&(null===(t=n.get)||void 0===t?void 0:t.call(this[e]))}),n.set&&(i.set=function(...t){var i;return null===(i=n.set)||void 0===i?void 0:i.call(this[e],...t)}),Object.defineProperty(t,s,i)}}))}))}};return((t,...e)=>{e.forEach((e=>{Object.keys(e).forEach((i=>{const s=e[i];Array.isArray(t[i])&&Array.isArray(s)?t[i]=[...t[i],...s]:t[i]=s}))}))})(di,Zi),di})); +//# sourceMappingURL=view360.pkgd.min.js.map diff --git a/src/static/view360/view360.pkgd.min.js.map b/src/static/view360/view360.pkgd.min.js.map new file mode 100644 index 0000000..c628d08 --- /dev/null +++ b/src/static/view360/view360.pkgd.min.js.map @@ -0,0 +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/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/projection/CubemapProjection.ts","../src/projection/CubestripProjection.ts","../src/projection/CylindricalProjection.ts","../src/projection/EquiangularProjection.ts","../src/projection/EquirectProjection.ts","../src/projection/LittlePlanetProjection.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 = {\n min: -Infinity, max: Infinity\n} as const;\nexport const DEFAULT_PITCH_RANGE: Readonly = {\n min: -90, max: 90\n} as const;\nexport const DEFAULT_ZOOM_RANGE: Readonly = {\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 = Number.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 = (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 = >(val?: T): NoBoolean => 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 = (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 return window.isSecureContext && !!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;\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 {\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 {\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> {\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> {\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> {\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;\n\n/**\n * Camera's rotation control\n * @ko 카메라의 회전을 담당하는 컨트롤\n * @since 4.0.0\n */\nclass RotateControl extends Component 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 = {}) {\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 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[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[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[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> {\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> {\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;\n\n/**\n * Camera's zoom control\n * @ko 카메라의 줌 값을 담당하는 컨트롤\n * @since 4.0.0\n */\nclass ZoomControl extends Component 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 * @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 * @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 * 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 /**\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 = {}) {\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 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 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[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[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[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> {\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;\n\n/**\n * Camera's rotation control by gyroscope\n * @ko 자이로스코프를 이용한 회전 컨트롤\n * @since 4.0.0\n */\nclass GyroControl extends Component 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 {\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 {\n // Request sensor permission, on iOS13+\n if (sensorCanBeEnabledIOS()) {\n return (DeviceMotionEvent as typeof DeviceMotionEvent & {\n requestPermission: () => Promise;\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 = {}) {\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;\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;\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;\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 {\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 * 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) {\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;\n\n public constructor({\n source,\n width,\n height,\n flipY\n }: {\n source: Exclude;\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\";\n\n/**\n * @hidden\n */\nclass TextureVideo extends Texture2D {\n public source: HTMLVideoElement;\n\n public destroy() {\n const video = this.source;\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\";\n\n/**\n * @hidden\n */\nclass TextureLoader {\n private _loadChecker: ImReady;\n\n constructor() {\n this._loadChecker = new ImReady();\n }\n\n public async load(src: ProjectionOptions[\"src\"], video: ProjectionOptions[\"video\"]): Promise {\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 {\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): Promise {\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): Promise {\n const config: VideoConfig = {\n autoplay: true,\n muted: true,\n loop: false,\n volume: 1,\n ...videoConfig,\n };\n const video = this._toVideoElement(src, config);\n\n return this._load([video], resolve => {\n const { autoplay, muted } = config;\n\n video.currentTime = 0;\n if (autoplay && muted) {\n video.play().catch(() => void 0);\n }\n\n resolve(new TextureVideo({\n source: video,\n width: video.videoWidth,\n height: video.videoHeight,\n flipY: true\n }));\n });\n }\n\n private _load(content: HTMLElement[], onLoad: (resolve: (value: T) => void) => void): Promise {\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): 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 (Array.isArray(src)) {\n src.forEach(source => this._appendSourceElement(video, source));\n } else {\n this._appendSourceElement(video, src);\n }\n\n const sourceCount = video.querySelectorAll(\"source\").length;\n if (sourceCount > 0 && video.readyState < 1) {\n video.load();\n }\n\n return video;\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) {\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","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 {\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) {\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 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>(program: WebGLProgram, uniforms: T): UniformLocations {\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);\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 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, 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, 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\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 `devicePixelRatio` value.\n * @ko 현재 `devicePixelRatio` 값.\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 * 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.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 canvas.width = canvasSize.x * devicePixelRatio;\n canvas.height = canvasSize.y * devicePixelRatio;\n\n this._pixelRatio = devicePixelRatio;\n this.ctx.resize();\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 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 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 } 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;\n autoplay: boolean | Partial;\n autoInit: boolean;\n autoResize: boolean;\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 {\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 _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\n private _autoInit: View360Options[\"autoInit\"];\n private _autoResize: View360Options[\"autoResize\"];\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 *
\n * \n *
\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 * 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 * 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 *
\n * \n * \n * \n *
\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 * \n *
\n * \n *
\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 canvasSelector = \"canvas\",\n useResizeObserver = true,\n on = {},\n plugins = [],\n maxDeltaTime = 1 / 30,\n tabIndex = 0,\n debug = false\n }: Partial = {}) {\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._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._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._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\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._autoResizer.disable();\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._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` if load was successful. {@ko 프로젝션 로드에 성공했을 경우 `Promise`를 반환합니다. }\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 {\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 mesh = this._mesh;\n\n if (!mesh) return;\n\n this._emit(EVENTS.BEFORE_RENDER);\n\n if (autoPlayer.playing) {\n autoPlayer.update(delta);\n control.sync();\n }\n\n if (camera.animation) {\n camera.animation.update(delta);\n } else {\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(eventName: K, ...params: EventParams) {\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 if (\n !camera.animation\n && !control.animating\n && !autoplay.playing\n && !texture.isVideo()\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 // 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 this._emit(EVENTS.PROJECTION_CHANGE, {\n projection\n });\n }\n\n private async _loadTexture(projection: Projection): Promise {\n const contentLoader = new TextureLoader();\n const { src, video } = projection;\n\n this._emit(EVENTS.LOAD_START, {\n src,\n video\n });\n\n const texture = await contentLoader.load(src, video);\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\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 = {}) {\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) {\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 | 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 = {}) {\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 = {}) {\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 = {}) {\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 = {}) {\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 = {}) {\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 = {}) {\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 = {}) {\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 = {}) {\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) {\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;\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;\n /**\n * @copy ControlBar#playButton\n */\n playButton: boolean | Partial;\n /**\n * @copy ControlBar#volumeButton\n */\n volumeButton: boolean | Partial;\n /**\n * @copy ControlBar#fullscreenButton\n */\n fullscreenButton: boolean | Partial;\n /**\n * @copy ControlBar#videoTime\n */\n videoTime: boolean | Partial;\n /**\n * @copy ControlBar#pieView\n */\n pieView: boolean | Partial;\n /**\n * @copy ControlBar#vrButton\n */\n vrButton: boolean | Partial;\n /**\n * @copy ControlBar#gyroButton\n */\n gyroButton: boolean | Partial;\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;\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, HTMLElement>;\n private _items: Record, 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 = {}) {\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, 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) => {\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) => {\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;\n /**\n * @copy Projection#video\n */\n video?: boolean | Partial;\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 WebGLContext from \"./WebGLContext\";\nimport UniformCanvasCube from \"../uniform/UniformCanvasCube\";\nimport UniformTexture2D from \"../uniform/UniformTexture2D\";\nimport UniformTextureCube from \"../uniform/UniformTextureCube\";\n\ntype CommonProjectionUniforms = {\n uTexture: UniformTexture2D | UniformTextureCube | UniformCanvasCube;\n}\n\n/**\n * @hidden\n */\nclass TriangleMesh 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;\n\n public constructor(vao: VertexArrayObject, program: ShaderProgram) {\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 return this.program.uniforms.uTexture.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 = Record> {\n public readonly program: WebGLProgram;\n public readonly uniforms: T;\n public readonly uniformLocations: UniformLocations;\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 {\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;\n public readonly indicies: VertexData;\n public readonly uvs: VertexData;\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(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 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;\n private _cubemapFlipX: NonNullable;\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;\n private _cubemapFlipX: NonNullable;\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 * @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","_a","Number","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","window","isSecureContext","DeviceMotionEvent","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","fov","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","minFov","maxFov","currentFov","current","_getZoomedHorizontalFov","hFov","fovToZoom","baseFov","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","location","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","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","_wheelInput","_scale","scaledDelta","_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","hfovToZoom","zoomScale","newCursor","style","cursor","Texture","flipY","wrapS","WebGLRenderingContext","CLAMP_TO_EDGE","wrapT","isVideo","isCube","Texture2D","source","TextureVideo","video","pause","removeAttribute","load","isPaused","paused","ended","readyState","hasAudio","audioTracks","webkitAudioDecodedByteCount","mozHasAudio","TextureCube","sources","TextureLoader","_loadChecker","ImReady","src","loadVideo","Array","isArray","loadCubeImage","imgSrc","loadImage","images","_toImageArray","_load","image","naturalWidth","naturalHeight","videoConfig","config","autoplay","muted","volume","_toVideoElement","currentTime","play","videoWidth","videoHeight","content","onLoad","loader","reject","once","errorCount","check","imgEl","Image","crossOrigin","HTMLVideoElement","playsInline","setAttribute","forEach","_appendSourceElement","querySelectorAll","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","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","count","geometry","indicies","buffers","WebGLContext","canvas","_canvas","maxTextureSize","_maxTextureSize","isWebGL2","_isWebGL2","supportVAO","_extensions","vao","lost","_contextLost","debug","_debug","_onContextLost","_onContextRestore","loseContext","init","gl","_getContext","_gl","getParameter","MAX_TEXTURE_SIZE","getExtension","bindBuffer","ARRAY_BUFFER","ELEMENT_ARRAY_BUFFER","forceLoseContext","extension","forceRestoreContext","restoreContext","clear","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","texture","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","createBuffer","buffer","deleteBuffer","createVertexArray","ext","createVertexArrayOES","bindVertexArray","bindVertexArrayOES","deleteVertexArray","deleteVertexArrayOES","_supplyIndiciesData","_supplyAttributeData","vertices","uvs","bufferData","data","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","canvasSize","devicePixelRatio","clientWidth","clientHeight","mesh","renderVR","vr","eyeParams","eye","View360","_rootEl","_vr","_hotspot","plugins","_plugins","projection","_projection","_initialized","_mesh","initialized","_autoplay","autoInit","_autoInit","autoResize","_autoResize","canvasSelector","_canvasSelector","tabIndex","_tabIndex","_animator","updateCamera","root","renderFrame","autoPlayer","_emit","_renderFrameOnDemand","getTexture","_renderVRFrame","_delta","getElement","findCanvas","selector","_autoResizer","_addEventHandlers","plugin","animator","_bindComponentEvents","_resizeComponents","_loadTexture","_applyProjection","hasAttribute","addPlugins","push","removePlugins","pluginIdx","splice","eventName","params","evtParams","target","newMesh","createMesh","updateControl","contentLoader","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","_video","_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","request","call","VideoTime","_onCustomTimeChange","timeMinute","floor","timeSeconds","timeSecondsFormatted","durationMinute","durationSeconds","durationSecondsFormatted","innerText","PieView","resetCamera","_viewer","_updatePie","piePath","_piePathEl","rangeCircle","_rangeCircleEl","halfFov","pieRadius","pieDeg","pieOffset","isFinite","radius","rangeDiff","offset","_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","deleteTexture","pixelStorei","UNPACK_FLIP_Y_WEBGL","uniform1i","activeTexture","TEXTURE0","texSubImage2D","TEXTURE_CUBE_MAP_POSITIVE_X","RGBA","UNSIGNED_BYTE","texImage2D","CubeTexturePainter","_size","_renderingOrder","undef","_calcRenderingSize","surfaceIdx","row","_row","column","_column","renderingFace","drawImage","UniformCanvasCube","_painter","TriangleMesh","uTexture","ShaderProgram","VertexData","Geometry","Float32Array","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","cubemapFlipX","_cubemapFlipX","partial","_partial","_halfHeight","cylinderHeight","cylinderTheta","restrictedYaw","restrictedPitch","minZoom","REPEAT","uYaw","uPitch","uZoom","propsObj","props","propName","withMethods","attr","proto","getOwnPropertyNames","charAt","descriptor","getOwnPropertyDescriptor","value","defineProperty","args","getterDescriptor","get","set","merge","srcs","modules"],"mappings":"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"} \ No newline at end of file