@lumiscaphe/viewer 4.2.2 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/lib/index.cjs +6 -6
- package/dist/lib/index.d.ts +47 -52
- package/dist/lib/index.js +525 -592
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [Version 4.3.0]
|
|
2
|
+
|
|
3
|
+
- Cancel superseded loads to free bandwidth on rapid view switching
|
|
4
|
+
- Report previously-silenced frame load failures via `onLoadError`
|
|
5
|
+
- Type `Options.events` with strict callback signatures
|
|
6
|
+
- Drop unused `image` / `video` / `vrcube` / `vrobject` option slots
|
|
7
|
+
|
|
1
8
|
## [Version 4.2.2]
|
|
2
9
|
|
|
3
10
|
- Fix iOS Canvas2D blur by replacing resize polling with ResizeObserver
|
package/dist/lib/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".ls-viewer-container{display:block;position:relative;overflow:hidden;-webkit-user-select:none;user-select:none;width:100%;height:100%}.ls-viewer-container-image,.ls-viewer-container-video{cursor:default;pointer-events:none}.ls-viewer-container-vrcube{cursor:pointer;cursor:grab}.ls-viewer-container-vrcube-grabbing{cursor:move;cursor:grabbing}.ls-viewer-container-vrobject{cursor:move;cursor:grab}.ls-viewer-container-vrobject-grabbing{cursor:move;cursor:grabbing}.ls-viewer-container-loading{cursor:progress}.ls-viewer-canvas{position:absolute;opacity:0;transition:opacity .5s}.ls-viewer-video{position:absolute}")),document.head.appendChild(e)}}catch(r){console.error("vite-plugin-css-injected-by-js",r)}})();
|
|
2
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=require("debounce-promise"),h=require("twgl.js"),N=require("regression");function B(l){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(l){for(const e in l)if(e!=="default"){const i=Object.getOwnPropertyDescriptor(l,e);Object.defineProperty(t,e,i.get?i:{enumerable:!0,get:()=>l[e]})}}return t.default=l,Object.freeze(t)}const x=B(h);class f{constructor(t,e){this.width=t,this.height=e}get aspect(){return this.width/this.height}}const b=class b{constructor(t,e,i,s){this.top=t,this.left=e,this.width=i,this.height=s}static contains(t,e){return e.x>=0&&e.x<t.width&&e.y>=0&&e.y<t.height}static fit(t,e,i){const s=t.aspect,r=e.aspect;let a=0,n=0;switch(i){case"contain":a=r<s?e.width:e.height*s,n=r<s?e.width/s:e.height;break;case"cover":default:a=r<s?e.height*s:e.width,n=r<s?e.height:e.width/s;break;case"fill":a=e.width,n=e.height;break}const o=(e.height-n)/2,u=(e.width-a)/2;return new b(o,u,a,n)}static project(t,e,i,s){const r=b.fit(t,e,i),a=r.width/t.width,n=r.height/t.height;return{x:Math.round(r.left+s.x*a),y:Math.round(r.top+s.y*n)}}static unproject(t,e,i,s){const r=b.fit(t,e,i),a=r.width/t.width,n=r.height/t.height;return{x:Math.round((s.x-r.left)/a),y:Math.round((s.y-r.top)/n)}}static getStandardAspectRatio(t,e,i){if(t===0||e===0)return 0;if(i)return i;const s=t/e;return t<e?s<b.PORTRAIT_ASPECT_BOUNDARY?9/16:3/4:s<b.LANDSCAPE_ASPECT_BOUNDARY?4/3:16/9}static getStandardResolution(t,e,i){if(t===0||e===0)return new f(0,0);const s=b.getStandardAspectRatio(t,e,i);if(i){const a=b.getStandardQuality(Math.min(t,e));return new f(Math.round(a*s),Math.round(a))}if(t<e){const a=b.getStandardQuality(Math.max(e*s,t));return new f(Math.round(a),Math.round(a/s))}const r=b.getStandardQuality(Math.max(t/s,e));return new f(Math.round(r*s),Math.round(r))}static getStandardQuality(t){return t<=720?720:1080}};b.LANDSCAPE_ASPECT_BOUNDARY=Math.sqrt(4/3*(16/9)),b.PORTRAIT_ASPECT_BOUNDARY=Math.sqrt(3/4*(9/16));let y=b;class X{constructor(t){this.element=document.createElement("canvas"),this.element.classList.add("ls-viewer-canvas"),this.element.style.opacity="0",this.element.width=0,this.element.height=0,this.context=this.element.getContext("2d"),this.context.imageSmoothingQuality="high",this.backCanvas=document.createElement("canvas"),this.backContext=this.backCanvas.getContext("2d"),this.backContext.imageSmoothingQuality="high",this.fit=t}destroy(){this.requestAnimationId&&(cancelAnimationFrame(this.requestAnimationId),this.requestAnimationId=void 0)}show(t){t?this.element.style.display="block":this.element.style.opacity="1"}hide(t){t?this.element.style.display="none":this.element.style.opacity="0"}resize(t,e,i){const s=Math.floor(t*i),r=Math.floor(e*i);this.element.style.width=`${t}px`,this.element.style.height=`${e}px`,!(this.element.width===s&&this.element.height===r)&&(this.element.width=s,this.element.height=r,this.context.imageSmoothingQuality="high",this.backCanvas.width=s,this.backCanvas.height=r,this.backContext.imageSmoothingQuality="high",this.image&&this.draw(this.image,!1))}draw(t,e,i){if(!t)return;this.requestAnimationId&&(cancelAnimationFrame(this.requestAnimationId),this.requestAnimationId=void 0);const s=y.fit(new f(t.width,t.height),new f(this.element.width,this.element.height),this.fit);e?(this.backContext.drawImage(this.element,0,0),this.context.globalAlpha=0,this.fadeLoop(t,i||0)):(this.context.globalAlpha=1,this.context.drawImage(t,s.left,s.top,s.width,s.height)),this.image=t}fadeLoop(t,e){if(this.context.globalAlpha>=1){cancelAnimationFrame(this.requestAnimationId),this.requestAnimationId=void 0;return}const i=Math.min(this.context.globalAlpha+e,1),s=y.fit(new f(t.width,t.height),new f(this.element.width,this.element.height),this.fit);this.context.clearRect(0,0,this.element.width,this.element.height),this.context.globalAlpha=1,this.context.drawImage(this.backCanvas,0,0),this.context.globalAlpha=i,this.context.drawImage(t,s.left,s.top,s.width,s.height),this.requestAnimationId=requestAnimationFrame(()=>{this.fadeLoop(t,e)})}}class Y{constructor(){this.element=document.createElement("canvas"),this.element.classList.add("ls-viewer-canvas"),this.element.style.opacity="0",this.element.width=0,this.element.height=0,this.context=x.getContext(this.element,{preserveDrawingBuffer:!0}),this.context&&this.context.isContextLost()&&(this.context=void 0),x.setDefaults({textureColor:[1,1,1,1]})}show(){this.element.style.opacity="1"}hide(){this.element.style.opacity="0"}resize(t,e,i){this.element.width=t*i,this.element.height=e*i,this.element.style.width=`${t}px`,this.element.style.height=`${e}px`}}class g{static accelerate(t,e){const i=e||1.5;return Math.abs(t)**i*(t>0?1:-1)}static clamp(t,e,i){return Math.max(Math.min(t,i),e)}static degreesToRadians(t){return t*(Math.PI/180)}static radiansToDegrees(t){return t*(180/Math.PI)}static mod(t,e){return t-e*Math.floor(t/e)}static perspectiveWithFovX(t,e,i,s,r){const a=Math.tan(t/2),n=a/e;return this.perspectiveWithLeft(-a,a,-n,n,i,s,r)}static perspectiveWithFovY(t,e,i,s,r){const a=i*Math.tan(t/2),n=a*e;return this.perspectiveWithLeft(-n,n,-a,a,i,s,r)}static perspectiveWithLeft(t,e,i,s,r,a,n){n=n||new Float32Array(16);const o=e+t,u=e-t,d=s+i,w=s-i,c=a-r;return n[0]=2*r/u,n[1]=0,n[2]=0,n[3]=0,n[4]=0,n[5]=2*r/w,n[6]=0,n[7]=0,n[8]=o/u,n[9]=d/w,n[10]=-a/c,n[11]=-1,n[12]=0,n[13]=0,n[14]=-a*r/c,n[15]=0,n}}const F=class F{static initCubeFace(t,e,i){let s=[0,0,0];const r=h.v3.subtract(e,t),a=h.v3.mulScalar([0,1,0],h.v3.length(r)),n=h.v3.mulScalar(h.v3.normalize(h.v3.cross(r,a)),h.v3.length(r)),o=h.v3.mulScalar(h.v3.normalize(h.v3.cross(a,n)),h.v3.length(r));switch(i){case"front":e=h.v3.add(t,o),s=h.v3.normalize(a);break;case"right":e=h.v3.add(t,n),s=h.v3.normalize(a);break;case"back":e=h.v3.subtract(t,o),s=h.v3.normalize(a);break;case"left":e=h.v3.subtract(t,n),s=h.v3.normalize(a);break;case"up":e=h.v3.add(t,a),s=h.v3.normalize(h.v3.mulScalar(o,-1));break;case"down":e=h.v3.subtract(t,a),s=h.v3.normalize(o);break}return new F(e,t,s)}constructor(t,e,i){this.target=h.v3.copy(t),this.eye=h.v3.copy(e),this.up=h.v3.copy(i)}get viewVector(){return h.v3.subtract(this.target,this.eye)}get rightVector(){return h.v3.normalize(h.v3.cross(this.viewVector,this.up))}get viewMatrix(){return h.m4.inverse(h.m4.lookAt(this.eye,this.target,this.up))}clone(){return new F(h.v3.copy(this.target),h.v3.copy(this.eye),h.v3.copy(this.up))}};F.default=new F([0,0,0],[2,2,2],[0,1,0]);let S=F;class Q{constructor(t){this.target=t.target;const e=h.v3.normalize(h.v3.subtract(t.eye,t.target)),i=h.v3.dot(e,[1,0,0]),s=h.v3.dot(e,[0,1,0]),r=h.v3.dot(e,[0,0,1]);this.longitude=Math.atan2(i,r),this.latitude=Math.atan2(s,Math.sqrt(i*i+r*r)),h.v3.dot(t.up,[0,1,0])<0&&(this.longitude=Math.PI+this.longitude,this.latitude=Math.PI-this.latitude),this.distance=h.v3.length(h.v3.subtract(t.target,t.eye))}get vector(){const t=Math.cos(this.latitude)*this.distance,e=Math.sin(this.latitude)*this.distance,i=Math.cos(this.longitude)*t,s=Math.sin(this.longitude)*t;return[i,e,s]}pointOfView(t){const e=h.m4.rotationY(this.longitude),i=h.m4.rotationX(-this.latitude),s=h.m4.rotationZ(0),r=h.m4.multiply(e,h.m4.multiply(i,s));let a=[0,0,-1];a=h.m4.transformPoint(r,a);let n=[0,1,0];n=h.m4.transformPoint(r,n);const o=h.v3.subtract(t,h.v3.mulScalar(a,this.distance));return new S(t,o,n)}}class W{constructor(){}async animation(t){return t.scene}async database(t){throw new Error("Unavailable")}async image(t){return t.scene}async video(t){return t.scene}async vrCube(t){return t.scene}async vrObject(t){return t.scene}}class j{constructor(t){this.xmlDoc=t}get id(){return this.xmlDoc.getElementsByTagName("Database")[0]?.getAttribute("id")}getCameraId(t,e){return e?this.xmlDoc.querySelector(`RootCameraGroup Group[name="${e}"] Camera[name="${t}"]`)?.getAttribute("id"):this.xmlDoc.querySelector(`RootCameraGroup Camera[name="${t}"]`)?.getAttribute("id")}getCameraById(t,e){let i;return t&&e?i=this.xmlDoc.querySelector(`RootCameraGroup Group[id="${e}"] Camera[id="${t}"]`):i=this.xmlDoc.querySelector(`RootCameraGroup Camera[id="${t}"]`),i?this.mapElementToCamera(i):null}getCameraByName(t,e){let i;return e&&t?i=this.xmlDoc.querySelector(`RootCameraGroup Group[name="${e}"] Camera[name="${t}"]`):i=this.xmlDoc.querySelector(`RootCameraGroup Camera[name="${t}"]`),i?this.mapElementToCamera(i):null}getCameraGroupId(t){return this.xmlDoc.querySelector(`RootCameraGroup Group[name="${t}"]`)?.getAttribute("id")}getCameraGroupById(t){const e=this.xmlDoc.querySelector(`RootCameraGroup Group[id="${t}"]`);return e?this.mapElementToCameraGroup(e):null}getCameraGroupByName(t){const e=this.xmlDoc.querySelector(`RootCameraGroup Group[name="${t}"]`);return e?this.mapElementToCameraGroup(e):null}mapElementToCamera(t){return{id:t.getAttribute("id"),name:t.getAttribute("name"),pointOfView:new S([parseFloat(t.querySelector("PointOfView Target").getAttribute("x")),parseFloat(t.querySelector("PointOfView Target").getAttribute("y")),parseFloat(t.querySelector("PointOfView Target").getAttribute("z"))],[parseFloat(t.querySelector("PointOfView Eye").getAttribute("x")),parseFloat(t.querySelector("PointOfView Eye").getAttribute("y")),parseFloat(t.querySelector("PointOfView Eye").getAttribute("z"))],[parseFloat(t.querySelector("PointOfView Up").getAttribute("x")),parseFloat(t.querySelector("PointOfView Up").getAttribute("y")),parseFloat(t.querySelector("PointOfView Up").getAttribute("z"))])}}mapElementToCameraGroup(t){return{id:t.getAttribute("id"),name:t.getAttribute("name"),cameras:[...t.querySelectorAll("Camera")].map(e=>this.mapElementToCamera(e))}}}const v=class v{constructor(t){this.server=t}static buildQuery(t){return Object.entries(t).filter(([e,i])=>i!=null).map(([e,i])=>`${e}=${i}`).join("&")}static sceneParameters(t){const e=t.scene,i=e.length>1?e.find(a=>a.accessory):null,s=e.length>1?e.find(a=>a.decor):null,r=e.find(a=>a!==i&&a!==s);return{databaseId:r.database,configuration:r?.configuration,animations:r?.animations?.join("/"),accessoryDatabaseId:i?.database,decorDatabaseId:s?.database,decorDeltaAltitude:s?.translation?.y}}static renderParameters(t){const{parameters:e,view:i}=t;return{background:i.background,width:e.width,height:e.height,softwareAntialiasing:e.antialiasing,superSampling:e.superSampling}}static encoderParameters(t){const{encoder:e}=t;return{imageFormat:e.format,imageQuality:e.quality}}static async fetch(t){return fetch(t).then(e=>e.text()).then(e=>{const s=e.replace(/&/g,"&").match(this.xmlRegex);return s?s.map(r=>r.replace(this.xmlRegex,"$1")):Promise.reject()})}async animation(t){const e={...v.sceneParameters(t),animation:t.view.animation,bookmarkSet:t.view.camera.split("/")[0],bookmark:t.view.camera.split("/")[1],frames:t.view.frames,loop:!!t.view.loop,...v.renderParameters(t),...v.encoderParameters(t)},i=v.buildQuery(e);return v.fetch(`${this.server}/ImagesFromAnimation?${i}`)}async database(t){return fetch(`${this.server}/Database?databaseId=${t}`).then(e=>e.text()).then(e=>{const i=new DOMParser().parseFromString(e,"application/xml");return new j(i)})}async image(t){const e={...v.sceneParameters(t),bookmarkSet:t.view.camera.split("/")[0],bookmark:t.view.camera.split("/")[1],...v.renderParameters(t),...v.encoderParameters(t)},i=v.buildQuery(e);return Promise.resolve(`${this.server}/ImageFromBookmark?${i}`)}async video(t){const e={...v.sceneParameters(t),animation:t.view.animation,bookmarkSet:t.view.camera.split("/")[0],bookmark:t.view.camera.split("/")[1],duration:t.view.duration,frames:t.view.frames,loop:!!t.view.loop,reverse:!!t.view.reverse,...v.renderParameters(t),...v.encoderParameters(t)},i=v.buildQuery(e);return Promise.resolve(`${this.server}/ImagesFromAnimation?${i}`)}async vrCube(t){const e={...v.sceneParameters(t),bookmarkSet:t.view.camera.split("/")[0],bookmark:t.view.camera.split("/")[1],...v.renderParameters(t),...v.encoderParameters(t)};e.width=Math.max(e.width,e.height),e.height=Math.max(e.width,e.height);const i=v.buildQuery(e);return v.fetch(`${this.server}/CubeFromBookmark?${i}`)}async vrObject(t){const e={...v.sceneParameters(t),bookmarkSet:t.view.camera,...v.renderParameters(t),...v.encoderParameters(t)},i=v.buildQuery(e);return v.fetch(`${this.server}/ImagesFromBookmarkSet?${i}`)}};v.xmlRegex=/directUrl="([^"]*)"/g;let A=v;class m{constructor(t){this.server=t}static scene(t){return t.scene.map(e=>{const{accessory:i,decor:s,...r}=e;return r})}static renderParameters(t){return{...t.parameters,superSampling:t.parameters.superSampling.toString()}}static encoder(t){switch(t.encoder.format){case"jpeg":return{jpeg:{quality:t.encoder.quality}};case"png":return{png:{compression:t.encoder.compression}};case"webp":return{webp:{quality:t.encoder.quality}}}return{jpeg:{quality:80}}}static async fetchFrame(t,e){return fetch(t,{method:"POST",body:JSON.stringify(e)}).then(i=>i.json()).then(i=>i.url)}static async fetchFrameArray(t,e){return fetch(t,{method:"POST",body:JSON.stringify(e)}).then(i=>i.json()).then(i=>i.map(s=>s.url))}static async fetchHotspots(t,e){return fetch(t,{method:"POST",body:JSON.stringify(e)}).then(i=>i.json())}static async fetchHotspotsArray(t,e){return fetch(t,{method:"POST",body:JSON.stringify(e)}).then(i=>i.json())}static async fetchPick(t,e){return fetch(t,{method:"POST",body:JSON.stringify(e)}).then(i=>i.json()).then(i=>i[0])}async database(t){return fetch(`${this.server}/Database?databaseId=${t}`).then(e=>e.text()).then(e=>{const i=new DOMParser().parseFromString(e,"application/xml");return new j(i)})}async image(t){const e={scene:m.scene(t),mode:{image:{camera:t.view.camera}},renderParameters:m.renderParameters(t),encoder:m.encoder(t)};return m.fetchFrame(`${this.server}/Snapshot`,e)}async vrCube(t){const e={scene:m.scene(t),mode:{vrCube:{camera:t.view.camera}},renderParameters:m.renderParameters(t),encoder:m.encoder(t)};return e.renderParameters.width=Math.max(e.renderParameters.width,e.renderParameters.height),e.renderParameters.height=Math.max(e.renderParameters.width,e.renderParameters.height),m.fetchFrameArray(`${this.server}/Snapshot`,e)}async vrObject(t){let e;t.view.cameraGroup?e={images:{cameraGroup:t.view.cameraGroup}}:t.view.frames?e={vrObject:{camera:t.view.camera,frames:t.view.frames}}:e={vrObject:{camera:t.view.camera,panFrames:t.view.panFrames||1,panFrom:t.view.panFrom||0,panTo:t.view.panTo||0,panLoop:t.view.panLoop||!1,tiltFrames:t.view.tiltFrames||1,tiltFrom:t.view.tiltFrom||0,tiltTo:t.view.tiltTo||0,tiltLoop:t.view.tiltLoop||!1}};const i={scene:m.scene(t),mode:e,renderParameters:m.renderParameters(t),encoder:m.encoder(t)};return m.fetchFrameArray(`${this.server}/Snapshot`,i)}async animation(t){const e={scene:m.scene(t),mode:{animation:{id:t.view.animation,camera:t.view.camera,fps:t.view.fps}},renderParameters:m.renderParameters(t),encoder:m.encoder(t)};return m.fetchFrameArray(`${this.server}/Snapshot`,e)}async imageHotspots(t,e){const i={scene:m.scene(t),mode:{image:{camera:t.view.camera}},renderParameters:m.renderParameters(t),...this.hotspotsBody(e)};return await m.fetchHotspots(`${this.server}/Hotspot`,i)}async imagePick(t,e){const i={scene:m.scene(t),camera:t.view.camera,renderParameters:m.renderParameters(t),positions:[e]};return await m.fetchPick(`${this.server}/Pick`,i)}async vrCubeHotspots(t,e){const i={scene:m.scene(t),mode:{vrCube:{camera:t.view.camera}},renderParameters:m.renderParameters(t),...this.hotspotsBody(e)};return i.renderParameters.width=Math.max(i.renderParameters.width,i.renderParameters.height),i.renderParameters.height=Math.max(i.renderParameters.width,i.renderParameters.height),await m.fetchHotspotsArray(`${this.server}/Hotspot`,i)}async vrObjectHotspots(t,e){let i;t.view.cameraGroup?i={images:{cameraGroup:t.view.cameraGroup}}:t.view.frames?i={vrObject:{camera:t.view.camera,frames:t.view.frames}}:i={vrObject:{camera:t.view.camera,panFrames:t.view.panFrames||1,panFrom:t.view.panFrom||0,panTo:t.view.panTo||0,panLoop:t.view.panLoop||!1,tiltFrames:t.view.tiltFrames||1,tiltFrom:t.view.tiltFrom||0,tiltTo:t.view.tiltTo||0,tiltLoop:t.view.tiltLoop||!1}};const s={scene:m.scene(t),mode:i,renderParameters:m.renderParameters(t),...this.hotspotsBody(e)};return await m.fetchHotspotsArray(`${this.server}/Hotspot`,s)}hotspotsBody(t){return{positions:t.every(e=>typeof e!="string")?t:void 0,tags:t.every(e=>typeof e=="string")?t:void 0}}}class k{constructor(t,e,i){switch(e){case"static":this.webrender=new W;break;case"v1":this.webrender=new A(t),this.webrenderV2=new m(t);break;case"v2":this.webrender=new m(t),this.webrenderV2=new m(t);break;default:this.webrender=new A(t),this.webrenderV2=new m(t);break}this.delegate=i,this.loadingId=0,this.loaded=0,this.total=0,this.databases=[],this.onLoadStart=i&&i.onLoadStart?i.onLoadStart:()=>{},this.onLoadProgress=i&&i.onLoadProgress?i.onLoadProgress:()=>{},this.onLoadEnd=i&&i.onLoadEnd?i.onLoadEnd:()=>{}}get progress(){return this.total?this.loaded/this.total:0}async loadImageSnapshot(t){this.loadingId+=1,this.loaded=0,this.total=1,this.onLoadStart(this.progress);const{loadingId:e}=this;return this.webrender.image(t).then(i=>this.loadImage(i,e)).then(i=>(this.onLoadEnd(this.progress),i))}async loadVideoSnapshot(t,e){this.loadingId+=1,this.loaded=0,this.total=1,this.onLoadStart(this.progress);const{loadingId:i}=this;return this.webrender.video(e).then(s=>this.loadVideo(t,s,!!e.view.loop,i)).then(()=>(this.onLoadEnd(this.progress),t))}async loadVRCubeSnapshot(t){this.loadingId+=1,this.loaded=0,this.total=0,this.onLoadStart(this.progress);const{loadingId:e}=this;return this.webrender.vrCube(t).then(i=>{this.total=i.length;const s=i.map(r=>this.loadImage(r,e));return Promise.all(s)}).then(i=>(this.onLoadEnd(this.progress),i))}async loadVRObjectSnapshot(t,e){this.loadingId+=1,this.loaded=0,this.total=0,this.onLoadStart(this.progress);const{loadingId:i}=this;return t.view.animation?t.encoder?.format==="mp4"?this.webrender.video(t).then(s=>this.loadVideoFrames(s,t.view.frames,30,i)):this.webrender.animation(t).then(s=>this.loadImageFrames(s,t.view.loop,e,i)):this.webrender.vrObject(t).then(s=>this.loadImageFrames(s,t.view.loop,e,i))}async loadImage(t,e){const i=new Image;i.crossOrigin=location.protocol==="file:"&&!k.isValidHttpUrl(t)?null:"anonymous";const s=new Promise((r,a)=>{i.addEventListener("load",()=>{e===this.loadingId&&(this.loaded+=1,this.onLoadProgress(this.progress),r(i))},{once:!0}),i.addEventListener("error",n=>{e===this.loadingId&&a(`${n.type} : ${t}`)},{once:!0})});return i.src=t,s}loadImageFrames(t,e,i,s){this.total=t.length;const r=new Array(t.length),a=i||0;for(let n=0,o=t.length;n<o;n+=1){const u=Math.ceil(n/2)*(n%2===0?1:-1),d=e?g.mod(a+u,o):n;r[d]=this.loadImage(t[d],s)}return Promise.all(r).then(()=>this.onLoadEnd(this.progress)).catch(()=>{}),r}async loadVideo(t,e,i,s){t.loop=i;const r=new Promise((a,n)=>{t.addEventListener("canplaythrough",()=>{s===this.loadingId&&(this.loaded+=1,this.onLoadProgress(this.progress),a())},{once:!0}),t.addEventListener("error",o=>{s===this.loadingId&&n(`${o.type} : ${e}`)},{once:!0})});return t.src=e,t.load(),r}async loadVideoFrame(t,e,i,s,r){let a=0;return new Promise((n,o)=>{const u=()=>{if(r!==this.loadingId)return;if(a!==s){a+=1;return}t.removeEventListener("seeked",u);const d=document.createElement("canvas");d.width=t.videoWidth,d.height=t.videoHeight,d.getContext("2d").drawImage(t,0,0);const c=new Image;c.src=d.toDataURL(),n(c),this.loaded+=1,this.onLoadProgress(this.progress),s!==i-1&&(t.currentTime+=1/e)};t.addEventListener("seeked",u),t.addEventListener("error",d=>{r===this.loadingId&&o(d)},{once:!0})})}loadVideoFrames(t,e,i,s){this.total=e;const r=new Array(e),a=document.createElement("video");for(let n=0,o=e;n<o;n+=1)r[n]=this.loadVideoFrame(a,i,e,n,s);return a.addEventListener("canplaythrough",()=>{s===this.loadingId&&(a.currentTime=1/i/2)},{once:!0}),a.src=t,a.load(),Promise.all(r).then(()=>this.onLoadEnd(this.progress)).catch(()=>{}),r}async loadImageHotspots(t,e){return this.webrenderV2?await this.webrenderV2.imageHotspots(await this.convert(t),e):Promise.reject(new Error("Hotspots only available with api V2"))}async loadVRCubeHotspots(t,e){return this.webrenderV2?await this.webrenderV2.vrCubeHotspots(await this.convert(t),e):Promise.reject(new Error("Hotspots only available with api V2"))}async loadVRObjectHotspots(t,e){return this.webrenderV2?await this.webrenderV2.vrObjectHotspots(await this.convert(t),e):Promise.reject(new Error("Hotspots only available with api V2"))}async loadImagePick(t,e){return this.webrenderV2?await this.webrenderV2.imagePick(await this.convert(t),e):Promise.reject(new Error("Picking only available with api V2"))}async loadVRObjectPick(t,e,i,s){return this.webrenderV2?await this.webrenderV2.imagePick(await this.vrObjectFrameSnapshot(t,i,s),e):Promise.reject(new Error("Picking only available with api V2"))}async loadVRCubePick(t,e,i){return this.webrenderV2?await this.webrenderV2.imagePick(await this.vrCubeFrameSnapshot(t,i),e):Promise.reject(new Error("Picking only available with api V2"))}async convert(t){if(!this.webrenderV2||this.webrender instanceof m||!t.view.camera)return t;const e=t.scene.find(o=>!o.decor&&!o.accessory);if(!e)return t;let i=this.databases.find(o=>o.id===e.database);(!i||!i.xmlDoc)&&(i=await this.webrender.database(e.database),this.databases.push(i));const s=t.view.camera.split("/"),r=s.length===2?s[0]:void 0,a=s.length===2?s[1]:s[0],n=i.getCameraId(a,r);if(n)return{...t,view:{...t.view,camera:n}};{const o=i.getCameraGroupId(a);return o?{...t,view:{...t.view,cameraGroup:o}}:t}}async vrObjectFrameSnapshot(t,e,i){if(!this.webrenderV2)return t;const s=t.scene.find(a=>!a.decor&&!a.accessory);if(!s)return t;let r=this.databases.find(a=>a.id===s.database);if(r||(r=await this.webrender.database(s.database),this.databases.push(r)),this.webrender instanceof A){if(!t.view.camera)return t;const a=r.getCameraGroupId(t.view.camera);if(!a)return t;const n=r.getCameraGroupById(a);if(!n)return t;const o=n.cameras[e];return o?{...t,view:{...t.view,camera:o.id}}:t}else if(this.webrender instanceof m){const a=typeof t.view.camera=="string"?t.view.camera:t.view.camera?.id;if(a){const n=r.getCameraById(a);if(!n)return t;const o=new Q(n.pointOfView),u=2*Math.PI/i;o.longitude+=e*u%(2*Math.PI);const d=o.pointOfView(n.pointOfView.target);return{...t,view:{...t.view,camera:{id:n.id,pov:{target:{x:d.target[0],y:d.target[1],z:d.target[2]},eye:{x:d.eye[0],y:d.eye[1],z:d.eye[2]},up:{x:d.up[0],y:d.up[1],z:d.up[2]}}}}}}else if(t.view.cameraGroup){const n=r.getCameraGroupById(t.view.cameraGroup);if(!n)return t;const o=n.cameras[e];return o?{...t,view:{...t.view,camera:o.id}}:t}else return t}else return t}async vrCubeFrameSnapshot(t,e){const i=t.scene.find(o=>!o.decor&&!o.accessory);if(!i)return t;let s=this.databases.find(o=>o.id===i.database);if(s||(s=await this.webrender.database(i.database),this.databases.push(s)),!t.view.camera)return t;let r;if(this.webrender instanceof A){const o=t.view.camera.split("/"),u=o.length===2?o[0]:void 0,d=o.length===2?o[1]:o[0];r=s.getCameraId(d,u)}else this.webrender instanceof m&&(r=typeof t.view.camera=="string"?t.view.camera:t.view.camera.id);if(!r)return t;const a=s.getCameraById(r);if(!a)return t;const n=S.initCubeFace(a.pointOfView.eye,a.pointOfView.target,e);return{...t,view:{...t.view,camera:{id:a.id,pov:{target:{x:n.target[0],y:n.target[1],z:n.target[2]},eye:{x:n.eye[0],y:n.eye[1],z:n.eye[2]},up:{x:n.up[0],y:n.up[1],z:n.up[2]}},lens:{fov:90}}},parameters:{...t.parameters,width:Math.max(t.parameters.width,t.parameters.height),height:Math.max(t.parameters.width,t.parameters.height)}}}onLoadStart(t){this.delegate&&this.delegate.onLoadStart(t)}onLoadProgress(t){this.delegate&&this.delegate.onLoadProgress(t)}onLoadEnd(t){this.delegate&&this.delegate.onLoadEnd(t)}static isValidHttpUrl(t){let e;try{e=new URL(t)}catch{return!1}return e.protocol==="http:"||e.protocol==="https:"}}class J{constructor(){this.element=document.createElement("video"),this.element.classList.add("ls-viewer-video"),this.element.style.opacity="0",this.element.width=0,this.element.height=0,this.element.setAttribute("muted",""),this.element.setAttribute("playsinline",""),this.element.setAttribute("preload","auto")}show(){this.element.style.opacity="1"}hide(){this.element.style.opacity="0"}resize(t,e,i,s){const r=y.fit(i,new f(t,e),s);this.element.style.top=`${r.top}px`,this.element.style.left=`${r.left}px`,this.element.style.width=`${r.width}px`,this.element.style.height=`${r.height}px`,(i.width!==this.element.width||i.height!==this.element.height)&&(this.element.width=i.width,this.element.height=i.height)}}class q{constructor(t,e,i){this.container=t,this.canvas=e,this.loader=i,this.hotspotList=[]}destroy(){}show(){this.canvas.show(!1),this.container.classList.add("ls-viewer-container-image")}hide(){this.canvas.hide(!1),this.container.classList.remove("ls-viewer-container-image")}async load(t,e,i,s){let r=Promise.resolve();const a=JSON.stringify(t);a===this.snapshotHash&&this.image?r=r.then(()=>this.canvas.draw(this.image,s,.05)):r=r.then(()=>this.loader.loadImageSnapshot(t).then(o=>{this.canvas.draw(o,s,.05),this.image=o}));const n=JSON.stringify(e);return(a!==this.snapshotHash||n!==this.hotspotsHash)&&(e.length?r=r.then(()=>this.loader.loadImageHotspots(t,e).then(o=>{this.hotspotList=o})):this.hotspotList=[]),this.hotspotsHash=n,this.snapshotHash=a,r}async pick(t,e){const i=new f(t.parameters.width,t.parameters.height),s=y.unproject(i,this.canvas.resolution,this.canvas.fit,e);return this.loader.loadImagePick(t,s)}hotspots(t){return this.hotspotList.map(e=>({...e,position2D:y.project(t,this.canvas.resolution,this.canvas.fit,e.position2D)})).map(e=>({...e,visibility:y.contains(this.canvas.resolution,e.position2D)?e.visibility:"OutOfFrustum"}))}snapshot(t,e){return this.canvas.element.toDataURL(t,e)}onMouseDown(t){}onMouseMove(t){}onMouseUp(t){}onMouseEnter(t){}onTouchStart(t){}onTouchMove(t){}onTouchEnd(t){}onDeviceOrientation(t){}}class I{constructor(t,e){this.x=t,this.y=e}clone(){return new I(this.x,this.y)}}class p{static pointFromMouseEvent(t){return new I(t.screenX,t.screenY)}static pointFromTouchEvent(t){const e=t.targetTouches[0]||t.changedTouches[0];return new I(e.screenX,e.screenY)}}class V{constructor(...t){t.length===3?({0:this.u,1:this.v,2:this.o}=t,this.w=h.v3.cross(this.u,this.v)):t.length===4?{0:this.u,1:this.v,2:this.w,3:this.o}=t:(this.u=[1,0,0],this.v=[0,1,0],this.w=[0,0,1],this.o=[0,0,0])}get localToGlobalMatrix(){const t=[this.u[0],this.u[1],this.u[2],0],e=[this.v[0],this.v[1],this.v[2],0],i=[this.w[0],this.w[1],this.w[2],0],s=[this.o[0],this.o[1],this.o[2],1];return[...t,...e,...i,...s]}get globalToLocalMatrix(){return h.m4.inverse(this.localToGlobalMatrix)}}class Z{constructor(t,e,i){this.x=t,this.y=e,this.time=i}}class R{constructor(t){this.points=[],this.onMotion=t,this.lastPoint=new I(0,0),this.velocity=new I(0,0),this.loop=this.loop.bind(this)}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0)}track(t){const e=Date.now();this.points=this.points.filter(i=>e-i.time<=100),this.points.push(new Z(t.x,t.y,e)),this.lastPoint=t}start(){if(this.points.length===0)return;const t=this.points[0],e=this.points[this.points.length-1],i=e.x-t.x,s=e.y-t.y,r=e.time-t.time;this.velocity=new I(r===0?0:i/(r/15),r===0?0:s/(r/15)),this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0),this.animationFrameId=requestAnimationFrame(this.loop)}stop(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0),this.points=[]}loop(){if(Math.abs(this.velocity.x)<1&&Math.abs(this.velocity.y)<1){this.animationFrameId=void 0,this.points=[];return}this.lastPoint.x+=this.velocity.x,this.lastPoint.y+=this.velocity.y,this.velocity.x*=.9,this.velocity.y*=.9,this.onMotion(this.lastPoint.clone()),this.animationFrameId=requestAnimationFrame(this.loop)}}class _{constructor(t,e,i){this.isStarted=!1,this.pov=t,this.fov=g.degreesToRadians(e),this.orientationMatrix=h.m4.identity(),this.inertia=new R(this.motion.bind(this)),this.onMotion=i,this.initPov=this.pov,this.initFov=this.fov,this.initOrientation=g.degreesToRadians(window.orientation)||0,this.startPov=new S([0,0,1],[0,0,0],[0,1,0]),this.startSize={width:0,height:0},this.previousPoint=new I(0,0)}destroy(){this.inertia.destroy()}get orientedPov(){const t=h.v3.normalize(h.v3.cross(this.pov.up,this.pov.target)),e=new V(t,[0,1,0],this.pov.eye),i=h.m4.identity();h.m4.multiply(i,e.localToGlobalMatrix,i),h.m4.multiply(i,this.orientationMatrix,i),h.m4.multiply(i,e.globalToLocalMatrix,i);const s=h.m4.transformDirection(i,this.pov.target),r=this.pov.eye,a=h.m4.transformDirection(i,this.pov.up);return new S(s,r,a)}reset(){this.pov=this.initPov.clone(),this.fov=this.initFov}start(t,e){this.isStarted=!0,this.startPov=this.pov,this.startSize=e,this.previousPoint=t,this.inertia.stop()}motion(t){this.isStarted&&this.inertia.track(t);const e={x:t.x-this.previousPoint.x,y:t.y-this.previousPoint.y},i=g.accelerate(e.x,1.3)/this.startSize.width*.2*Math.PI*1.5,s=g.accelerate(e.y,1.3)/this.startSize.height*.2*Math.PI,r=h.m4.multiply(h.m4.rotationY(i),h.m4.rotationX(-s)),a=h.v3.normalize(h.v3.cross(this.pov.up,this.pov.target)),n=new V(a,[0,1,0],this.pov.eye),o=h.m4.identity();h.m4.multiply(o,n.localToGlobalMatrix,o),h.m4.multiply(o,r,o),h.m4.multiply(o,n.globalToLocalMatrix,o);const u=h.m4.transformPoint(o,this.pov.target),d=h.m4.transformDirection(o,this.pov.up);h.v3.cross(d,[0,0,1])[0]>=0&&(this.pov.target=u,this.pov.up=d),this.previousPoint=t,this.onMotion()}end(t,e){this.isStarted=!1,e&&(this.inertia.track(t),this.inertia.start())}orientation(t,e,i){const s=g.degreesToRadians(window.orientation)||0,r=g.degreesToRadians(t),a=g.degreesToRadians(-e),n=g.degreesToRadians(-i),o=h.m4.rotationX(g.degreesToRadians(90));h.m4.rotateZ(o,this.initOrientation,o),h.m4.rotateZ(o,r,o),h.m4.rotateX(o,a,o),h.m4.rotateY(o,n,o),h.m4.rotateZ(o,-s,o),this.orientationMatrix=o,this.onMotion()}}var K=`precision mediump float;
|
|
1
|
+
(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".ls-viewer-container{display:block;position:relative;overflow:hidden;-webkit-user-select:none;user-select:none;width:100%;height:100%}.ls-viewer-container-image,.ls-viewer-container-video{cursor:default;pointer-events:none}.ls-viewer-container-vrcube{cursor:pointer;cursor:grab;touch-action:none}.ls-viewer-container-vrcube-grabbing{cursor:move;cursor:grabbing}.ls-viewer-container-vrobject{cursor:move;cursor:grab;touch-action:none}.ls-viewer-container-vrobject-grabbing{cursor:move;cursor:grabbing}.ls-viewer-container-loading{cursor:progress}.ls-viewer-canvas{position:absolute;opacity:0;transition:opacity .5s}.ls-viewer-video{position:absolute}")),document.head.appendChild(e)}}catch(r){console.error("vite-plugin-css-injected-by-js",r)}})();
|
|
2
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=require("debounce-promise"),h=require("twgl.js"),N=require("regression");function U(u){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(u){for(const e in u)if(e!=="default"){const i=Object.getOwnPropertyDescriptor(u,e);Object.defineProperty(t,e,i.get?i:{enumerable:!0,get:()=>u[e]})}}return t.default=u,Object.freeze(t)}const M=U(h);class y{constructor(t,e){this.width=t,this.height=e}get aspect(){return this.width/this.height}}const P=class P{constructor(t,e,i,r){this.top=t,this.left=e,this.width=i,this.height=r}static contains(t,e){return e.x>=0&&e.x<t.width&&e.y>=0&&e.y<t.height}static fit(t,e,i){const r=t.aspect,s=e.aspect;let a=0,n=0;switch(i){case"contain":a=s<r?e.width:e.height*r,n=s<r?e.width/r:e.height;break;case"cover":default:a=s<r?e.height*r:e.width,n=s<r?e.height:e.width/r;break;case"fill":a=e.width,n=e.height;break}const o=(e.height-n)/2,l=(e.width-a)/2;return new P(o,l,a,n)}static project(t,e,i,r){const s=P.fit(t,e,i),a=s.width/t.width,n=s.height/t.height;return{x:Math.round(s.left+r.x*a),y:Math.round(s.top+r.y*n)}}static unproject(t,e,i,r){const s=P.fit(t,e,i),a=s.width/t.width,n=s.height/t.height;return{x:Math.round((r.x-s.left)/a),y:Math.round((r.y-s.top)/n)}}static getStandardAspectRatio(t,e,i){if(t===0||e===0)return 0;if(i)return i;const r=t/e;return t<e?r<P.PORTRAIT_ASPECT_BOUNDARY?9/16:3/4:r<P.LANDSCAPE_ASPECT_BOUNDARY?4/3:16/9}static getStandardResolution(t,e,i){if(t===0||e===0)return new y(0,0);const r=P.getStandardAspectRatio(t,e,i);if(i){const a=P.getStandardQuality(Math.min(t,e));return new y(Math.round(a*r),Math.round(a))}if(t<e){const a=P.getStandardQuality(Math.max(e*r,t));return new y(Math.round(a),Math.round(a/r))}const s=P.getStandardQuality(Math.max(t/r,e));return new y(Math.round(s*r),Math.round(s))}static getStandardQuality(t){return t<=720?720:1080}};P.LANDSCAPE_ASPECT_BOUNDARY=Math.sqrt(4/3*(16/9)),P.PORTRAIT_ASPECT_BOUNDARY=Math.sqrt(3/4*(9/16));let b=P;class B{constructor(t){this.element=document.createElement("canvas"),this.element.classList.add("ls-viewer-canvas"),this.element.style.opacity="0",this.element.width=0,this.element.height=0,this.context=this.element.getContext("2d"),this.context.imageSmoothingQuality="high",this.backCanvas=document.createElement("canvas"),this.backContext=this.backCanvas.getContext("2d"),this.backContext.imageSmoothingQuality="high",this.fit=t}destroy(){this.requestAnimationId&&(cancelAnimationFrame(this.requestAnimationId),this.requestAnimationId=void 0)}show(t){t?this.element.style.display="block":this.element.style.opacity="1"}hide(t){t?this.element.style.display="none":this.element.style.opacity="0"}resize(t,e,i){const r=Math.floor(t*i),s=Math.floor(e*i);this.element.style.width=`${t}px`,this.element.style.height=`${e}px`,!(this.element.width===r&&this.element.height===s)&&(this.element.width=r,this.element.height=s,this.context.imageSmoothingQuality="high",this.backCanvas.width=r,this.backCanvas.height=s,this.backContext.imageSmoothingQuality="high",this.image&&this.draw(this.image,!1))}draw(t,e,i){if(!t)return;this.requestAnimationId&&(cancelAnimationFrame(this.requestAnimationId),this.requestAnimationId=void 0);const r=b.fit(new y(t.width,t.height),new y(this.element.width,this.element.height),this.fit);e?(this.backContext.drawImage(this.element,0,0),this.context.globalAlpha=0,this.fadeLoop(t,i||0)):(this.context.globalAlpha=1,this.context.drawImage(t,r.left,r.top,r.width,r.height)),this.image=t}fadeLoop(t,e){if(this.context.globalAlpha>=1){cancelAnimationFrame(this.requestAnimationId),this.requestAnimationId=void 0;return}const i=Math.min(this.context.globalAlpha+e,1),r=b.fit(new y(t.width,t.height),new y(this.element.width,this.element.height),this.fit);this.context.clearRect(0,0,this.element.width,this.element.height),this.context.globalAlpha=1,this.context.drawImage(this.backCanvas,0,0),this.context.globalAlpha=i,this.context.drawImage(t,r.left,r.top,r.width,r.height),this.requestAnimationId=requestAnimationFrame(()=>{this.fadeLoop(t,e)})}}class X{constructor(){this.element=document.createElement("canvas"),this.element.classList.add("ls-viewer-canvas"),this.element.style.opacity="0",this.element.width=0,this.element.height=0,this.context=M.getContext(this.element,{preserveDrawingBuffer:!0}),this.context&&this.context.isContextLost()&&(this.context=void 0),M.setDefaults({textureColor:[1,1,1,1]})}show(){this.element.style.opacity="1"}hide(){this.element.style.opacity="0"}resize(t,e,i){this.element.width=t*i,this.element.height=e*i,this.element.style.width=`${t}px`,this.element.style.height=`${e}px`}}class w{static accelerate(t,e){const i=e||1.5;return Math.abs(t)**i*(t>0?1:-1)}static clamp(t,e,i){return Math.max(Math.min(t,i),e)}static degreesToRadians(t){return t*(Math.PI/180)}static radiansToDegrees(t){return t*(180/Math.PI)}static mod(t,e){return t-e*Math.floor(t/e)}static perspectiveWithFovX(t,e,i,r,s){const a=Math.tan(t/2),n=a/e;return this.perspectiveWithLeft(-a,a,-n,n,i,r,s)}static perspectiveWithFovY(t,e,i,r,s){const a=i*Math.tan(t/2),n=a*e;return this.perspectiveWithLeft(-n,n,-a,a,i,r,s)}static perspectiveWithLeft(t,e,i,r,s,a,n){n=n||new Float32Array(16);const o=e+t,l=e-t,m=r+i,v=r-i,c=a-s;return n[0]=2*s/l,n[1]=0,n[2]=0,n[3]=0,n[4]=0,n[5]=2*s/v,n[6]=0,n[7]=0,n[8]=o/l,n[9]=m/v,n[10]=-a/c,n[11]=-1,n[12]=0,n[13]=0,n[14]=-a*s/c,n[15]=0,n}}const O=class O{static initCubeFace(t,e,i){let r=[0,0,0];const s=h.v3.subtract(e,t),a=h.v3.mulScalar([0,1,0],h.v3.length(s)),n=h.v3.mulScalar(h.v3.normalize(h.v3.cross(s,a)),h.v3.length(s)),o=h.v3.mulScalar(h.v3.normalize(h.v3.cross(a,n)),h.v3.length(s));switch(i){case"front":e=h.v3.add(t,o),r=h.v3.normalize(a);break;case"right":e=h.v3.add(t,n),r=h.v3.normalize(a);break;case"back":e=h.v3.subtract(t,o),r=h.v3.normalize(a);break;case"left":e=h.v3.subtract(t,n),r=h.v3.normalize(a);break;case"up":e=h.v3.add(t,a),r=h.v3.normalize(h.v3.mulScalar(o,-1));break;case"down":e=h.v3.subtract(t,a),r=h.v3.normalize(o);break}return new O(e,t,r)}constructor(t,e,i){this.target=h.v3.copy(t),this.eye=h.v3.copy(e),this.up=h.v3.copy(i)}get viewVector(){return h.v3.subtract(this.target,this.eye)}get rightVector(){return h.v3.normalize(h.v3.cross(this.viewVector,this.up))}get viewMatrix(){return h.m4.inverse(h.m4.lookAt(this.eye,this.target,this.up))}clone(){return new O(h.v3.copy(this.target),h.v3.copy(this.eye),h.v3.copy(this.up))}};O.default=new O([0,0,0],[2,2,2],[0,1,0]);let I=O;class Y{constructor(t){this.target=t.target;const e=h.v3.normalize(h.v3.subtract(t.eye,t.target)),i=h.v3.dot(e,[1,0,0]),r=h.v3.dot(e,[0,1,0]),s=h.v3.dot(e,[0,0,1]);this.longitude=Math.atan2(i,s),this.latitude=Math.atan2(r,Math.sqrt(i*i+s*s)),h.v3.dot(t.up,[0,1,0])<0&&(this.longitude=Math.PI+this.longitude,this.latitude=Math.PI-this.latitude),this.distance=h.v3.length(h.v3.subtract(t.target,t.eye))}get vector(){const t=Math.cos(this.latitude)*this.distance,e=Math.sin(this.latitude)*this.distance,i=Math.cos(this.longitude)*t,r=Math.sin(this.longitude)*t;return[i,e,r]}pointOfView(t){const e=h.m4.rotationY(this.longitude),i=h.m4.rotationX(-this.latitude),r=h.m4.rotationZ(0),s=h.m4.multiply(e,h.m4.multiply(i,r));let a=[0,0,-1];a=h.m4.transformPoint(s,a);let n=[0,1,0];n=h.m4.transformPoint(s,n);const o=h.v3.subtract(t,h.v3.mulScalar(a,this.distance));return new I(t,o,n)}}class Q{constructor(){}async animation(t,e){return t.scene}async database(t){throw new Error("Unavailable")}async image(t,e){return t.scene}async video(t){return t.scene}async vrCube(t,e){return t.scene}async vrObject(t,e){return t.scene}}class V{constructor(t){this.xmlDoc=t}get id(){return this.xmlDoc.getElementsByTagName("Database")[0]?.getAttribute("id")}getCameraId(t,e){return e?this.xmlDoc.querySelector(`RootCameraGroup Group[name="${e}"] Camera[name="${t}"]`)?.getAttribute("id"):this.xmlDoc.querySelector(`RootCameraGroup Camera[name="${t}"]`)?.getAttribute("id")}getCameraById(t,e){let i;return t&&e?i=this.xmlDoc.querySelector(`RootCameraGroup Group[id="${e}"] Camera[id="${t}"]`):i=this.xmlDoc.querySelector(`RootCameraGroup Camera[id="${t}"]`),i?this.mapElementToCamera(i):null}getCameraByName(t,e){let i;return e&&t?i=this.xmlDoc.querySelector(`RootCameraGroup Group[name="${e}"] Camera[name="${t}"]`):i=this.xmlDoc.querySelector(`RootCameraGroup Camera[name="${t}"]`),i?this.mapElementToCamera(i):null}getCameraGroupId(t){return this.xmlDoc.querySelector(`RootCameraGroup Group[name="${t}"]`)?.getAttribute("id")}getCameraGroupById(t){const e=this.xmlDoc.querySelector(`RootCameraGroup Group[id="${t}"]`);return e?this.mapElementToCameraGroup(e):null}getCameraGroupByName(t){const e=this.xmlDoc.querySelector(`RootCameraGroup Group[name="${t}"]`);return e?this.mapElementToCameraGroup(e):null}mapElementToCamera(t){return{id:t.getAttribute("id"),name:t.getAttribute("name"),pointOfView:new I([parseFloat(t.querySelector("PointOfView Target").getAttribute("x")),parseFloat(t.querySelector("PointOfView Target").getAttribute("y")),parseFloat(t.querySelector("PointOfView Target").getAttribute("z"))],[parseFloat(t.querySelector("PointOfView Eye").getAttribute("x")),parseFloat(t.querySelector("PointOfView Eye").getAttribute("y")),parseFloat(t.querySelector("PointOfView Eye").getAttribute("z"))],[parseFloat(t.querySelector("PointOfView Up").getAttribute("x")),parseFloat(t.querySelector("PointOfView Up").getAttribute("y")),parseFloat(t.querySelector("PointOfView Up").getAttribute("z"))])}}mapElementToCameraGroup(t){return{id:t.getAttribute("id"),name:t.getAttribute("name"),cameras:[...t.querySelectorAll("Camera")].map(e=>this.mapElementToCamera(e))}}}const g=class g{constructor(t){this.server=t}static buildQuery(t){return Object.entries(t).filter(([e,i])=>i!=null).map(([e,i])=>`${e}=${i}`).join("&")}static sceneParameters(t){const e=t.scene,i=e.length>1?e.find(a=>a.accessory):null,r=e.length>1?e.find(a=>a.decor):null,s=e.find(a=>a!==i&&a!==r);return{databaseId:s.database,configuration:s?.configuration,animations:s?.animations?.join("/"),accessoryDatabaseId:i?.database,decorDatabaseId:r?.database,decorDeltaAltitude:r?.translation?.y}}static renderParameters(t){const{parameters:e,view:i}=t;return{background:i.background,width:e.width,height:e.height,softwareAntialiasing:e.antialiasing,superSampling:e.superSampling}}static encoderParameters(t){const{encoder:e}=t;return{imageFormat:e.format,imageQuality:e.quality}}static async fetch(t,e){return fetch(t,{signal:e}).then(i=>i.text()).then(i=>{const s=i.replace(/&/g,"&").match(this.xmlRegex);return s?s.map(a=>a.replace(this.xmlRegex,"$1")):Promise.reject()})}async animation(t,e){const i={...g.sceneParameters(t),animation:t.view.animation,bookmarkSet:t.view.camera.split("/")[0],bookmark:t.view.camera.split("/")[1],frames:t.view.frames,loop:!!t.view.loop,...g.renderParameters(t),...g.encoderParameters(t)},r=g.buildQuery(i);return g.fetch(`${this.server}/ImagesFromAnimation?${r}`,e)}async database(t){return fetch(`${this.server}/Database?databaseId=${t}`).then(e=>e.text()).then(e=>{const i=new DOMParser().parseFromString(e,"application/xml");return new V(i)})}async image(t,e){const i={...g.sceneParameters(t),bookmarkSet:t.view.camera.split("/")[0],bookmark:t.view.camera.split("/")[1],...g.renderParameters(t),...g.encoderParameters(t)},r=g.buildQuery(i);return Promise.resolve(`${this.server}/ImageFromBookmark?${r}`)}async video(t){const e={...g.sceneParameters(t),animation:t.view.animation,bookmarkSet:t.view.camera.split("/")[0],bookmark:t.view.camera.split("/")[1],duration:t.view.duration,frames:t.view.frames,loop:!!t.view.loop,reverse:!!t.view.reverse,...g.renderParameters(t),...g.encoderParameters(t)},i=g.buildQuery(e);return Promise.resolve(`${this.server}/ImagesFromAnimation?${i}`)}async vrCube(t,e){const i={...g.sceneParameters(t),bookmarkSet:t.view.camera.split("/")[0],bookmark:t.view.camera.split("/")[1],...g.renderParameters(t),...g.encoderParameters(t)};i.width=Math.max(i.width,i.height),i.height=Math.max(i.width,i.height);const r=g.buildQuery(i);return g.fetch(`${this.server}/CubeFromBookmark?${r}`,e)}async vrObject(t,e){const i={...g.sceneParameters(t),bookmarkSet:t.view.camera,...g.renderParameters(t),...g.encoderParameters(t)},r=g.buildQuery(i);return g.fetch(`${this.server}/ImagesFromBookmarkSet?${r}`,e)}};g.xmlRegex=/directUrl="([^"]*)"/g;let S=g;class d{constructor(t){this.server=t}static scene(t){return t.scene.map(e=>{const{accessory:i,decor:r,...s}=e;return s})}static renderParameters(t){return{...t.parameters,superSampling:t.parameters.superSampling.toString()}}static encoder(t){switch(t.encoder.format){case"jpeg":return{jpeg:{quality:t.encoder.quality}};case"png":return{png:{compression:t.encoder.compression}};case"webp":return{webp:{quality:t.encoder.quality}}}return{jpeg:{quality:80}}}static async fetchFrame(t,e,i){return fetch(t,{method:"POST",body:JSON.stringify(e),signal:i}).then(r=>r.json()).then(r=>r.url)}static async fetchFrameArray(t,e,i){return fetch(t,{method:"POST",body:JSON.stringify(e),signal:i}).then(r=>r.json()).then(r=>r.map(s=>s.url))}static async fetchHotspots(t,e){return fetch(t,{method:"POST",body:JSON.stringify(e)}).then(i=>i.json())}static async fetchHotspotsArray(t,e){return fetch(t,{method:"POST",body:JSON.stringify(e)}).then(i=>i.json())}static async fetchPick(t,e){return fetch(t,{method:"POST",body:JSON.stringify(e)}).then(i=>i.json()).then(i=>i[0])}async database(t){return fetch(`${this.server}/Database?databaseId=${t}`).then(e=>e.text()).then(e=>{const i=new DOMParser().parseFromString(e,"application/xml");return new V(i)})}async image(t,e){const i={scene:d.scene(t),mode:{image:{camera:t.view.camera}},renderParameters:d.renderParameters(t),encoder:d.encoder(t)};return d.fetchFrame(`${this.server}/Snapshot`,i,e)}async vrCube(t,e){const i={scene:d.scene(t),mode:{vrCube:{camera:t.view.camera}},renderParameters:d.renderParameters(t),encoder:d.encoder(t)};return i.renderParameters.width=Math.max(i.renderParameters.width,i.renderParameters.height),i.renderParameters.height=Math.max(i.renderParameters.width,i.renderParameters.height),d.fetchFrameArray(`${this.server}/Snapshot`,i,e)}async vrObject(t,e){let i;t.view.cameraGroup?i={images:{cameraGroup:t.view.cameraGroup}}:t.view.frames?i={vrObject:{camera:t.view.camera,frames:t.view.frames}}:i={vrObject:{camera:t.view.camera,panFrames:t.view.panFrames||1,panFrom:t.view.panFrom||0,panTo:t.view.panTo||0,panLoop:t.view.panLoop||!1,tiltFrames:t.view.tiltFrames||1,tiltFrom:t.view.tiltFrom||0,tiltTo:t.view.tiltTo||0,tiltLoop:t.view.tiltLoop||!1}};const r={scene:d.scene(t),mode:i,renderParameters:d.renderParameters(t),encoder:d.encoder(t)};return d.fetchFrameArray(`${this.server}/Snapshot`,r,e)}async animation(t,e){const i={scene:d.scene(t),mode:{animation:{id:t.view.animation,camera:t.view.camera,fps:t.view.fps}},renderParameters:d.renderParameters(t),encoder:d.encoder(t)};return d.fetchFrameArray(`${this.server}/Snapshot`,i,e)}async imageHotspots(t,e){const i={scene:d.scene(t),mode:{image:{camera:t.view.camera}},renderParameters:d.renderParameters(t),...this.hotspotsBody(e)};return await d.fetchHotspots(`${this.server}/Hotspot`,i)}async imagePick(t,e){const i={scene:d.scene(t),camera:t.view.camera,renderParameters:d.renderParameters(t),positions:[e]};return await d.fetchPick(`${this.server}/Pick`,i)}async vrCubeHotspots(t,e){const i={scene:d.scene(t),mode:{vrCube:{camera:t.view.camera}},renderParameters:d.renderParameters(t),...this.hotspotsBody(e)};return i.renderParameters.width=Math.max(i.renderParameters.width,i.renderParameters.height),i.renderParameters.height=Math.max(i.renderParameters.width,i.renderParameters.height),await d.fetchHotspotsArray(`${this.server}/Hotspot`,i)}async vrObjectHotspots(t,e){let i;t.view.cameraGroup?i={images:{cameraGroup:t.view.cameraGroup}}:t.view.frames?i={vrObject:{camera:t.view.camera,frames:t.view.frames}}:i={vrObject:{camera:t.view.camera,panFrames:t.view.panFrames||1,panFrom:t.view.panFrom||0,panTo:t.view.panTo||0,panLoop:t.view.panLoop||!1,tiltFrames:t.view.tiltFrames||1,tiltFrom:t.view.tiltFrom||0,tiltTo:t.view.tiltTo||0,tiltLoop:t.view.tiltLoop||!1}};const r={scene:d.scene(t),mode:i,renderParameters:d.renderParameters(t),...this.hotspotsBody(e)};return await d.fetchHotspotsArray(`${this.server}/Hotspot`,r)}hotspotsBody(t){return{positions:t.every(e=>typeof e!="string")?t:void 0,tags:t.every(e=>typeof e=="string")?t:void 0}}}class k{constructor(t,e,i){switch(e){case"static":this.webrender=new Q;break;case"v1":this.webrender=new S(t),this.webrenderV2=new d(t);break;case"v2":this.webrender=new d(t),this.webrenderV2=new d(t);break;default:this.webrender=new S(t),this.webrenderV2=new d(t);break}this.delegate=i,this.controller=new AbortController,this.loaded=0,this.total=0,this.databases=[],this.onLoadStart=i&&i.onLoadStart?i.onLoadStart:()=>{},this.onLoadProgress=i&&i.onLoadProgress?i.onLoadProgress:()=>{},this.onLoadEnd=i&&i.onLoadEnd?i.onLoadEnd:()=>{}}get progress(){return this.total?this.loaded/this.total:0}renew(){return this.controller.abort(),this.controller=new AbortController,this.controller.signal}async loadImageSnapshot(t){const e=this.renew();return this.loaded=0,this.total=1,this.onLoadStart(this.progress),this.webrender.image(t,e).then(i=>this.loadImage(i,e)).then(i=>(this.onLoadEnd(this.progress),i))}async loadVideoSnapshot(t,e){const i=this.renew();return this.loaded=0,this.total=1,this.onLoadStart(this.progress),this.webrender.video(e).then(r=>this.loadVideo(t,r,!!e.view.loop,i)).then(()=>(this.onLoadEnd(this.progress),t))}async loadVRCubeSnapshot(t){const e=this.renew();return this.loaded=0,this.total=0,this.onLoadStart(this.progress),this.webrender.vrCube(t,e).then(i=>{this.total=i.length;const r=i.map(s=>this.loadImage(s,e));return Promise.all(r)}).then(i=>(this.onLoadEnd(this.progress),i))}async loadVRObjectSnapshot(t,e){const i=this.renew();return this.loaded=0,this.total=0,this.onLoadStart(this.progress),t.view.animation?t.encoder?.format==="mp4"?this.webrender.video(t).then(r=>this.loadVideoFrames(r,t.view.frames,30,i)):this.webrender.animation(t,i).then(r=>this.loadImageFrames(r,t.view.loop,e,i)):this.webrender.vrObject(t,i).then(r=>this.loadImageFrames(r,t.view.loop,e,i))}async loadImage(t,e){const i=new Image;i.crossOrigin=location.protocol==="file:"&&!k.isValidHttpUrl(t)?null:"anonymous";const r=new Promise((s,a)=>{const n=()=>{i.src="",a(new DOMException("Image load aborted","AbortError"))};if(e.aborted){n();return}i.addEventListener("load",()=>{e.removeEventListener("abort",n),this.loaded+=1,this.onLoadProgress(this.progress),s(i)},{once:!0}),i.addEventListener("error",o=>{e.removeEventListener("abort",n),a(`${o.type} : ${t}`)},{once:!0}),e.addEventListener("abort",n,{once:!0})});return i.src=t,r}loadImageFrames(t,e,i,r){this.total=t.length;const s=new Array(t.length),a=i||0;for(let n=0,o=t.length;n<o;n+=1){const l=Math.ceil(n/2)*(n%2===0?1:-1),m=e?w.mod(a+l,o):n;s[m]=this.loadImage(t[m],r)}return Promise.all(s).then(()=>this.onLoadEnd(this.progress)).catch(n=>{n instanceof DOMException&&n.name==="AbortError"||this.onLoadEnd(this.progress)}),s}async loadVideo(t,e,i,r){t.loop=i;const s=new Promise((a,n)=>{const o=()=>{t.removeAttribute("src"),t.load(),n(new DOMException("Video load aborted","AbortError"))};if(r.aborted){o();return}t.addEventListener("canplaythrough",()=>{r.removeEventListener("abort",o),this.loaded+=1,this.onLoadProgress(this.progress),a()},{once:!0}),t.addEventListener("error",l=>{r.removeEventListener("abort",o),n(`${l.type} : ${e}`)},{once:!0}),r.addEventListener("abort",o,{once:!0})});return t.src=e,t.load(),s}async loadVideoFrame(t,e,i,r,s){let a=0;return new Promise((n,o)=>{const l=()=>{if(s.aborted)return;if(a!==r){a+=1;return}t.removeEventListener("seeked",l),t.removeEventListener("error",m),s.removeEventListener("abort",v);const c=document.createElement("canvas");c.width=t.videoWidth,c.height=t.videoHeight,c.getContext("2d").drawImage(t,0,0);const E=new Image;E.src=c.toDataURL(),n(E),this.loaded+=1,this.onLoadProgress(this.progress),r!==i-1&&(t.currentTime+=1/e)},m=c=>{s.removeEventListener("abort",v),o(c)},v=()=>{t.removeEventListener("seeked",l),t.removeEventListener("error",m),o(new DOMException("Video frame load aborted","AbortError"))};if(s.aborted){v();return}t.addEventListener("seeked",l),t.addEventListener("error",m,{once:!0}),s.addEventListener("abort",v,{once:!0})})}loadVideoFrames(t,e,i,r){this.total=e;const s=new Array(e),a=document.createElement("video");for(let n=0,o=e;n<o;n+=1)s[n]=this.loadVideoFrame(a,i,e,n,r);return a.addEventListener("canplaythrough",()=>{r.aborted||(a.currentTime=1/i/2)},{once:!0}),r.addEventListener("abort",()=>{a.removeAttribute("src"),a.load()},{once:!0}),a.src=t,a.load(),Promise.all(s).then(()=>this.onLoadEnd(this.progress)).catch(n=>{n instanceof DOMException&&n.name==="AbortError"||this.onLoadEnd(this.progress)}),s}async loadImageHotspots(t,e){return this.webrenderV2?await this.webrenderV2.imageHotspots(await this.convert(t),e):Promise.reject(new Error("Hotspots only available with api V2"))}async loadVRCubeHotspots(t,e){return this.webrenderV2?await this.webrenderV2.vrCubeHotspots(await this.convert(t),e):Promise.reject(new Error("Hotspots only available with api V2"))}async loadVRObjectHotspots(t,e){return this.webrenderV2?await this.webrenderV2.vrObjectHotspots(await this.convert(t),e):Promise.reject(new Error("Hotspots only available with api V2"))}async loadImagePick(t,e){return this.webrenderV2?await this.webrenderV2.imagePick(await this.convert(t),e):Promise.reject(new Error("Picking only available with api V2"))}async loadVRObjectPick(t,e,i,r){return this.webrenderV2?await this.webrenderV2.imagePick(await this.vrObjectFrameSnapshot(t,i,r),e):Promise.reject(new Error("Picking only available with api V2"))}async loadVRCubePick(t,e,i){return this.webrenderV2?await this.webrenderV2.imagePick(await this.vrCubeFrameSnapshot(t,i),e):Promise.reject(new Error("Picking only available with api V2"))}async convert(t){if(!this.webrenderV2||this.webrender instanceof d||!t.view.camera)return t;const e=t.scene.find(o=>!o.decor&&!o.accessory);if(!e)return t;let i=this.databases.find(o=>o.id===e.database);(!i||!i.xmlDoc)&&(i=await this.webrender.database(e.database),this.databases.push(i));const r=t.view.camera.split("/"),s=r.length===2?r[0]:void 0,a=r.length===2?r[1]:r[0],n=i.getCameraId(a,s);if(n)return{...t,view:{...t.view,camera:n}};{const o=i.getCameraGroupId(a);return o?{...t,view:{...t.view,cameraGroup:o}}:t}}async vrObjectFrameSnapshot(t,e,i){if(!this.webrenderV2)return t;const r=t.scene.find(a=>!a.decor&&!a.accessory);if(!r)return t;let s=this.databases.find(a=>a.id===r.database);if(s||(s=await this.webrender.database(r.database),this.databases.push(s)),this.webrender instanceof S){if(!t.view.camera)return t;const a=s.getCameraGroupId(t.view.camera);if(!a)return t;const n=s.getCameraGroupById(a);if(!n)return t;const o=n.cameras[e];return o?{...t,view:{...t.view,camera:o.id}}:t}else if(this.webrender instanceof d){const a=typeof t.view.camera=="string"?t.view.camera:t.view.camera?.id;if(a){const n=s.getCameraById(a);if(!n)return t;const o=new Y(n.pointOfView),l=2*Math.PI/i;o.longitude+=e*l%(2*Math.PI);const m=o.pointOfView(n.pointOfView.target);return{...t,view:{...t.view,camera:{id:n.id,pov:{target:{x:m.target[0],y:m.target[1],z:m.target[2]},eye:{x:m.eye[0],y:m.eye[1],z:m.eye[2]},up:{x:m.up[0],y:m.up[1],z:m.up[2]}}}}}}else if(t.view.cameraGroup){const n=s.getCameraGroupById(t.view.cameraGroup);if(!n)return t;const o=n.cameras[e];return o?{...t,view:{...t.view,camera:o.id}}:t}else return t}else return t}async vrCubeFrameSnapshot(t,e){const i=t.scene.find(o=>!o.decor&&!o.accessory);if(!i)return t;let r=this.databases.find(o=>o.id===i.database);if(r||(r=await this.webrender.database(i.database),this.databases.push(r)),!t.view.camera)return t;let s;if(this.webrender instanceof S){const o=t.view.camera.split("/"),l=o.length===2?o[0]:void 0,m=o.length===2?o[1]:o[0];s=r.getCameraId(m,l)}else this.webrender instanceof d&&(s=typeof t.view.camera=="string"?t.view.camera:t.view.camera.id);if(!s)return t;const a=r.getCameraById(s);if(!a)return t;const n=I.initCubeFace(a.pointOfView.eye,a.pointOfView.target,e);return{...t,view:{...t.view,camera:{id:a.id,pov:{target:{x:n.target[0],y:n.target[1],z:n.target[2]},eye:{x:n.eye[0],y:n.eye[1],z:n.eye[2]},up:{x:n.up[0],y:n.up[1],z:n.up[2]}},lens:{fov:90}}},parameters:{...t.parameters,width:Math.max(t.parameters.width,t.parameters.height),height:Math.max(t.parameters.width,t.parameters.height)}}}onLoadStart(t){this.delegate&&this.delegate.onLoadStart(t)}onLoadProgress(t){this.delegate&&this.delegate.onLoadProgress(t)}onLoadEnd(t){this.delegate&&this.delegate.onLoadEnd(t)}static isValidHttpUrl(t){let e;try{e=new URL(t)}catch{return!1}return e.protocol==="http:"||e.protocol==="https:"}}class W{constructor(){this.element=document.createElement("video"),this.element.classList.add("ls-viewer-video"),this.element.style.opacity="0",this.element.width=0,this.element.height=0,this.element.setAttribute("muted",""),this.element.setAttribute("playsinline",""),this.element.setAttribute("preload","auto")}show(){this.element.style.opacity="1"}hide(){this.element.style.opacity="0"}resize(t,e,i,r){const s=b.fit(i,new y(t,e),r);this.element.style.top=`${s.top}px`,this.element.style.left=`${s.left}px`,this.element.style.width=`${s.width}px`,this.element.style.height=`${s.height}px`,(i.width!==this.element.width||i.height!==this.element.height)&&(this.element.width=i.width,this.element.height=i.height)}}class j{constructor(t,e,i){this.container=t,this.canvas=e,this.loader=i,this.hotspotList=[]}destroy(){}show(){this.canvas.show(!1),this.container.classList.add("ls-viewer-container-image")}hide(){this.canvas.hide(!1),this.container.classList.remove("ls-viewer-container-image")}async load(t,e,i,r){let s=Promise.resolve();const a=JSON.stringify(t);a===this.snapshotHash&&this.image?s=s.then(()=>this.canvas.draw(this.image,r,.05)):s=s.then(()=>this.loader.loadImageSnapshot(t).then(o=>{this.canvas.draw(o,r,.05),this.image=o}));const n=JSON.stringify(e);return(a!==this.snapshotHash||n!==this.hotspotsHash)&&(e.length?s=s.then(()=>this.loader.loadImageHotspots(t,e).then(o=>{this.hotspotList=o})):this.hotspotList=[]),this.hotspotsHash=n,this.snapshotHash=a,s}async pick(t,e){const i=new y(t.parameters.width,t.parameters.height),r=b.unproject(i,this.canvas.resolution,this.canvas.fit,e);return this.loader.loadImagePick(t,r)}hotspots(t){return this.hotspotList.map(e=>({...e,position2D:b.project(t,this.canvas.resolution,this.canvas.fit,e.position2D)})).map(e=>({...e,visibility:b.contains(this.canvas.resolution,e.position2D)?e.visibility:"OutOfFrustum"}))}snapshot(t,e){return this.canvas.element.toDataURL(t,e)}onPointerDown(t){}onPointerMove(t){}onPointerUp(t){}onPointerCancel(t){}onDeviceOrientation(t){}}class T{constructor(...t){t.length===3?({0:this.u,1:this.v,2:this.o}=t,this.w=h.v3.cross(this.u,this.v)):t.length===4?{0:this.u,1:this.v,2:this.w,3:this.o}=t:(this.u=[1,0,0],this.v=[0,1,0],this.w=[0,0,1],this.o=[0,0,0])}get localToGlobalMatrix(){const t=[this.u[0],this.u[1],this.u[2],0],e=[this.v[0],this.v[1],this.v[2],0],i=[this.w[0],this.w[1],this.w[2],0],r=[this.o[0],this.o[1],this.o[2],1];return[...t,...e,...i,...r]}get globalToLocalMatrix(){return h.m4.inverse(this.localToGlobalMatrix)}}class _{constructor(t,e,i){this.x=t,this.y=e,this.time=i}}class f{constructor(t,e){this.x=t,this.y=e}clone(){return new f(this.x,this.y)}}class q{constructor(t){this.loop=()=>{if(Math.abs(this.velocity.x)<1&&Math.abs(this.velocity.y)<1){this.animationFrameId=void 0,this.points=[];return}this.lastPoint.x+=this.velocity.x,this.lastPoint.y+=this.velocity.y,this.velocity.x*=.9,this.velocity.y*=.9,this.onMotion(this.lastPoint.clone()),this.animationFrameId=requestAnimationFrame(this.loop)},this.points=[],this.onMotion=t,this.lastPoint=new f(0,0),this.velocity=new f(0,0)}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0)}track(t){const e=Date.now();this.points=this.points.filter(i=>e-i.time<=100),this.points.push(new _(t.x,t.y,e)),this.lastPoint=t}start(){if(this.points.length===0)return;const t=this.points[0],e=this.points[this.points.length-1],i=e.x-t.x,r=e.y-t.y,s=e.time-t.time;this.velocity=new f(s===0?0:i/(s/15),s===0?0:r/(s/15)),this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0),this.animationFrameId=requestAnimationFrame(this.loop)}stop(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0),this.points=[]}}class J{constructor(t,e,i){this.motion=r=>{this.isStarted&&this.inertia.track(r);const s={x:r.x-this.previousPoint.x,y:r.y-this.previousPoint.y},a=w.accelerate(s.x,1.3)/this.startSize.width*.2*Math.PI*1.5,n=w.accelerate(s.y,1.3)/this.startSize.height*.2*Math.PI,o=h.m4.multiply(h.m4.rotationY(a),h.m4.rotationX(-n)),l=h.v3.normalize(h.v3.cross(this.pov.up,this.pov.target)),m=new T(l,[0,1,0],this.pov.eye),v=h.m4.identity();h.m4.multiply(v,m.localToGlobalMatrix,v),h.m4.multiply(v,o,v),h.m4.multiply(v,m.globalToLocalMatrix,v);const c=h.m4.transformPoint(v,this.pov.target),p=h.m4.transformDirection(v,this.pov.up);h.v3.cross(p,[0,0,1])[0]>=0&&(this.pov.target=c,this.pov.up=p),this.previousPoint=r,this.onMotion()},this.isStarted=!1,this.pov=t,this.fov=w.degreesToRadians(e),this.orientationMatrix=h.m4.identity(),this.inertia=new q(this.motion),this.onMotion=i,this.initPov=this.pov,this.initFov=this.fov,this.initOrientation=w.degreesToRadians(window.orientation)||0,this.startPov=new I([0,0,1],[0,0,0],[0,1,0]),this.startSize={width:0,height:0},this.previousPoint=new f(0,0)}destroy(){this.inertia.destroy()}get orientedPov(){const t=h.v3.normalize(h.v3.cross(this.pov.up,this.pov.target)),e=new T(t,[0,1,0],this.pov.eye),i=h.m4.identity();h.m4.multiply(i,e.localToGlobalMatrix,i),h.m4.multiply(i,this.orientationMatrix,i),h.m4.multiply(i,e.globalToLocalMatrix,i);const r=h.m4.transformDirection(i,this.pov.target),s=this.pov.eye,a=h.m4.transformDirection(i,this.pov.up);return new I(r,s,a)}reset(){this.pov=this.initPov.clone(),this.fov=this.initFov}start(t,e){this.isStarted=!0,this.startPov=this.pov,this.startSize=e,this.previousPoint=t,this.inertia.stop()}end(t,e){this.isStarted=!1,e&&(this.inertia.track(t),this.inertia.start())}orientation(t,e,i){const r=w.degreesToRadians(window.orientation)||0,s=w.degreesToRadians(t),a=w.degreesToRadians(-e),n=w.degreesToRadians(-i),o=h.m4.rotationX(w.degreesToRadians(90));h.m4.rotateZ(o,this.initOrientation,o),h.m4.rotateZ(o,s,o),h.m4.rotateX(o,a,o),h.m4.rotateY(o,n,o),h.m4.rotateZ(o,-r,o),this.orientationMatrix=o,this.onMotion()}}var Z=`precision mediump float;
|
|
3
3
|
|
|
4
4
|
uniform float u_mix;
|
|
5
5
|
uniform samplerCube u_texture;
|
|
@@ -11,7 +11,7 @@ void main() {
|
|
|
11
11
|
vec4 backColor = textureCube(u_texture_back, direction);
|
|
12
12
|
vec4 color = textureCube(u_texture, direction);
|
|
13
13
|
gl_FragColor = mix(backColor, color, u_mix);
|
|
14
|
-
}`,
|
|
14
|
+
}`,K=`attribute vec4 position;
|
|
15
15
|
|
|
16
16
|
uniform mat4 u_mvpi;
|
|
17
17
|
|
|
@@ -20,6 +20,6 @@ varying vec3 direction;
|
|
|
20
20
|
void main() {
|
|
21
21
|
direction = (u_mvpi * position).xyz;
|
|
22
22
|
gl_Position = position;
|
|
23
|
-
}`;class
|
|
24
|
-
`,`${
|
|
25
|
-
`]),this.quad=x.primitives.createXYQuadBufferInfo(this.gl),this.uniforms={u_mvpi:h.m4.identity(),u_mix:0,u_texture_back:x.createTexture(this.gl,{target:this.gl.TEXTURE_CUBE_MAP,minMag:this.gl.LINEAR,width:1,height:1}),u_texture:x.createTexture(this.gl,{target:this.gl.TEXTURE_CUBE_MAP,minMag:this.gl.LINEAR,width:1,height:1})},this.render=this.render.bind(this)}destroy(){this.interaction.destroy(),this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0)}show(){this.canvas.show(),this.container.classList.add("ls-viewer-container-vrcube")}hide(){this.canvas.hide(),this.container.classList.remove("ls-viewer-container-vrcube")}get pov(){return this.interaction.pov}set pov(t){this.interaction.pov.eye.every((e,i)=>e===t.eye[i])&&this.interaction.pov.target.every((e,i)=>e===t.target[i])&&this.interaction.pov.up.every((e,i)=>e===t.up[i])||(this.interaction.pov=t.clone(),this.animationFrameId=requestAnimationFrame(this.render))}get fov(){return g.radiansToDegrees(this.interaction.fov)}set fov(t){this.interaction.fov!==t&&(this.interaction.fov=g.degreesToRadians(t),this.animationFrameId=requestAnimationFrame(this.render))}async load(t,e,i,s){let r=Promise.resolve();{const o=this.gl.getExtension("WEBGL_debug_renderer_info");o&&navigator.platform==="MacIntel"&&navigator.userAgent.includes("Chrome")&&this.gl.getParameter(o.UNMASKED_RENDERER_WEBGL).includes("OpenGL")&&(t.parameters.width=Math.min(t.parameters.width,1812),t.parameters.height=Math.min(t.parameters.height,1812))}const a=JSON.stringify(t);a===this.snapshotHash?r=r.then(()=>(this.animationFrameId=requestAnimationFrame(this.render),Promise.resolve())):(this.images=[],this.animationFrameId=requestAnimationFrame(this.render),r=r.then(()=>this.loader.loadVRCubeSnapshot(t).then(o=>{this.images=o,x.createTexture(this.gl,{target:this.gl.TEXTURE_CUBE_MAP,min:this.gl.LINEAR_MIPMAP_LINEAR,minMag:this.gl.LINEAR,cubeFaceOrder:[this.gl.TEXTURE_CUBE_MAP_POSITIVE_Z,this.gl.TEXTURE_CUBE_MAP_POSITIVE_X,this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,this.gl.TEXTURE_CUBE_MAP_NEGATIVE_X,this.gl.TEXTURE_CUBE_MAP_POSITIVE_Y,this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y],src:o},(u,d)=>{u||(i&&this.interaction.reset(),this.uniforms.u_mix=s?0:1,this.uniforms.u_texture_back=this.uniforms.u_texture,this.uniforms.u_texture=d,this.animationFrameId=requestAnimationFrame(this.render))})})));const n=JSON.stringify(e);return(a!==this.snapshotHash||n!==this.hotspotsHash)&&(e.length?r=r.then(()=>this.loader.loadVRCubeHotspots(t,e).then(o=>{this.hotspotsList=o})):this.hotspotsList=[[]]),this.hotspotsHash=n,this.snapshotHash=a,r}async pick(t,e){const i=this.canvas.element.clientWidth,s=this.canvas.element.clientHeight,r=e.x,a=s-e.y,n=2*r/i-1,o=2*a/s-1,u=[n,o,0],d=this.modelViewProjectionMatrix,w=h.m4.inverse(d),c=h.v3.normalize(h.m4.transformPoint(w,u)),O=Math.max(Math.abs(c[0]),Math.abs(c[1]),Math.abs(c[2]));let L="";Math.abs(c[0])===O?L=c[0]>0?"XPOS":"XNEG":Math.abs(c[1])===O?L=c[1]>0?"YPOS":"YNEG":L=c[2]>0?"ZPOS":"ZNEG";let P=0,M=0,E="";switch(L){case"XPOS":P=(-c[2]/Math.abs(c[0])+1)/2,M=(-c[1]/Math.abs(c[0])+1)/2,E="right";break;case"XNEG":P=(c[2]/Math.abs(c[0])+1)/2,M=(-c[1]/Math.abs(c[0])+1)/2,E="left";break;case"YPOS":P=(c[0]/Math.abs(c[1])+1)/2,M=(c[2]/Math.abs(c[1])+1)/2,E="up";break;case"YNEG":P=(c[0]/Math.abs(c[1])+1)/2,M=(-c[2]/Math.abs(c[1])+1)/2,E="down";break;case"ZPOS":P=(c[0]/Math.abs(c[2])+1)/2,M=(-c[1]/Math.abs(c[2])+1)/2,E="front";break;case"ZNEG":P=(-c[0]/Math.abs(c[2])+1)/2,M=(-c[1]/Math.abs(c[2])+1)/2,E="back";break}const T={x:Math.round(P*Math.max(t.parameters.width,t.parameters.height)),y:Math.round(M*Math.max(t.parameters.width,t.parameters.height))};return this.loader.loadVRCubePick(t,T,E)}hotspots(){const t=[];if(this.hotspotsList.length===0)return[];const e=this.hotspotsList[0]?.length??0,i=this.modelViewProjectionMatrix;for(let s=0;s<e;s++){const r=this.hotspotsList.findIndex(U=>U[s].visibility!=="OutOfFrustum");if(r===-1)continue;const a={...this.hotspotsList[r][s]},n=a.position2D.x/this.images[0].width,o=a.position2D.y/this.images[0].height;let u=0,d=0,w=0;switch(r){case 0:this.pov.target[2]<0&&(a.visibility="OutOfFrustum"),u=2*n-1,d=1-2*o,w=1;break;case 1:this.pov.target[0]>0&&(a.visibility="OutOfFrustum"),u=1,d=1-2*o,w=1-2*n;break;case 2:this.pov.target[2]>0&&(a.visibility="OutOfFrustum"),u=1-2*n,d=1-2*o,w=-1;break;case 3:this.pov.target[0]<0&&(a.visibility="OutOfFrustum"),u=-1,d=1-2*o,w=2*n-1;break;case 4:this.pov.target[1]<0&&(a.visibility="OutOfFrustum"),u=2*n-1,d=1,w=2*o-1;break;case 5:this.pov.target[1]>0&&(a.visibility="OutOfFrustum"),u=2*n-1,d=-1,w=1-2*o;break}const c=h.v3.normalize([u,d,w]),O=h.m4.transformPoint(i,c),L=this.canvas.element.clientWidth,P=this.canvas.element.clientHeight,M=.5*L*(O[0]+1),E=.5*P*(O[1]+1),T={x:Math.round(M),y:Math.round(P-E)},z=new f(L,P),$=y.contains(z,T)?a.visibility:"OutOfFrustum";t.push({...a,position2D:T,visibility:$})}return t}snapshot(t,e){return this.canvas.element.toDataURL(t,e)}get modelViewProjectionMatrix(){const t=this.canvas.element.clientWidth,e=this.canvas.element.clientHeight,i=t>e?t/e:e/t,s=y.getStandardAspectRatio(t,e,this.aspectRatioOverride),r=this.interaction.fov*(s/i),a=h.m4.setAxis(h.m4.identity(),[-1,0,0],0),n=t>e?g.perspectiveWithFovY(r,t/e,.5,100):g.perspectiveWithFovX(r,t/e,.5,100),o=this.interaction.orientedPov,u=h.m4.inverse(h.m4.lookAt(o.eye,o.target,o.up));return h.m4.multiply(h.m4.multiply(n,u),a)}render(){this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height),this.uniforms.u_mvpi=h.m4.inverse(this.modelViewProjectionMatrix),this.gl.useProgram(this.programInfo.program),x.setBuffersAndAttributes(this.gl,this.programInfo,this.quad),x.setUniforms(this.programInfo,this.uniforms),x.drawBufferInfo(this.gl,this.quad),this.uniforms.u_mix<1&&(this.uniforms.u_mix=Math.min(this.uniforms.u_mix+.05,1),this.animationFrameId=requestAnimationFrame(this.render))}onMouseDown(t){this.container.classList.add("ls-viewer-container-vrcube-grabbing"),this.interaction.start(p.pointFromMouseEvent(t),{width:this.gl.canvas.width,height:this.gl.canvas.height})}onMouseMove(t){this.interaction.isStarted&&(this.interaction.motion(p.pointFromMouseEvent(t)),t.preventDefault())}onMouseUp(t){this.interaction.isStarted&&(this.container.classList.remove("ls-viewer-container-vrcube-grabbing"),this.interaction.end(p.pointFromMouseEvent(t),!0))}onMouseEnter(t){this.interaction.isStarted&&t.buttons===0&&(this.container.classList.remove("ls-viewer-container-vrcube-grabbing"),this.interaction.end(p.pointFromMouseEvent(t),!1))}onTouchStart(t){this.container.classList.add("ls-viewer-container-vrcube-grabbing"),this.interaction.start(p.pointFromTouchEvent(t),{width:this.gl.canvas.width,height:this.gl.canvas.height})}onTouchMove(t){this.interaction.isStarted&&(this.interaction.motion(p.pointFromTouchEvent(t)),t.preventDefault())}onTouchEnd(t){this.interaction.isStarted&&(this.container.classList.remove("ls-viewer-container-vrcube-grabbing"),this.interaction.end(p.pointFromTouchEvent(t),!0))}onDeviceOrientation(t){this.interaction.orientation(t.alpha,t.beta,t.gamma)}}class et{constructor(t,e,i,s,r){this.isStarted=!1,this.position=t,this.frames=e,this.rows=i,this.loop=s,this.onMotion=r,this.inertia=new R(this.motion.bind(this)),this.initPosition={...this.position},this.startPosition={x:0,y:0},this.startPoint=new I(0,0),this.startSize={width:0,height:0},this.lastPoints=[],this.lastPointsNumber=20}destroy(){this.inertia.destroy()}reset(){this.position={...this.initPosition}}get positionIndex(){return this.frames*this.position.y+this.position.x}set positionIndex(t){if(this.positionIndex===t)return;const e=this.loop?g.mod(t,this.frames*this.rows):Math.max(0,Math.min(t,this.frames*this.rows));this.position.x=g.mod(e,this.frames),this.position.y=Math.floor(e/this.frames)}start(t,e){this.isStarted=!0,this.startPosition={...this.position},this.startPoint=t,this.startSize=e,this.lastPoints=[],this.inertia.stop()}motion(t){this.isStarted&&this.inertia.track(t),this.lastPoints.push({x:t.x,y:t.y}),this.lastPoints.splice(0,this.lastPoints.length-this.lastPointsNumber);const e=N.linear(this.lastPoints.map(s=>[s.x,s.y])),i=25;if(Math.abs(e.equation[0])<1){const s=g.accelerate(t.x-this.startPoint.x,1.3)/this.startSize.width*(this.frames/4);let r=this.startPosition.x-Math.round(s);r=this.loop?g.mod(r,this.frames):Math.max(0,Math.min(r,this.frames-1)),r!==this.position.x&&(this.position.x=r,this.onMotion());const a=Math.min(...this.lastPoints.map(o=>o.x));Math.max(...this.lastPoints.map(o=>o.x))-a>i&&(this.startPoint.y=t.y,this.startPosition.y=this.position.y)}else{const s=g.accelerate(t.y-this.startPoint.y,1.7)/this.startSize.height*(this.rows/4);let r=this.startPosition.y+Math.round(s);r=Math.max(0,Math.min(r,this.rows-1)),r!==this.position.y&&(this.position.y=r,this.onMotion());const a=Math.min(...this.lastPoints.map(o=>o.y));Math.max(...this.lastPoints.map(o=>o.y))-a>i&&(this.startPoint.x=t.x,this.startPosition.x=this.position.x)}}end(t,e){this.isStarted=!1,e&&(this.inertia.track(t),this.inertia.start())}}class C{constructor(t,e,i,s){this.container=t,this.canvas=e,this.loader=i,this.images=[],this.frames=24,this.hotspotsList=[[]],this.interaction=new et({x:0,y:0},1,1,!1,()=>{this.canvas.draw(this.image,!0,.5),this.onInteraction({position:this.interaction.positionIndex})}),this.onInteraction=s}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0)}show(){this.canvas.show(!1),this.container.classList.add("ls-viewer-container-vrobject")}hide(){this.canvas.hide(!1),this.container.classList.remove("ls-viewer-container-vrobject")}async goto(t){return new Promise(e=>{let i=this.interaction.positionIndex;const s=()=>{if(this.interaction.positionIndex===t)e();else{let r=i>t?-1:1;this.interaction.loop&&this.interaction.frames-i+t<Math.abs(t-i)&&(r*=-1),i+=.5*r,this.position=Math.floor(i),this.animationFrameId=requestAnimationFrame(s)}};this.animationFrameId=requestAnimationFrame(s)})}get position(){return this.interaction.positionIndex}set position(t){this.interaction.positionIndex=t,this.canvas.draw(this.image,!0,.5)}get image(){return this.images[this.interaction.positionIndex]}async load(t,e,i,s){let r=Promise.resolve();i&&this.interaction.reset();const a=JSON.stringify(t);a===this.snapshotHash&&this.image?r=r.then(()=>this.canvas.draw(this.image,s,.05)):(this.images=[],r=r.then(()=>this.loader.loadVRObjectSnapshot(t,this.interaction.positionIndex).then(o=>{const u=o.length;return this.images=new Array(u),this.interaction.frames=t.view.frames??t.view.panFrames??this.frames,this.interaction.rows=u/this.interaction.frames,this.interaction.loop=!!t.view.loop,i&&this.interaction.reset(),o.forEach((d,w)=>{d.then(c=>{this.images[w]=c,c===this.image&&this.canvas.draw(this.image,s,.05)}).catch(()=>{})}),o[this.interaction.positionIndex].then(()=>Promise.resolve())})));const n=JSON.stringify(e);return(a!==this.snapshotHash||n!==this.hotspotsHash)&&(e.length?r=r.then(()=>this.loader.loadVRObjectHotspots(t,e).then(o=>{this.hotspotsList=o})):this.hotspotsList=[[]]),this.hotspotsHash=n,this.snapshotHash=a,r}async pick(t,e){const i=new f(t.parameters.width,t.parameters.height),s=y.unproject(i,this.canvas.resolution,this.canvas.fit,e);return this.loader.loadVRObjectPick(t,s,this.position,this.frames)}hotspots(t){return(this.hotspotsList[this.interaction.positionIndex]||[]).map(i=>({...i,position2D:y.project(t,this.canvas.resolution,this.canvas.fit,i.position2D)})).map(i=>({...i,visibility:y.contains(this.canvas.resolution,i.position2D)?i.visibility:"OutOfFrustum"}))}snapshot(t,e){return this.canvas.element.toDataURL(t,e)}onMouseDown(t){this.container.classList.add("ls-viewer-container-vrobject-grabbing"),this.interaction.start(p.pointFromMouseEvent(t),{width:this.canvas.element.width,height:this.canvas.element.height})}onMouseMove(t){this.interaction.isStarted&&(this.interaction.motion(p.pointFromMouseEvent(t)),t.preventDefault())}onMouseUp(t){this.interaction.isStarted&&(this.container.classList.remove("ls-viewer-container-vrobject-grabbing"),this.interaction.end(p.pointFromMouseEvent(t),!0))}onMouseEnter(t){this.interaction.isStarted&&t.buttons===0&&(this.container.classList.remove("ls-viewer-container-vrobject-grabbing"),this.interaction.end(p.pointFromMouseEvent(t),!1))}onTouchStart(t){this.container.classList.add("ls-viewer-container-vrobject-grabbing"),this.interaction.start(p.pointFromTouchEvent(t),{width:this.canvas.element.width,height:this.canvas.element.height})}onTouchMove(t){this.interaction.isStarted&&(this.interaction.motion(p.pointFromTouchEvent(t)),t.preventDefault())}onTouchEnd(t){this.interaction.isStarted&&(this.container.classList.remove("ls-viewer-container-vrobject-grabbing"),this.interaction.end(p.pointFromTouchEvent(t),!0))}onDeviceOrientation(t){}}class G{constructor(t,e,i){this.container=t,this.loader=i,this.video=e}destroy(){}show(){this.video.show(),this.container.classList.add("ls-viewer-container-video")}hide(){this.video.hide(),this.container.classList.remove("ls-viewer-container-video")}async load(t){const e=JSON.stringify(t);return e===this.hash?(this.video.element.load(),Promise.resolve()):(this.hash=e,this.loader.loadVideoSnapshot(this.video.element,t))}async pick(t,e){return Promise.reject()}hotspots(t){return[]}snapshot(t,e){return"data:image/gif;base64,R0lGODlhAQABAIAAAP7//wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="}async play(){return new Promise((t,e)=>{this.video.element.addEventListener("ended",()=>{t()},{once:!0}),this.video.element.play().catch(e),this.show()})}onMouseDown(t){}onMouseMove(t){}onMouseUp(t){}onMouseEnter(t){}onTouchStart(t){}onTouchMove(t){}onTouchEnd(t){}onDeviceOrientation(t){}}class it{constructor(t,e){this.onDeviceOrientation=this.onDeviceOrientation.bind(this),this.onResize=this.onResize.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseMove=this.onMouseMove.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onMouseEnter=this.onMouseEnter.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onLoadStart=this.onLoadStart.bind(this),this.onLoadProgress=this.onLoadProgress.bind(this),this.onLoadEnd=this.onLoadEnd.bind(this),this.onLoadError=this.onLoadError.bind(this),this.onHotspotsChange=this.onHotspotsChange.bind(this),this.onVrcubeInteraction=this.onVrcubeInteraction.bind(this),this.onVrobjectInteraction=this.onVrobjectInteraction.bind(this),this.options={server:"localhost",api:"v1",autores:!0,fit:"cover",image:{},video:{},vrcube:{},vrobject:{},events:{},...e},this.options.events={onLoadStart:()=>{},onLoadProgress:()=>{},onLoadEnd:()=>{},onLoadError:()=>{},onInteraction:()=>{},onVrcubeInteraction:()=>{},onVrobjectInteraction:()=>{},onHotspotsChange:()=>{},...e.events},this.options.events.onLoadError=D(this.options.events.onLoadError,10),this.container=t,this.container.classList.add("ls-viewer-container"),this.canvas2D=new X(this.options.fit),this.container.prepend(this.canvas2D.element),this.canvas3D=new Y,this.container.prepend(this.canvas3D.element),this.video=new J,this.container.prepend(this.video.element),this.loader=new k(this.options.server,this.options.api,this),this.resolution=new f(0,0),this.parameters={width:0,height:0,antialiasing:!1,superSampling:2},this.encoder={format:"jpeg",quality:80},this.hotspots=[],this.widgetImage=new q(t,this.canvas2D,this.loader),this.widgetVideo=new G(t,this.video,this.loader),this.widgetVRObject=new C(t,this.canvas2D,this.loader,this.onVrobjectInteraction),this.canvas3D.context&&(this.widgetVRCube=new H(t,this.canvas3D,this.loader,this.onVrcubeInteraction,this.aspectRatioOverride)),this.widget=this.widgetImage,this.container.addEventListener("mousedown",this.onMouseDown),this.container.addEventListener("mouseenter",this.onMouseEnter),this.container.addEventListener("touchstart",this.onTouchStart),document.addEventListener("mousemove",this.onMouseMove,{passive:!1}),document.addEventListener("mouseup",this.onMouseUp),document.addEventListener("touchmove",this.onTouchMove,{passive:!1}),document.addEventListener("touchend",this.onTouchEnd),this.loadWidget=D(this.loadWidget,10),this.resizeObserver=new ResizeObserver(this.onResize),this.resizeObserver.observe(this.container)}destroy(){this.resizeObserver.disconnect(),this.canvas2D.destroy(),this.container.removeEventListener("mousedown",this.onMouseDown),this.container.removeEventListener("mouseenter",this.onMouseEnter),this.container.removeEventListener("touchstart",this.onTouchStart),document.removeEventListener("mousemove",this.onMouseMove),document.removeEventListener("mouseup",this.onMouseUp),document.removeEventListener("touchmove",this.onTouchMove),document.removeEventListener("touchend",this.onTouchEnd)}async load(t,e){let i=Promise.resolve();return e?.animation&&(i=i.then(()=>this.loadAnimation(e.animation))),this.view&&e?.fromPosition!==void 0&&this.viewWidget instanceof C&&(this.view.mode,i=i.then(()=>this.viewWidget.goto(e.fromPosition))),e?.animation&&(i=i.then(()=>this.widgetVideo.play())),i=i.then(()=>(this.scene=Array.isArray(t)?[...t]:[t],this.loadWidget(!1,!(e&&e.animation)))),i.catch(s=>{this.onLoadError(s)}),i}async setEncoder(t){this.encoder={...t};let e=Promise.resolve();return e=e.then(()=>this.loadWidget(!1,!0)),e.catch(i=>{this.onLoadError(i)}),e}setParameters(t){if(t.width&&t.height){this.resolution=new f(t.width,t.height);const i=this.container.clientWidth,s=this.container.clientHeight;this.canvas2D.resize(i,s,this.getCanvas2DPixelRatio(i,s))}this.parameters={...t},this.parameters.width=this.resolution.width,this.parameters.height=this.resolution.height;let e=Promise.resolve();return e=e.then(()=>this.loadWidget(!1,!0)),e.catch(i=>{this.onLoadError(i)}),e}setHotspots(t){this.hotspots=t,this.loadWidget(!1,!1)}async setView(t,e){let i=Promise.resolve();return e?.animation&&(i=i.then(()=>this.loadAnimation(e.animation))),this.view&&e?.fromPosition!==void 0&&this.viewWidget instanceof C&&(i=i.then(()=>this.viewWidget.goto(e.fromPosition))),e?.animation&&(i=i.then(()=>this.widgetVideo.play())),i=i.then(()=>{let s=!0;return this.view={...t},this.view&&this.viewWidget instanceof C&&e?.toPosition!==void 0&&(s=!1,this.viewWidget.position=e.toPosition),this.loadWidget(s,!(e&&e.animation))}),i.catch(s=>{this.onLoadError(s)}),i}setVrcube(t){this.widgetVRCube&&Object.assign(this.widgetVRCube,t)}setVrobject(t){Object.assign(this.widgetVRObject,t)}async loadAnimation(t){const e={scene:this.scene,view:{animation:t.name,camera:t.camera,duration:t.duration,loop:t.loop,reverse:t.reverse},parameters:this.parameters,encoder:{format:"mp4"}};return e.view?.background||(e.view.background="product"),this.widgetVideo.load(e).then(()=>Promise.resolve())}async playAnimation(t){return this.loadAnimation(t).then(()=>this.widgetVideo.play()).catch(e=>{this.onLoadError(e)})}stopAnimation(){this.widgetVideo.hide()}async pick(t){if(!this.scene)throw new Error("No scene set");if(!this.view)throw new Error("No view set");if(!this.view.camera&&!this.view.cameraGroup)throw new Error("No camera set");const e={scene:this.scene,view:this.view,parameters:this.parameters,encoder:this.encoder};return await this.viewWidget.pick(e,t)}async pickHotspot(t){const e=await this.pick(t),i=Object.values(e.point),s=h.v3.normalize(Object.values(e.normal)),r=h.v3.add(i,h.v3.mulScalar(s,.01));return e.point={x:r[0],y:r[1],z:r[2]},e}snapshot(t,e){return this.viewWidget.snapshot(t,e)}async loadWidget(t,e){if(!this.scene||!this.view||!this.parameters.width||!this.parameters.height)return Promise.resolve();const i=this.viewWidget;if(!i)return Promise.reject(new Error("Unknown view mode"));const s={scene:this.scene,view:this.view,parameters:this.parameters,encoder:this.encoder};return s.view.background||(s.view.background="product"),i.load(s,this.hotspots,t,e).then(()=>{this.widget.hide(),this.widget=i,this.widget.show(),this.widgetVideo.hide(),this.onHotspotsChange()})}get aspectRatioOverride(){switch(this.options.aspectRatio){case"4:3":return 4/3;case"16:9":return 16/9;default:return}}get viewWidget(){switch(this.view?.mode){case"image":return this.widgetImage;case"video":return this.widgetVideo;case"vrcube":return this.widgetVRCube??this.widgetImage;case"vrobject":return this.widgetVRObject;default:return this.widgetImage}}onMouseDown(t){this.widget.onMouseDown(t)}onMouseEnter(t){this.widget.onMouseEnter(t)}onMouseMove(t){this.widget.onMouseMove(t)}onMouseUp(t){this.widget.onMouseUp(t)}onTouchStart(t){this.widget.onTouchStart(t)}onTouchMove(t){this.widget.onTouchMove(t)}onTouchEnd(t){this.widget.onTouchEnd(t)}onDeviceOrientation(t){this.widget.onDeviceOrientation(t)}getCanvas2DPixelRatio(t,e){return t<=0||e<=0||this.resolution.width<=0||this.resolution.height<=0?window.devicePixelRatio:Math.min(window.devicePixelRatio,this.resolution.width/t,this.resolution.height/e)}onResize(){const t=this.container.clientWidth,e=this.container.clientHeight;this.options.autores&&(this.resolution=y.getStandardResolution(t*window.devicePixelRatio,e*window.devicePixelRatio,this.aspectRatioOverride),this.parameters.width=this.resolution.width,this.parameters.height=this.resolution.height),this.canvas2D.resize(t,e,this.getCanvas2DPixelRatio(t,e)),this.canvas3D.resize(t,e,window.devicePixelRatio),this.video.resize(t,e,this.resolution,this.options.fit),this.loadWidget(!1,!1).then(()=>{this.onHotspotsChange()}).catch(i=>{this.onLoadError(i)})}onVrcubeInteraction(...t){this.onHotspotsChange(),this.options.events.onInteraction(...t),this.options.events.onVrcubeInteraction(...t)}onVrobjectInteraction(t){this.onHotspotsChange(),this.options.events.onInteraction(t.position),this.options.events.onVrobjectInteraction(t.position)}onHotspotsChange(){const t=this.widget.hotspots(this.resolution);t.length&&this.options.events.onHotspotsChange(t)}onLoadStart(...t){this.container.classList.add("ls-viewer-container-loading"),this.options.events.onLoadStart(...t)}onLoadProgress(...t){this.options.events.onLoadProgress(...t)}onLoadEnd(...t){this.container.classList.remove("ls-viewer-container-loading"),this.options.events.onLoadEnd(...t)}onLoadError(...t){this.container.classList.remove("ls-viewer-container-loading"),this.options.events.onLoadError(...t)}}exports.WRAPIv2=void 0;(l=>{(t=>{t.Visible="Visible",t.Occluded="Occluded",t.Clipped="Clipped",t.OutOfFrustum="OutOfFrustum"})(l.HotspotVisibility||(l.HotspotVisibility={})),(t=>{t.VeryLow="veryLow",t.Low="low",t.Medium="medium",t.Fine="fine",t.Ultra="ultra"})(l.SunShadowQualityMode||(l.SunShadowQualityMode={})),(t=>{t.None="none",t.Weak="weak",t.Normal="normal",t.Fine="fine",t.UltraFine="ultraFine",t.Max="max"})(l.SunShadowSmoothnessMode||(l.SunShadowSmoothnessMode={})),(t=>{t.Manual="manual",t.TimeAndLoc="timeAndLoc",t.ExtractedFromEnv="extractedFromEnv"})(l.SunUseCaseMode||(l.SunUseCaseMode={})),(t=>{t.ShowOnly="showOnly",t.HideOnly="hideOnly"})(l.SurfacesFilterMode||(l.SurfacesFilterMode={}))})(exports.WRAPIv2||(exports.WRAPIv2={}));exports.Viewer=it;exports.WidgetImage=q;exports.WidgetVRCube=H;exports.WidgetVRObject=C;exports.WidgetVideo=G;
|
|
23
|
+
}`;class R{constructor(t,e,i,r,s){this.render=()=>{this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height),this.uniforms.u_mvpi=h.m4.inverse(this.modelViewProjectionMatrix),this.gl.useProgram(this.programInfo.program),M.setBuffersAndAttributes(this.gl,this.programInfo,this.quad),M.setUniforms(this.programInfo,this.uniforms),M.drawBufferInfo(this.gl,this.quad),this.uniforms.u_mix<1&&(this.uniforms.u_mix=Math.min(this.uniforms.u_mix+.05,1),this.animationFrameId=requestAnimationFrame(this.render))},this.container=t,this.canvas=e,this.loader=i,this.aspectRatioOverride=s,this.images=[],this.hotspotsList=[[]];const a=new I([0,0,1],[0,0,0],[0,1,0]),n=60,o=h.m4.rotationX(w.degreesToRadians(15));h.m4.transformDirection(o,a.target,a.target),h.m4.transformDirection(o,a.up,a.up),this.interaction=new J(a,n,()=>{this.animationFrameId=requestAnimationFrame(this.render),this.onInteraction({pov:this.interaction.pov.clone(),fov:this.interaction.fov})}),this.onInteraction=r,this.gl=this.canvas.context,this.programInfo=M.createProgramInfo(this.gl,[`${K}
|
|
24
|
+
`,`${Z}
|
|
25
|
+
`]),this.quad=M.primitives.createXYQuadBufferInfo(this.gl),this.uniforms={u_mvpi:h.m4.identity(),u_mix:0,u_texture_back:M.createTexture(this.gl,{target:this.gl.TEXTURE_CUBE_MAP,minMag:this.gl.LINEAR,width:1,height:1}),u_texture:M.createTexture(this.gl,{target:this.gl.TEXTURE_CUBE_MAP,minMag:this.gl.LINEAR,width:1,height:1})}}destroy(){this.interaction.destroy(),this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0)}show(){this.canvas.show(),this.container.classList.add("ls-viewer-container-vrcube")}hide(){this.canvas.hide(),this.container.classList.remove("ls-viewer-container-vrcube")}get pov(){return this.interaction.pov}set pov(t){this.interaction.pov.eye.every((e,i)=>e===t.eye[i])&&this.interaction.pov.target.every((e,i)=>e===t.target[i])&&this.interaction.pov.up.every((e,i)=>e===t.up[i])||(this.interaction.pov=t.clone(),this.animationFrameId=requestAnimationFrame(this.render))}get fov(){return w.radiansToDegrees(this.interaction.fov)}set fov(t){this.interaction.fov!==t&&(this.interaction.fov=w.degreesToRadians(t),this.animationFrameId=requestAnimationFrame(this.render))}async load(t,e,i,r){let s=Promise.resolve();{const o=this.gl.getExtension("WEBGL_debug_renderer_info");o&&navigator.platform==="MacIntel"&&navigator.userAgent.includes("Chrome")&&this.gl.getParameter(o.UNMASKED_RENDERER_WEBGL).includes("OpenGL")&&(t.parameters.width=Math.min(t.parameters.width,1812),t.parameters.height=Math.min(t.parameters.height,1812))}const a=JSON.stringify(t);a===this.snapshotHash?s=s.then(()=>(this.animationFrameId=requestAnimationFrame(this.render),Promise.resolve())):(this.images=[],this.animationFrameId=requestAnimationFrame(this.render),s=s.then(()=>this.loader.loadVRCubeSnapshot(t).then(o=>{this.images=o,M.createTexture(this.gl,{target:this.gl.TEXTURE_CUBE_MAP,min:this.gl.LINEAR_MIPMAP_LINEAR,minMag:this.gl.LINEAR,cubeFaceOrder:[this.gl.TEXTURE_CUBE_MAP_POSITIVE_Z,this.gl.TEXTURE_CUBE_MAP_POSITIVE_X,this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,this.gl.TEXTURE_CUBE_MAP_NEGATIVE_X,this.gl.TEXTURE_CUBE_MAP_POSITIVE_Y,this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y],src:o},(l,m)=>{l||(i&&this.interaction.reset(),this.uniforms.u_mix=r?0:1,this.uniforms.u_texture_back=this.uniforms.u_texture,this.uniforms.u_texture=m,this.animationFrameId=requestAnimationFrame(this.render))})})));const n=JSON.stringify(e);return(a!==this.snapshotHash||n!==this.hotspotsHash)&&(e.length?s=s.then(()=>this.loader.loadVRCubeHotspots(t,e).then(o=>{this.hotspotsList=o})):this.hotspotsList=[[]]),this.hotspotsHash=n,this.snapshotHash=a,s}async pick(t,e){const i=this.canvas.element.clientWidth,r=this.canvas.element.clientHeight,s=e.x,a=r-e.y,n=2*s/i-1,o=2*a/r-1,l=[n,o,0],m=this.modelViewProjectionMatrix,v=h.m4.inverse(m),c=h.v3.normalize(h.m4.transformPoint(v,l)),p=Math.max(Math.abs(c[0]),Math.abs(c[1]),Math.abs(c[2]));let E="";Math.abs(c[0])===p?E=c[0]>0?"XPOS":"XNEG":Math.abs(c[1])===p?E=c[1]>0?"YPOS":"YNEG":E=c[2]>0?"ZPOS":"ZNEG";let x=0,A=0,L="";switch(E){case"XPOS":x=(-c[2]/Math.abs(c[0])+1)/2,A=(-c[1]/Math.abs(c[0])+1)/2,L="right";break;case"XNEG":x=(c[2]/Math.abs(c[0])+1)/2,A=(-c[1]/Math.abs(c[0])+1)/2,L="left";break;case"YPOS":x=(c[0]/Math.abs(c[1])+1)/2,A=(c[2]/Math.abs(c[1])+1)/2,L="up";break;case"YNEG":x=(c[0]/Math.abs(c[1])+1)/2,A=(-c[2]/Math.abs(c[1])+1)/2,L="down";break;case"ZPOS":x=(c[0]/Math.abs(c[2])+1)/2,A=(-c[1]/Math.abs(c[2])+1)/2,L="front";break;case"ZNEG":x=(-c[0]/Math.abs(c[2])+1)/2,A=(-c[1]/Math.abs(c[2])+1)/2,L="back";break}const F={x:Math.round(x*Math.max(t.parameters.width,t.parameters.height)),y:Math.round(A*Math.max(t.parameters.width,t.parameters.height))};return this.loader.loadVRCubePick(t,F,L)}hotspots(){const t=[];if(this.hotspotsList.length===0)return[];const e=this.hotspotsList[0]?.length??0,i=this.modelViewProjectionMatrix;for(let r=0;r<e;r++){const s=this.hotspotsList.findIndex(z=>z[r].visibility!=="OutOfFrustum");if(s===-1)continue;const a={...this.hotspotsList[s][r]},n=a.position2D.x/this.images[0].width,o=a.position2D.y/this.images[0].height;let l=0,m=0,v=0;switch(s){case 0:this.pov.target[2]<0&&(a.visibility="OutOfFrustum"),l=2*n-1,m=1-2*o,v=1;break;case 1:this.pov.target[0]>0&&(a.visibility="OutOfFrustum"),l=1,m=1-2*o,v=1-2*n;break;case 2:this.pov.target[2]>0&&(a.visibility="OutOfFrustum"),l=1-2*n,m=1-2*o,v=-1;break;case 3:this.pov.target[0]<0&&(a.visibility="OutOfFrustum"),l=-1,m=1-2*o,v=2*n-1;break;case 4:this.pov.target[1]<0&&(a.visibility="OutOfFrustum"),l=2*n-1,m=1,v=2*o-1;break;case 5:this.pov.target[1]>0&&(a.visibility="OutOfFrustum"),l=2*n-1,m=-1,v=1-2*o;break}const c=h.v3.normalize([l,m,v]),p=h.m4.transformPoint(i,c),E=this.canvas.element.clientWidth,x=this.canvas.element.clientHeight,A=.5*E*(p[0]+1),L=.5*x*(p[1]+1),F={x:Math.round(A),y:Math.round(x-L)},G=new y(E,x),$=b.contains(G,F)?a.visibility:"OutOfFrustum";t.push({...a,position2D:F,visibility:$})}return t}snapshot(t,e){return this.canvas.element.toDataURL(t,e)}get modelViewProjectionMatrix(){const t=this.canvas.element.clientWidth,e=this.canvas.element.clientHeight,i=t>e?t/e:e/t,r=b.getStandardAspectRatio(t,e,this.aspectRatioOverride),s=this.interaction.fov*(r/i),a=h.m4.setAxis(h.m4.identity(),[-1,0,0],0),n=t>e?w.perspectiveWithFovY(s,t/e,.5,100):w.perspectiveWithFovX(s,t/e,.5,100),o=this.interaction.orientedPov,l=h.m4.inverse(h.m4.lookAt(o.eye,o.target,o.up));return h.m4.multiply(h.m4.multiply(n,l),a)}onPointerDown(t){this.container.setPointerCapture(t.pointerId),this.container.classList.add("ls-viewer-container-vrcube-grabbing"),this.interaction.start(new f(t.screenX,t.screenY),{width:this.gl.canvas.width,height:this.gl.canvas.height})}onPointerMove(t){this.interaction.isStarted&&(this.interaction.motion(new f(t.screenX,t.screenY)),t.preventDefault())}onPointerUp(t){this.interaction.isStarted&&(this.container.classList.remove("ls-viewer-container-vrcube-grabbing"),this.interaction.end(new f(t.screenX,t.screenY),!0))}onPointerCancel(t){this.interaction.isStarted&&(this.container.classList.remove("ls-viewer-container-vrcube-grabbing"),this.interaction.end(new f(t.screenX,t.screenY),!1))}onDeviceOrientation(t){this.interaction.orientation(t.alpha,t.beta,t.gamma)}}class tt{constructor(t,e,i,r,s){this.motion=a=>{this.isStarted&&this.inertia.track(a),this.lastPoints.push({x:a.x,y:a.y}),this.lastPoints.splice(0,this.lastPoints.length-this.lastPointsNumber);const n=N.linear(this.lastPoints.map(l=>[l.x,l.y])),o=25;if(Math.abs(n.equation[0])<1){const l=w.accelerate(a.x-this.startPoint.x,1.3)/this.startSize.width*(this.frames/4);let m=this.startPosition.x-Math.round(l);m=this.loop?w.mod(m,this.frames):Math.max(0,Math.min(m,this.frames-1)),m!==this.position.x&&(this.position.x=m,this.onMotion());const v=Math.min(...this.lastPoints.map(p=>p.x));Math.max(...this.lastPoints.map(p=>p.x))-v>o&&(this.startPoint.y=a.y,this.startPosition.y=this.position.y)}else{const l=w.accelerate(a.y-this.startPoint.y,1.7)/this.startSize.height*(this.rows/4);let m=this.startPosition.y+Math.round(l);m=Math.max(0,Math.min(m,this.rows-1)),m!==this.position.y&&(this.position.y=m,this.onMotion());const v=Math.min(...this.lastPoints.map(p=>p.y));Math.max(...this.lastPoints.map(p=>p.y))-v>o&&(this.startPoint.x=a.x,this.startPosition.x=this.position.x)}},this.isStarted=!1,this.position=t,this.frames=e,this.rows=i,this.loop=r,this.onMotion=s,this.inertia=new q(this.motion),this.initPosition={...this.position},this.startPosition={x:0,y:0},this.startPoint=new f(0,0),this.startSize={width:0,height:0},this.lastPoints=[],this.lastPointsNumber=20}destroy(){this.inertia.destroy()}reset(){this.position={...this.initPosition}}get positionIndex(){return this.frames*this.position.y+this.position.x}set positionIndex(t){if(this.positionIndex===t)return;const e=this.loop?w.mod(t,this.frames*this.rows):Math.max(0,Math.min(t,this.frames*this.rows));this.position.x=w.mod(e,this.frames),this.position.y=Math.floor(e/this.frames)}start(t,e){this.isStarted=!0,this.startPosition={...this.position},this.startPoint=t,this.startSize=e,this.lastPoints=[],this.inertia.stop()}end(t,e){this.isStarted=!1,e&&(this.inertia.track(t),this.inertia.start())}}class C{constructor(t,e,i,r){this.container=t,this.canvas=e,this.loader=i,this.images=[],this.frames=24,this.hotspotsList=[[]],this.interaction=new tt({x:0,y:0},1,1,!1,()=>{this.canvas.draw(this.image,!0,.5),this.onInteraction({position:this.interaction.positionIndex})}),this.onInteraction=r}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0)}show(){this.canvas.show(!1),this.container.classList.add("ls-viewer-container-vrobject")}hide(){this.canvas.hide(!1),this.container.classList.remove("ls-viewer-container-vrobject")}async goto(t){return new Promise(e=>{let i=this.interaction.positionIndex;const r=()=>{if(this.interaction.positionIndex===t)e();else{let s=i>t?-1:1;this.interaction.loop&&this.interaction.frames-i+t<Math.abs(t-i)&&(s*=-1),i+=.5*s,this.position=Math.floor(i),this.animationFrameId=requestAnimationFrame(r)}};this.animationFrameId=requestAnimationFrame(r)})}get position(){return this.interaction.positionIndex}set position(t){this.interaction.positionIndex=t,this.canvas.draw(this.image,!0,.5)}get image(){return this.images[this.interaction.positionIndex]}async load(t,e,i,r){let s=Promise.resolve();i&&this.interaction.reset();const a=JSON.stringify(t);a===this.snapshotHash&&this.image?s=s.then(()=>this.canvas.draw(this.image,r,.05)):(this.images=[],s=s.then(()=>this.loader.loadVRObjectSnapshot(t,this.interaction.positionIndex).then(o=>{const l=o.length;return this.images=new Array(l),this.interaction.frames=t.view.frames??t.view.panFrames??this.frames,this.interaction.rows=l/this.interaction.frames,this.interaction.loop=!!t.view.loop,i&&this.interaction.reset(),o.forEach((m,v)=>{m.then(c=>{this.images[v]=c,c===this.image&&this.canvas.draw(this.image,r,.05)}).catch(()=>{})}),o[this.interaction.positionIndex].then(()=>Promise.resolve())})));const n=JSON.stringify(e);return(a!==this.snapshotHash||n!==this.hotspotsHash)&&(e.length?s=s.then(()=>this.loader.loadVRObjectHotspots(t,e).then(o=>{this.hotspotsList=o})):this.hotspotsList=[[]]),this.hotspotsHash=n,this.snapshotHash=a,s}async pick(t,e){const i=new y(t.parameters.width,t.parameters.height),r=b.unproject(i,this.canvas.resolution,this.canvas.fit,e);return this.loader.loadVRObjectPick(t,r,this.position,this.frames)}hotspots(t){return(this.hotspotsList[this.interaction.positionIndex]||[]).map(i=>({...i,position2D:b.project(t,this.canvas.resolution,this.canvas.fit,i.position2D)})).map(i=>({...i,visibility:b.contains(this.canvas.resolution,i.position2D)?i.visibility:"OutOfFrustum"}))}snapshot(t,e){return this.canvas.element.toDataURL(t,e)}onPointerDown(t){this.container.setPointerCapture(t.pointerId),this.container.classList.add("ls-viewer-container-vrobject-grabbing"),this.interaction.start(new f(t.screenX,t.screenY),{width:this.canvas.element.width,height:this.canvas.element.height})}onPointerMove(t){this.interaction.isStarted&&(this.interaction.motion(new f(t.screenX,t.screenY)),t.preventDefault())}onPointerUp(t){this.interaction.isStarted&&(this.container.classList.remove("ls-viewer-container-vrobject-grabbing"),this.interaction.end(new f(t.screenX,t.screenY),!0))}onPointerCancel(t){this.interaction.isStarted&&(this.container.classList.remove("ls-viewer-container-vrobject-grabbing"),this.interaction.end(new f(t.screenX,t.screenY),!1))}onDeviceOrientation(t){}}class H{constructor(t,e,i){this.container=t,this.loader=i,this.video=e}destroy(){}show(){this.video.show(),this.container.classList.add("ls-viewer-container-video")}hide(){this.video.hide(),this.container.classList.remove("ls-viewer-container-video")}async load(t){const e=JSON.stringify(t);return e===this.hash?(this.video.element.load(),Promise.resolve()):(this.hash=e,this.loader.loadVideoSnapshot(this.video.element,t))}async pick(t,e){return Promise.reject()}hotspots(t){return[]}snapshot(t,e){return"data:image/gif;base64,R0lGODlhAQABAIAAAP7//wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="}async play(){return new Promise((t,e)=>{this.video.element.addEventListener("ended",()=>{t()},{once:!0}),this.video.element.play().catch(e),this.show()})}onPointerDown(t){}onPointerMove(t){}onPointerUp(t){}onPointerCancel(t){}onDeviceOrientation(t){}}class et{constructor(t,e){this.onPointerDown=i=>{this.container.addEventListener("pointermove",this.onPointerMove,{passive:!1}),this.widget.onPointerDown(i)},this.onPointerMove=i=>{this.widget.onPointerMove(i)},this.onPointerUp=i=>{this.container.removeEventListener("pointermove",this.onPointerMove),this.widget.onPointerUp(i)},this.onPointerCancel=i=>{this.container.removeEventListener("pointermove",this.onPointerMove),this.widget.onPointerCancel(i)},this.onDeviceOrientation=i=>{this.widget.onDeviceOrientation(i)},this.onResize=()=>{const i=this.container.clientWidth,r=this.container.clientHeight;this.options.autores&&(this.resolution=b.getStandardResolution(i*window.devicePixelRatio,r*window.devicePixelRatio,this.aspectRatioOverride),this.parameters.width=this.resolution.width,this.parameters.height=this.resolution.height),this.canvas2D.resize(i,r,this.getCanvas2DPixelRatio(i,r)),this.canvas3D.resize(i,r,window.devicePixelRatio),this.video.resize(i,r,this.resolution,this.options.fit),this.loadWidget(!1,!1).then(()=>{this.onHotspotsChange()}).catch(s=>{this.onLoadError(s)})},this.onVrcubeInteraction=i=>{this.onHotspotsChange(),this.options.events.onInteraction?.(i),this.options.events.onVrcubeInteraction?.(i)},this.onVrobjectInteraction=i=>{this.onHotspotsChange(),this.options.events.onInteraction?.(i.position),this.options.events.onVrobjectInteraction?.(i.position)},this.onHotspotsChange=()=>{const i=this.widget.hotspots(this.resolution);i.length&&this.options.events.onHotspotsChange?.(i)},this.onLoadStart=i=>{this.container.classList.add("ls-viewer-container-loading"),this.options.events.onLoadStart?.(i)},this.onLoadProgress=i=>{this.options.events.onLoadProgress?.(i)},this.onLoadEnd=i=>{this.container.classList.remove("ls-viewer-container-loading"),this.options.events.onLoadEnd?.(i)},this.onLoadError=i=>{i instanceof DOMException&&i.name==="AbortError"||(this.container.classList.remove("ls-viewer-container-loading"),this.options.events.onLoadError?.(i))},this.options={server:"localhost",api:"v1",autores:!0,fit:"cover",...e,events:{...e.events}},this.options.events.onLoadError&&(this.options.events.onLoadError=D(this.options.events.onLoadError,10)),this.container=t,this.container.classList.add("ls-viewer-container"),this.canvas2D=new B(this.options.fit),this.container.prepend(this.canvas2D.element),this.canvas3D=new X,this.container.prepend(this.canvas3D.element),this.video=new W,this.container.prepend(this.video.element),this.loader=new k(this.options.server,this.options.api,this),this.resolution=new y(0,0),this.parameters={width:0,height:0,antialiasing:!1,superSampling:2},this.encoder={format:"jpeg",quality:80},this.hotspots=[],this.widgetImage=new j(t,this.canvas2D,this.loader),this.widgetVideo=new H(t,this.video,this.loader),this.widgetVRObject=new C(t,this.canvas2D,this.loader,this.onVrobjectInteraction),this.canvas3D.context&&(this.widgetVRCube=new R(t,this.canvas3D,this.loader,this.onVrcubeInteraction,this.aspectRatioOverride)),this.widget=this.widgetImage,this.container.addEventListener("pointerdown",this.onPointerDown),this.container.addEventListener("pointerup",this.onPointerUp),this.container.addEventListener("pointercancel",this.onPointerCancel),this.loadWidget=D(this.loadWidget,10),this.resizeObserver=new ResizeObserver(this.onResize),this.resizeObserver.observe(this.container)}destroy(){this.resizeObserver.disconnect(),this.canvas2D.destroy(),this.container.removeEventListener("pointerdown",this.onPointerDown),this.container.removeEventListener("pointerup",this.onPointerUp),this.container.removeEventListener("pointercancel",this.onPointerCancel),this.container.removeEventListener("pointermove",this.onPointerMove)}async load(t,e){let i=Promise.resolve();return e?.animation&&(i=i.then(()=>this.loadAnimation(e.animation))),this.view&&e?.fromPosition!==void 0&&this.viewWidget instanceof C&&(this.view.mode,i=i.then(()=>this.viewWidget.goto(e.fromPosition))),e?.animation&&(i=i.then(()=>this.widgetVideo.play())),i=i.then(()=>(this.scene=Array.isArray(t)?[...t]:[t],this.loadWidget(!1,!(e&&e.animation)))),i.catch(r=>{this.onLoadError(r)}),i}async setEncoder(t){this.encoder={...t};let e=Promise.resolve();return e=e.then(()=>this.loadWidget(!1,!0)),e.catch(i=>{this.onLoadError(i)}),e}setParameters(t){if(t.width&&t.height){this.resolution=new y(t.width,t.height);const i=this.container.clientWidth,r=this.container.clientHeight;this.canvas2D.resize(i,r,this.getCanvas2DPixelRatio(i,r))}this.parameters={...t},this.parameters.width=this.resolution.width,this.parameters.height=this.resolution.height;let e=Promise.resolve();return e=e.then(()=>this.loadWidget(!1,!0)),e.catch(i=>{this.onLoadError(i)}),e}setHotspots(t){this.hotspots=t,this.loadWidget(!1,!1)}async setView(t,e){let i=Promise.resolve();return e?.animation&&(i=i.then(()=>this.loadAnimation(e.animation))),this.view&&e?.fromPosition!==void 0&&this.viewWidget instanceof C&&(i=i.then(()=>this.viewWidget.goto(e.fromPosition))),e?.animation&&(i=i.then(()=>this.widgetVideo.play())),i=i.then(()=>{let r=!0;return this.view={...t},this.view&&this.viewWidget instanceof C&&e?.toPosition!==void 0&&(r=!1,this.viewWidget.position=e.toPosition),this.loadWidget(r,!(e&&e.animation))}),i.catch(r=>{this.onLoadError(r)}),i}setVrcube(t){this.widgetVRCube&&Object.assign(this.widgetVRCube,t)}setVrobject(t){Object.assign(this.widgetVRObject,t)}async loadAnimation(t){const e={scene:this.scene,view:{animation:t.name,camera:t.camera,duration:t.duration,loop:t.loop,reverse:t.reverse},parameters:this.parameters,encoder:{format:"mp4"}};return e.view?.background||(e.view.background="product"),this.widgetVideo.load(e).then(()=>Promise.resolve())}async playAnimation(t){return this.loadAnimation(t).then(()=>this.widgetVideo.play()).catch(e=>{this.onLoadError(e)})}stopAnimation(){this.widgetVideo.hide()}async pick(t){if(!this.scene)throw new Error("No scene set");if(!this.view)throw new Error("No view set");if(!this.view.camera&&!this.view.cameraGroup)throw new Error("No camera set");const e={scene:this.scene,view:this.view,parameters:this.parameters,encoder:this.encoder};return await this.viewWidget.pick(e,t)}async pickHotspot(t){const e=await this.pick(t),i=Object.values(e.point),r=h.v3.normalize(Object.values(e.normal)),s=h.v3.add(i,h.v3.mulScalar(r,.01));return e.point={x:s[0],y:s[1],z:s[2]},e}snapshot(t,e){return this.viewWidget.snapshot(t,e)}async loadWidget(t,e){if(!this.scene||!this.view||!this.parameters.width||!this.parameters.height)return Promise.resolve();const i=this.viewWidget;if(!i)return Promise.reject(new Error("Unknown view mode"));const r={scene:this.scene,view:this.view,parameters:this.parameters,encoder:this.encoder};return r.view.background||(r.view.background="product"),i.load(r,this.hotspots,t,e).then(()=>{this.widget.hide(),this.widget=i,this.widget.show(),this.widgetVideo.hide(),this.onHotspotsChange()})}get aspectRatioOverride(){switch(this.options.aspectRatio){case"4:3":return 4/3;case"16:9":return 16/9;default:return}}get viewWidget(){switch(this.view?.mode){case"image":return this.widgetImage;case"video":return this.widgetVideo;case"vrcube":return this.widgetVRCube??this.widgetImage;case"vrobject":return this.widgetVRObject;default:return this.widgetImage}}getCanvas2DPixelRatio(t,e){return t<=0||e<=0||this.resolution.width<=0||this.resolution.height<=0?window.devicePixelRatio:Math.min(window.devicePixelRatio,this.resolution.width/t,this.resolution.height/e)}}exports.WRAPIv2=void 0;(u=>{(t=>{t.Visible="Visible",t.Occluded="Occluded",t.Clipped="Clipped",t.OutOfFrustum="OutOfFrustum"})(u.HotspotVisibility||(u.HotspotVisibility={})),(t=>{t.VeryLow="veryLow",t.Low="low",t.Medium="medium",t.Fine="fine",t.Ultra="ultra"})(u.SunShadowQualityMode||(u.SunShadowQualityMode={})),(t=>{t.None="none",t.Weak="weak",t.Normal="normal",t.Fine="fine",t.UltraFine="ultraFine",t.Max="max"})(u.SunShadowSmoothnessMode||(u.SunShadowSmoothnessMode={})),(t=>{t.Manual="manual",t.TimeAndLoc="timeAndLoc",t.ExtractedFromEnv="extractedFromEnv"})(u.SunUseCaseMode||(u.SunUseCaseMode={})),(t=>{t.ShowOnly="showOnly",t.HideOnly="hideOnly"})(u.SurfacesFilterMode||(u.SurfacesFilterMode={}))})(exports.WRAPIv2||(exports.WRAPIv2={}));exports.Viewer=et;exports.WidgetImage=j;exports.WidgetVRCube=R;exports.WidgetVRObject=C;exports.WidgetVideo=H;
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -42,6 +42,17 @@ export declare interface Encoder {
|
|
|
42
42
|
quality?: number;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export declare interface Events {
|
|
46
|
+
onLoadStart?: (progress: number) => void;
|
|
47
|
+
onLoadProgress?: (progress: number) => void;
|
|
48
|
+
onLoadEnd?: (progress: number) => void;
|
|
49
|
+
onLoadError?: (error: unknown) => void;
|
|
50
|
+
onInteraction?: (data: number | VrCubeInteractionData) => void;
|
|
51
|
+
onVrcubeInteraction?: (data: VrCubeInteractionData) => void;
|
|
52
|
+
onVrobjectInteraction?: (position: number) => void;
|
|
53
|
+
onHotspotsChange?: (hotspots: Hotspot[]) => void;
|
|
54
|
+
}
|
|
55
|
+
|
|
45
56
|
export declare interface Hotspot {
|
|
46
57
|
id: string;
|
|
47
58
|
name: string;
|
|
@@ -63,12 +74,13 @@ declare class Loader {
|
|
|
63
74
|
private webrender;
|
|
64
75
|
private webrenderV2?;
|
|
65
76
|
private delegate?;
|
|
66
|
-
private
|
|
77
|
+
private controller;
|
|
67
78
|
private loaded;
|
|
68
79
|
private total;
|
|
69
80
|
private databases;
|
|
70
81
|
constructor(server: string, api: string, delegate: LoaderDelegate);
|
|
71
82
|
get progress(): number;
|
|
83
|
+
private renew;
|
|
72
84
|
loadImageSnapshot(snapshot: Snapshot): Promise<HTMLImageElement>;
|
|
73
85
|
loadVideoSnapshot(video: HTMLVideoElement, snapshot: Snapshot): Promise<any>;
|
|
74
86
|
loadVRCubeSnapshot(snapshot: Snapshot): Promise<HTMLImageElement[]>;
|
|
@@ -105,11 +117,7 @@ export declare interface Options {
|
|
|
105
117
|
aspectRatio?: '4:3' | '16:9';
|
|
106
118
|
autores: boolean;
|
|
107
119
|
fit: 'contain' | 'cover' | 'fill';
|
|
108
|
-
|
|
109
|
-
video: any;
|
|
110
|
-
vrcube: any;
|
|
111
|
-
vrobject: any;
|
|
112
|
-
events: any;
|
|
120
|
+
events: Events;
|
|
113
121
|
}
|
|
114
122
|
|
|
115
123
|
declare interface Parameters_2 {
|
|
@@ -224,25 +232,27 @@ export declare class Viewer {
|
|
|
224
232
|
private loadWidget;
|
|
225
233
|
private get aspectRatioOverride();
|
|
226
234
|
private get viewWidget();
|
|
227
|
-
private
|
|
228
|
-
private
|
|
229
|
-
private
|
|
230
|
-
private
|
|
231
|
-
private onTouchStart;
|
|
232
|
-
private onTouchMove;
|
|
233
|
-
private onTouchEnd;
|
|
235
|
+
private onPointerDown;
|
|
236
|
+
private onPointerMove;
|
|
237
|
+
private onPointerUp;
|
|
238
|
+
private onPointerCancel;
|
|
234
239
|
private onDeviceOrientation;
|
|
235
240
|
private getCanvas2DPixelRatio;
|
|
236
241
|
private onResize;
|
|
237
242
|
private onVrcubeInteraction;
|
|
238
243
|
private onVrobjectInteraction;
|
|
239
244
|
private onHotspotsChange;
|
|
240
|
-
onLoadStart(
|
|
241
|
-
onLoadProgress(
|
|
242
|
-
onLoadEnd(
|
|
245
|
+
onLoadStart: (progress: number) => void;
|
|
246
|
+
onLoadProgress: (progress: number) => void;
|
|
247
|
+
onLoadEnd: (progress: number) => void;
|
|
243
248
|
private onLoadError;
|
|
244
249
|
}
|
|
245
250
|
|
|
251
|
+
export declare interface VrCubeInteractionData {
|
|
252
|
+
pov: PointOfView;
|
|
253
|
+
fov: number;
|
|
254
|
+
}
|
|
255
|
+
|
|
246
256
|
export declare interface WebRenderScene {
|
|
247
257
|
database: string;
|
|
248
258
|
configuration?: string;
|
|
@@ -263,13 +273,10 @@ export declare interface Widget {
|
|
|
263
273
|
hotspots(resolution: Resolution): Hotspot[];
|
|
264
274
|
pick(snapshot: Snapshot, position: WRAPIv2.Vector2D): Promise<WRAPIv2.PickResult>;
|
|
265
275
|
snapshot(type: string, quality: number): string;
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
onTouchStart(e: TouchEvent): void;
|
|
271
|
-
onTouchMove(e: TouchEvent): void;
|
|
272
|
-
onTouchEnd(e: TouchEvent): void;
|
|
276
|
+
onPointerDown(e: PointerEvent): void;
|
|
277
|
+
onPointerMove(e: PointerEvent): void;
|
|
278
|
+
onPointerUp(e: PointerEvent): void;
|
|
279
|
+
onPointerCancel(e: PointerEvent): void;
|
|
273
280
|
onDeviceOrientation(e: DeviceOrientationEvent): void;
|
|
274
281
|
}
|
|
275
282
|
|
|
@@ -289,13 +296,10 @@ export declare class WidgetImage implements Widget {
|
|
|
289
296
|
pick(snapshot: Snapshot, position: WRAPIv2.Vector2D): Promise<WRAPIv2.PickResult>;
|
|
290
297
|
hotspots(resolution: Resolution): Hotspot[];
|
|
291
298
|
snapshot(type: string, quality: number): string;
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
onTouchStart(e: TouchEvent): void;
|
|
297
|
-
onTouchMove(e: TouchEvent): void;
|
|
298
|
-
onTouchEnd(e: TouchEvent): void;
|
|
299
|
+
onPointerDown(e: PointerEvent): void;
|
|
300
|
+
onPointerMove(e: PointerEvent): void;
|
|
301
|
+
onPointerUp(e: PointerEvent): void;
|
|
302
|
+
onPointerCancel(e: PointerEvent): void;
|
|
299
303
|
onDeviceOrientation(e: DeviceOrientationEvent): void;
|
|
300
304
|
}
|
|
301
305
|
|
|
@@ -313,13 +317,10 @@ export declare class WidgetVideo implements Widget {
|
|
|
313
317
|
hotspots(resolution: Resolution): Hotspot[];
|
|
314
318
|
snapshot(type: string, quality: number): string;
|
|
315
319
|
play(): Promise<void>;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
onTouchStart(e: TouchEvent): void;
|
|
321
|
-
onTouchMove(e: TouchEvent): void;
|
|
322
|
-
onTouchEnd(e: TouchEvent): void;
|
|
320
|
+
onPointerDown(e: PointerEvent): void;
|
|
321
|
+
onPointerMove(e: PointerEvent): void;
|
|
322
|
+
onPointerUp(e: PointerEvent): void;
|
|
323
|
+
onPointerCancel(e: PointerEvent): void;
|
|
323
324
|
onDeviceOrientation(e: DeviceOrientationEvent): void;
|
|
324
325
|
}
|
|
325
326
|
|
|
@@ -352,14 +353,11 @@ export declare class WidgetVRCube implements Widget {
|
|
|
352
353
|
hotspots(): Hotspot[];
|
|
353
354
|
snapshot(type: string, quality: number): string;
|
|
354
355
|
private get modelViewProjectionMatrix();
|
|
355
|
-
render()
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
onTouchStart(e: TouchEvent): void;
|
|
361
|
-
onTouchMove(e: TouchEvent): void;
|
|
362
|
-
onTouchEnd(e: TouchEvent): void;
|
|
356
|
+
render: () => void;
|
|
357
|
+
onPointerDown(e: PointerEvent): void;
|
|
358
|
+
onPointerMove(e: PointerEvent): void;
|
|
359
|
+
onPointerUp(e: PointerEvent): void;
|
|
360
|
+
onPointerCancel(e: PointerEvent): void;
|
|
363
361
|
onDeviceOrientation(e: DeviceOrientationEvent): void;
|
|
364
362
|
}
|
|
365
363
|
|
|
@@ -387,13 +385,10 @@ export declare class WidgetVRObject implements Widget {
|
|
|
387
385
|
pick(snapshot: Snapshot, position: WRAPIv2.Vector2D): Promise<WRAPIv2.PickResult>;
|
|
388
386
|
hotspots(resolution: Resolution): Hotspot[];
|
|
389
387
|
snapshot(type: string, quality: number): string;
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
onTouchStart(e: TouchEvent): void;
|
|
395
|
-
onTouchMove(e: TouchEvent): void;
|
|
396
|
-
onTouchEnd(e: TouchEvent): void;
|
|
388
|
+
onPointerDown(e: PointerEvent): void;
|
|
389
|
+
onPointerMove(e: PointerEvent): void;
|
|
390
|
+
onPointerUp(e: PointerEvent): void;
|
|
391
|
+
onPointerCancel(e: PointerEvent): void;
|
|
397
392
|
onDeviceOrientation(e: DeviceOrientationEvent): void;
|
|
398
393
|
}
|
|
399
394
|
|