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