itowns 2.43.2-next.25 → 2.43.2-next.26

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.
@@ -1,2 +1,2 @@
1
- "use strict";!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("itowns_widgets",[],e):"object"==typeof exports?exports.itowns_widgets=e():t.itowns_widgets=e()}(self,(()=>(self.webpackChunkitowns=self.webpackChunkitowns||[]).push([[605],{12587:(t,e,o)=>{o.r(e),o.d(e,{C3DTilesStyle:()=>I,Minimap:()=>f,Navigation:()=>c,Scale:()=>y,Searchbar:()=>T,Widget:()=>n});var i=o(59432);const n=class{#t;constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2?arguments[2]:void 0;this.parentElement=e.parentElement||t.domElement,this.position=e.position||o.position,["top-left","top-right","bottom-left","bottom-right","top","bottom","left","right"].includes(this.position)||(console.warn(`'position' optional parameter for 'Widget' constructor is not a valid option. It will be set to '${o.position}'.`),this.position=o.position),this.domElement=document.createElement("div"),this.parentElement.appendChild(this.domElement),this.domElement.style.width=`${e.width||e.size||o.width}px`,this.domElement.style.height=`${e.height||e.size||o.height}px`;const i=this.position.split("-");if(this.domElement.classList.add(`${i[0]}-widget`),i[1])this.domElement.classList.add(`${i[1]}-widget`);else switch(i[0]){case"top":case"bottom":this.domElement.style.left=`calc(50% - ${this.domElement.offsetWidth/2}px)`;break;case"left":case"right":this.domElement.style.top=`calc(50% - ${this.domElement.offsetHeight/2}px)`}e.translate&&(this.domElement.style.transform=`translate(${e.translate.x||0}px, ${e.translate.y||0}px)`),this.domElement.addEventListener("pointerdown",(t=>{t.stopPropagation()})),this.domElement.addEventListener("mousedown",(t=>{t.stopPropagation()}))}show(){this.domElement.style.display=this.#t}hide(){this.#t=window.getComputedStyle(this.domElement).display,this.domElement.style.display="none"}},s={displayCompass:!0,display3DToggle:!0,displayZoomIn:!0,displayZoomOut:!0,animationDuration:500,position:"bottom-left",direction:"column"},a={id:"compass",content:"",info:"Rotate the camera to face North",parentId:"widgets"},l={id:"3d-button",content:"3D",info:"Tilt the camera"},r={id:"zoom-in-button",content:'<span class="widget-zoom-button-logo"></span>',info:"Zoom in",parentId:"zoom-button-bar"},d={id:"zoom-out-button",content:'<span id="zoom-out-logo" class="widget-zoom-button-logo"></span>',info:"Zoom out",parentId:"zoom-button-bar"},c=class extends n{#e;#o(t){return t.time=this.animationDuration,this.#e.controls.lookAtCoordinate(t)}#i(t,e){return this.addButton(t.id,t.content,t.info,e,t.parentId)}constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!t.isGlobeView)throw new Error("'Navigation' plugin only supports 'GlobeView'. Therefore, the 'view' parameter must be a 'GlobeView'.");["top","bottom","left","right"].includes(e.position)&&(console.warn(`'position' optional parameter for 'Navigation' is not a valid option. It will be set to '${s.position}'.`),e.position=s.position),super(t,e,s),this.#e=t,this.direction=e.direction||s.direction,["column","row"].includes(this.direction)||(console.warn(`'direction' optional parameter for 'Navigation' constructor is not a valid option. It will be set to '${s.direction}'.`),this.direction=s.direction),this.animationDuration=void 0===e.animationDuration?s.animationDuration:e.animationDuration,this.domElement.id="widgets-navigation",this.domElement.classList.add(`${this.direction}-widget`),(e.displayCompass??s.displayCompass)&&(this.compass=this.#i(a,(()=>{this.#o({heading:0,tilt:89.5})})),t.addEventListener(i.G.CAMERA_MOVED,(t=>{this.compass.style.transform=`rotate(${-t.heading}deg)`}))),(e.display3DToggle??s.display3DToggle)&&(this.toggle3D=this.#i(l,(()=>{this.#o({tilt:this.#e.controls.getTilt()<89?89.5:40})})),t.addEventListener(i.G.CAMERA_MOVED,(t=>{this.toggle3D.innerHTML=t.tilt<89?"2D":"3D"}))),(e.displayZoomIn??s.displayZoomIn)&&(this.zoomIn=this.#i(r,(()=>{this.#o({zoom:Math.min(20,this.#e.controls.getZoom()+1)})}))),(e.displayZoomOut??s.displayZoomOut)&&(this.zoomOut=this.#i(d,(()=>{this.#o({zoom:Math.max(3,this.#e.controls.getZoom()-1)})})))}addButton(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:()=>{},n=arguments.length>4?arguments[4]:void 0,s=document.getElementById(n);s||(s=this.addButtonBar(n));const a=document.createElement("button");return a.className="widget-button",a.id=t,a.innerHTML=e,a.title=o,a.onclick=i,s.appendChild(a),a.tabIndex=-1,window.addEventListener("pointerup",(()=>{document.activeElement===a&&this.#e.domElement.focus()})),a}addButtonBar(t){const e=document.createElement("div");return e.className="widget-button-bar",t&&(e.id=t),this.domElement.appendChild(e),e}};var m=o(52404),h=o(87196),p=o(8917),u=o(93320);const g={minScale:2e-6,maxScale:2e-9,zoomRatio:1/30,width:150,height:150,position:"bottom-left"},f=class extends n{constructor(t,e){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(!t.isGlobeView)throw new Error("'Minimap' plugin only supports 'GlobeView'. Therefore, the 'view' parameter must be a 'GlobeView'.");if(!e.isColorLayer)throw new Error("'layer' parameter form 'Minimap' constructor should be a 'ColorLayer'.");if(super(t,o,g),this.minScale=o.minScale||g.minScale,this.maxScale=o.maxScale||g.maxScale,this.zoomRatio=o.zoomRatio||g.zoomRatio,this.domElement.id="widgets-minimap",o.cursor){const t=document.createElement("div");t.id="cursor-wrapper",this.domElement.appendChild(t),"string"==typeof o.cursor?t.innerHTML=o.cursor:o.cursor instanceof HTMLElement&&t.appendChild(o.cursor)}this.view=new p.A(this.domElement,e.source.extent,{camera:{type:u.d.ORTHOGRAPHIC},placement:e.source.extent,noControls:!0,maxSubdivisionLevel:t.tileLayer.maxSubdivisionLevel,disableFocusOnStart:!0}),this.view.addLayer(e),this.domElement.addEventListener("pointerdown",(t=>{t.preventDefault()}));const i=this.view.getScale(o.pitch),n=this.view.camera3D.zoom*this.maxScale/i,s=this.view.camera3D.zoom*this.minScale/i,a=new m.A(t.referenceCrs),l=new m.A(this.view.referenceCrs),r=t.controls.getCameraTargetPosition();t.addFrameRequester(h.n7.AFTER_RENDER,(()=>{const e=t.camera3D.position.distanceTo(r),i=t.getScaleFromDistance(o.pitch,e);this.view.camera3D.zoom=this.zoomRatio*s*i/this.minScale,this.view.camera3D.zoom=Math.min(Math.max(this.view.camera3D.zoom,n),s),this.view.camera3D.updateProjectionMatrix(),a.setFromVector3(t.controls.getCameraTargetPosition()),a.as(this.view.referenceCrs,l),this.view.camera3D.position.x=l.x,this.view.camera3D.position.y=l.y,this.view.camera3D.updateMatrixWorld(!0),this.view.notifyChange(this.view.camera3D)}))}};var w=o(98211),v=o(86397),E=o(72682);const b={width:200,height:30,position:"bottom-left"},y=class extends n{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(t,e,b),this.domElement.id="widgets-scale",this.view=t,this.domElement.innerHTML="Scale",this.width=e.width||b.width,this.view.isGlobeView?(this.view.addEventListener(v.S.GLOBE_INITIALIZED,(()=>{this.update()})),this.view.controls.addEventListener(w.W.RANGE_CHANGED,(()=>{this.update()}))):this.view.isPlanarView?(this.view.addEventListener(i.G.INITIALIZED,(()=>{this.update()})),this.view.addEventListener(E.w7.MOVED,(()=>{this.update()}))):console.warn("The 'view' linked to scale widget is neither a 'GlobeView' nor a 'PlanarView'. The scale wont automatically update. You can implement its update automation using 'Scale.update' method.")}addEventListeners(){}update(){let t=Math.round(this.view.getPixelsToMeters(this.width));const e=10**(t.toString().length-1);t=Math.round(t/e)*e;const o=this.view.getMetersToPixels(t);let i="m";t>=1e3&&(t/=1e3,i="km"),this.domElement.innerHTML=`${t} ${i}`,this.domElement.style.width=`${o}px`}};var C=o(7794);const x={width:300,height:38,position:"top",maxSuggestionNumber:10,fontSize:16,placeholder:"Search location"};function L(t,e){return t?(D(t),e>=t.length?e=0:e<0&&(e=t.length-1),t[e]?.classList.add("active"),e):e}function D(t){for(let e=0;e<t.length;e++)t[e].classList.remove("active")}function S(t){for(;t.children.length>1;)t.removeChild(t.lastChild)}const T=class extends n{#n;constructor(t,e){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(super(t,o,x),!e||!e.url||!e.parser||"function"!=typeof e.parser)throw new Error("'geocodingOptions' parameter for 'Searchbar' constructor is not a valid option. Please refer to the documentation.");this.#n=e.onSelected??(()=>{}),this.domElement.id="widgets-searchbar",this.domElement.style.height="auto";const i=document.createElement("form");i.setAttribute("autocomplete","off"),i.id="searchbar-autocompletion-form",this.domElement.appendChild(i);const n=document.createElement("input");let s;n.setAttribute("type","text"),n.setAttribute("name","mySearch"),n.setAttribute("placeholder",o.placeholder||x.placeholder),n.style.height=`${o.height||o.size||x.height}px`,n.style.fontSize=`${o.fontSize||x.fontSize}px`,i.appendChild(n),n.addEventListener("input",(()=>{const t=n.value;if(S(i),s=-1,!t)return!1;e.url.searchParams.set("text",t),C.A.json(e.url).then((a=>{const l=e.parser(a);let r=0;l.forEach(((e,a)=>{if(r===Math.min(l.size,o.maxSuggestionNumber||x.maxSuggestionNumber))return;const d=r;r++;const c=a.toUpperCase().indexOf(t.toUpperCase());if(c>-1){const l=document.createElement("div");l.style.minHeight=n.style.height,l.style.fontSize=`${o.fontSize||x.fontSize}px`;const r=a.slice(0,c),m=a.slice(c,c+t.length),h=a.slice(c+t.length,a.length);l.innerHTML=`<p>${r}<strong>${m}</strong>${h}</p>`,l.setAttribute("location",a),i.appendChild(l),l.addEventListener("mouseover",(()=>{D(i.children),s=d,l.classList.add("active")})),l.addEventListener("click",(()=>{this.#n(e),n.value=l.getAttribute("location"),S(i)}))}}))}))}));const a=(o.position||x.position).includes("top")?1:-1;n.addEventListener("keydown",(e=>{e.stopPropagation();const o=i.getElementsByTagName("div");switch(e.code){case"Escape":S(i),n.value="",t.domElement.focus();break;case"ArrowDown":e.preventDefault(),s=L(o,s+a);break;case"ArrowUp":e.preventDefault(),s=L(o,s-a);break;case"Enter":e.preventDefault(),o[Math.max(s,0)]&&(o[Math.max(s,0)].click(),t.domElement.focus())}})),n.addEventListener("focus",(()=>{i.classList.add("focus")})),n.addEventListener("blur",(()=>{i.classList.remove("focus"),D(i.children)})),i.addEventListener("mouseleave",(()=>{D(i.children),s=-1}))}};var _=o(48306),M=o(14333);const z={width:200,position:"top-right"};class A extends n{constructor(t,e){super(t,e,z),this.domElement.onclick=t=>t.stopImmediatePropagation();const o=document.createElement("select");this.domElement.appendChild(o);const i=new Map,n=()=>{for(const[t,e]of i)e.hidden=t!==o.selectedOptions[0]};o.onchange=n,t.getLayers().filter((t=>!0===t.isC3DTilesLayer)).forEach((e=>{const n=document.createElement("option");n.innerText=e.name,o.add(n);const s=document.createElement("div");this.domElement.appendChild(s),i.set(n,s),e.addEventListener(M.s.ON_TILE_CONTENT_LOADED,(()=>{for(;s.firstChild;)s.firstChild.remove();const o=new Map;for(const[,t]of e.tilesC3DTileFeatures)for(const[,e]of t)for(const t in e.getInfo().batchTable){o.has(t)||o.set(t,[]);const i=e.getInfo().batchTable[t];o.get(t).includes(i)||o.get(t).push(i)}const i=new Map,n=new Map,a=(o,a,l)=>{const r=document.createElement("input");r.setAttribute("type","color"),s.appendChild(r),r.onchange=()=>{const n=o();if(!l.includes(n))return;const s=r.value;i.set(n,(t=>t.getInfo().batchTable[a]==n?s:null)),e.updateStyle(),t.notifyChange()};const d=document.createElement("input");return d.setAttribute("type","range"),d.min=0,d.max=1,d.step=.1,d.value=1,s.appendChild(d),d.onchange=()=>{const i=o();if(!l.includes(i))return;const s=d.value;n.set(i,(t=>t.getInfo().batchTable[a]==i?s:null)),e.updateStyle(),t.notifyChange()},{inputColor:r,opacityElement:d}},l=(t,e)=>{const o=document.createElement("label");o.innerText=t,s.appendChild(o);const i=document.createElement("select");s.appendChild(i),e.forEach((t=>{const e=document.createElement("option");e.value=t,e.text=t,i.add(e)})),a((()=>i.selectedOptions[0].value),t,e)},r=(o,l)=>{const r=document.createElement("label");r.innerText=o,s.appendChild(r);const d=document.createElement("input");d.setAttribute("type","text"),s.appendChild(d);const{inputColor:c,opacityElement:m}=a((()=>d.value),o,l);d.onchange=()=>{if(!l.includes(d.value))return;const s=c.value,a=d.value;i.set(a,(t=>t.getInfo().batchTable[o]==a?s:null));const r=m.value;n.set(a,(t=>t.getInfo().batchTable[o]==a?r:null)),e.updateStyle(),t.notifyChange()}};for(const[t,e]of o)e.length<A.MAX_SELECT_VALUE?l(t,e):r(t,e);e.style=new _.Ay({fill:{color:t=>{let e=null;for(const[,o]of i)e=o(t)||e;return e},opacity:t=>{let e=1;for(const[,o]of n)e=o(t)||e;return e}}})}))})),n()}static get MAX_SELECT_VALUE(){return 10}}const I=A}},t=>t(t.s=12587)])));
1
+ "use strict";!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("itowns_widgets",[],e):"object"==typeof exports?exports.itowns_widgets=e():t.itowns_widgets=e()}(self,(()=>(self.webpackChunkitowns=self.webpackChunkitowns||[]).push([[605],{12587:(t,e,o)=>{o.r(e),o.d(e,{C3DTilesStyle:()=>I,Minimap:()=>f,Navigation:()=>c,Scale:()=>y,Searchbar:()=>T,Widget:()=>n});var i=o(84354);const n=class{#t;constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2?arguments[2]:void 0;this.parentElement=e.parentElement||t.domElement,this.position=e.position||o.position,["top-left","top-right","bottom-left","bottom-right","top","bottom","left","right"].includes(this.position)||(console.warn(`'position' optional parameter for 'Widget' constructor is not a valid option. It will be set to '${o.position}'.`),this.position=o.position),this.domElement=document.createElement("div"),this.parentElement.appendChild(this.domElement),this.domElement.style.width=`${e.width||e.size||o.width}px`,this.domElement.style.height=`${e.height||e.size||o.height}px`;const i=this.position.split("-");if(this.domElement.classList.add(`${i[0]}-widget`),i[1])this.domElement.classList.add(`${i[1]}-widget`);else switch(i[0]){case"top":case"bottom":this.domElement.style.left=`calc(50% - ${this.domElement.offsetWidth/2}px)`;break;case"left":case"right":this.domElement.style.top=`calc(50% - ${this.domElement.offsetHeight/2}px)`}e.translate&&(this.domElement.style.transform=`translate(${e.translate.x||0}px, ${e.translate.y||0}px)`),this.domElement.addEventListener("pointerdown",(t=>{t.stopPropagation()})),this.domElement.addEventListener("mousedown",(t=>{t.stopPropagation()}))}show(){this.domElement.style.display=this.#t}hide(){this.#t=window.getComputedStyle(this.domElement).display,this.domElement.style.display="none"}},s={displayCompass:!0,display3DToggle:!0,displayZoomIn:!0,displayZoomOut:!0,animationDuration:500,position:"bottom-left",direction:"column"},a={id:"compass",content:"",info:"Rotate the camera to face North",parentId:"widgets"},l={id:"3d-button",content:"3D",info:"Tilt the camera"},r={id:"zoom-in-button",content:'<span class="widget-zoom-button-logo"></span>',info:"Zoom in",parentId:"zoom-button-bar"},d={id:"zoom-out-button",content:'<span id="zoom-out-logo" class="widget-zoom-button-logo"></span>',info:"Zoom out",parentId:"zoom-button-bar"},c=class extends n{#e;#o(t){return t.time=this.animationDuration,this.#e.controls.lookAtCoordinate(t)}#i(t,e){return this.addButton(t.id,t.content,t.info,e,t.parentId)}constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!t.isGlobeView)throw new Error("'Navigation' plugin only supports 'GlobeView'. Therefore, the 'view' parameter must be a 'GlobeView'.");["top","bottom","left","right"].includes(e.position)&&(console.warn(`'position' optional parameter for 'Navigation' is not a valid option. It will be set to '${s.position}'.`),e.position=s.position),super(t,e,s),this.#e=t,this.direction=e.direction||s.direction,["column","row"].includes(this.direction)||(console.warn(`'direction' optional parameter for 'Navigation' constructor is not a valid option. It will be set to '${s.direction}'.`),this.direction=s.direction),this.animationDuration=void 0===e.animationDuration?s.animationDuration:e.animationDuration,this.domElement.id="widgets-navigation",this.domElement.classList.add(`${this.direction}-widget`),(e.displayCompass??s.displayCompass)&&(this.compass=this.#i(a,(()=>{this.#o({heading:0,tilt:89.5})})),t.addEventListener(i.G.CAMERA_MOVED,(t=>{this.compass.style.transform=`rotate(${-t.heading}deg)`}))),(e.display3DToggle??s.display3DToggle)&&(this.toggle3D=this.#i(l,(()=>{this.#o({tilt:this.#e.controls.getTilt()<89?89.5:40})})),t.addEventListener(i.G.CAMERA_MOVED,(t=>{this.toggle3D.innerHTML=t.tilt<89?"2D":"3D"}))),(e.displayZoomIn??s.displayZoomIn)&&(this.zoomIn=this.#i(r,(()=>{this.#o({zoom:Math.min(20,this.#e.controls.getZoom()+1)})}))),(e.displayZoomOut??s.displayZoomOut)&&(this.zoomOut=this.#i(d,(()=>{this.#o({zoom:Math.max(3,this.#e.controls.getZoom()-1)})})))}addButton(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:()=>{},n=arguments.length>4?arguments[4]:void 0,s=document.getElementById(n);s||(s=this.addButtonBar(n));const a=document.createElement("button");return a.className="widget-button",a.id=t,a.innerHTML=e,a.title=o,a.onclick=i,s.appendChild(a),a.tabIndex=-1,window.addEventListener("pointerup",(()=>{document.activeElement===a&&this.#e.domElement.focus()})),a}addButtonBar(t){const e=document.createElement("div");return e.className="widget-button-bar",t&&(e.id=t),this.domElement.appendChild(e),e}};var m=o(52404),h=o(87196),p=o(8917),u=o(93320);const g={minScale:2e-6,maxScale:2e-9,zoomRatio:1/30,width:150,height:150,position:"bottom-left"},f=class extends n{constructor(t,e){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(!t.isGlobeView)throw new Error("'Minimap' plugin only supports 'GlobeView'. Therefore, the 'view' parameter must be a 'GlobeView'.");if(!e.isColorLayer)throw new Error("'layer' parameter form 'Minimap' constructor should be a 'ColorLayer'.");if(super(t,o,g),this.minScale=o.minScale||g.minScale,this.maxScale=o.maxScale||g.maxScale,this.zoomRatio=o.zoomRatio||g.zoomRatio,this.domElement.id="widgets-minimap",o.cursor){const t=document.createElement("div");t.id="cursor-wrapper",this.domElement.appendChild(t),"string"==typeof o.cursor?t.innerHTML=o.cursor:o.cursor instanceof HTMLElement&&t.appendChild(o.cursor)}this.view=new p.A(this.domElement,e.source.extent,{camera:{type:u.d.ORTHOGRAPHIC},placement:e.source.extent,noControls:!0,maxSubdivisionLevel:t.tileLayer.maxSubdivisionLevel,disableFocusOnStart:!0}),this.view.addLayer(e),this.domElement.addEventListener("pointerdown",(t=>{t.preventDefault()}));const i=this.view.getScale(o.pitch),n=this.view.camera3D.zoom*this.maxScale/i,s=this.view.camera3D.zoom*this.minScale/i,a=new m.A(t.referenceCrs),l=new m.A(this.view.referenceCrs),r=t.controls.getCameraTargetPosition();t.addFrameRequester(h.n7.AFTER_RENDER,(()=>{const e=t.camera3D.position.distanceTo(r),i=t.getScaleFromDistance(o.pitch,e);this.view.camera3D.zoom=this.zoomRatio*s*i/this.minScale,this.view.camera3D.zoom=Math.min(Math.max(this.view.camera3D.zoom,n),s),this.view.camera3D.updateProjectionMatrix(),a.setFromVector3(t.controls.getCameraTargetPosition()),a.as(this.view.referenceCrs,l),this.view.camera3D.position.x=l.x,this.view.camera3D.position.y=l.y,this.view.camera3D.updateMatrixWorld(!0),this.view.notifyChange(this.view.camera3D)}))}};var w=o(98211),v=o(86397),E=o(72682);const b={width:200,height:30,position:"bottom-left"},y=class extends n{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(t,e,b),this.domElement.id="widgets-scale",this.view=t,this.domElement.innerHTML="Scale",this.width=e.width||b.width,this.view.isGlobeView?(this.view.addEventListener(v.S.GLOBE_INITIALIZED,(()=>{this.update()})),this.view.controls.addEventListener(w.W.RANGE_CHANGED,(()=>{this.update()}))):this.view.isPlanarView?(this.view.addEventListener(i.G.INITIALIZED,(()=>{this.update()})),this.view.addEventListener(E.w7.MOVED,(()=>{this.update()}))):console.warn("The 'view' linked to scale widget is neither a 'GlobeView' nor a 'PlanarView'. The scale wont automatically update. You can implement its update automation using 'Scale.update' method.")}addEventListeners(){}update(){let t=Math.round(this.view.getPixelsToMeters(this.width));const e=10**(t.toString().length-1);t=Math.round(t/e)*e;const o=this.view.getMetersToPixels(t);let i="m";t>=1e3&&(t/=1e3,i="km"),this.domElement.innerHTML=`${t} ${i}`,this.domElement.style.width=`${o}px`}};var C=o(7794);const x={width:300,height:38,position:"top",maxSuggestionNumber:10,fontSize:16,placeholder:"Search location"};function L(t,e){return t?(D(t),e>=t.length?e=0:e<0&&(e=t.length-1),t[e]?.classList.add("active"),e):e}function D(t){for(let e=0;e<t.length;e++)t[e].classList.remove("active")}function S(t){for(;t.children.length>1;)t.removeChild(t.lastChild)}const T=class extends n{#n;constructor(t,e){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(super(t,o,x),!e||!e.url||!e.parser||"function"!=typeof e.parser)throw new Error("'geocodingOptions' parameter for 'Searchbar' constructor is not a valid option. Please refer to the documentation.");this.#n=e.onSelected??(()=>{}),this.domElement.id="widgets-searchbar",this.domElement.style.height="auto";const i=document.createElement("form");i.setAttribute("autocomplete","off"),i.id="searchbar-autocompletion-form",this.domElement.appendChild(i);const n=document.createElement("input");let s;n.setAttribute("type","text"),n.setAttribute("name","mySearch"),n.setAttribute("placeholder",o.placeholder||x.placeholder),n.style.height=`${o.height||o.size||x.height}px`,n.style.fontSize=`${o.fontSize||x.fontSize}px`,i.appendChild(n),n.addEventListener("input",(()=>{const t=n.value;if(S(i),s=-1,!t)return!1;e.url.searchParams.set("text",t),C.A.json(e.url).then((a=>{const l=e.parser(a);let r=0;l.forEach(((e,a)=>{if(r===Math.min(l.size,o.maxSuggestionNumber||x.maxSuggestionNumber))return;const d=r;r++;const c=a.toUpperCase().indexOf(t.toUpperCase());if(c>-1){const l=document.createElement("div");l.style.minHeight=n.style.height,l.style.fontSize=`${o.fontSize||x.fontSize}px`;const r=a.slice(0,c),m=a.slice(c,c+t.length),h=a.slice(c+t.length,a.length);l.innerHTML=`<p>${r}<strong>${m}</strong>${h}</p>`,l.setAttribute("location",a),i.appendChild(l),l.addEventListener("mouseover",(()=>{D(i.children),s=d,l.classList.add("active")})),l.addEventListener("click",(()=>{this.#n(e),n.value=l.getAttribute("location"),S(i)}))}}))}))}));const a=(o.position||x.position).includes("top")?1:-1;n.addEventListener("keydown",(e=>{e.stopPropagation();const o=i.getElementsByTagName("div");switch(e.code){case"Escape":S(i),n.value="",t.domElement.focus();break;case"ArrowDown":e.preventDefault(),s=L(o,s+a);break;case"ArrowUp":e.preventDefault(),s=L(o,s-a);break;case"Enter":e.preventDefault(),o[Math.max(s,0)]&&(o[Math.max(s,0)].click(),t.domElement.focus())}})),n.addEventListener("focus",(()=>{i.classList.add("focus")})),n.addEventListener("blur",(()=>{i.classList.remove("focus"),D(i.children)})),i.addEventListener("mouseleave",(()=>{D(i.children),s=-1}))}};var _=o(48306),M=o(14333);const z={width:200,position:"top-right"};class A extends n{constructor(t,e){super(t,e,z),this.domElement.onclick=t=>t.stopImmediatePropagation();const o=document.createElement("select");this.domElement.appendChild(o);const i=new Map,n=()=>{for(const[t,e]of i)e.hidden=t!==o.selectedOptions[0]};o.onchange=n,t.getLayers().filter((t=>!0===t.isC3DTilesLayer)).forEach((e=>{const n=document.createElement("option");n.innerText=e.name,o.add(n);const s=document.createElement("div");this.domElement.appendChild(s),i.set(n,s),e.addEventListener(M.s.ON_TILE_CONTENT_LOADED,(()=>{for(;s.firstChild;)s.firstChild.remove();const o=new Map;for(const[,t]of e.tilesC3DTileFeatures)for(const[,e]of t)for(const t in e.getInfo().batchTable){o.has(t)||o.set(t,[]);const i=e.getInfo().batchTable[t];o.get(t).includes(i)||o.get(t).push(i)}const i=new Map,n=new Map,a=(o,a,l)=>{const r=document.createElement("input");r.setAttribute("type","color"),s.appendChild(r),r.onchange=()=>{const n=o();if(!l.includes(n))return;const s=r.value;i.set(n,(t=>t.getInfo().batchTable[a]==n?s:null)),e.updateStyle(),t.notifyChange()};const d=document.createElement("input");return d.setAttribute("type","range"),d.min=0,d.max=1,d.step=.1,d.value=1,s.appendChild(d),d.onchange=()=>{const i=o();if(!l.includes(i))return;const s=d.value;n.set(i,(t=>t.getInfo().batchTable[a]==i?s:null)),e.updateStyle(),t.notifyChange()},{inputColor:r,opacityElement:d}},l=(t,e)=>{const o=document.createElement("label");o.innerText=t,s.appendChild(o);const i=document.createElement("select");s.appendChild(i),e.forEach((t=>{const e=document.createElement("option");e.value=t,e.text=t,i.add(e)})),a((()=>i.selectedOptions[0].value),t,e)},r=(o,l)=>{const r=document.createElement("label");r.innerText=o,s.appendChild(r);const d=document.createElement("input");d.setAttribute("type","text"),s.appendChild(d);const{inputColor:c,opacityElement:m}=a((()=>d.value),o,l);d.onchange=()=>{if(!l.includes(d.value))return;const s=c.value,a=d.value;i.set(a,(t=>t.getInfo().batchTable[o]==a?s:null));const r=m.value;n.set(a,(t=>t.getInfo().batchTable[o]==a?r:null)),e.updateStyle(),t.notifyChange()}};for(const[t,e]of o)e.length<A.MAX_SELECT_VALUE?l(t,e):r(t,e);e.style=new _.Ay({fill:{color:t=>{let e=null;for(const[,o]of i)e=o(t)||e;return e},opacity:t=>{let e=1;for(const[,o]of n)e=o(t)||e;return e}}})}))})),n()}static get MAX_SELECT_VALUE(){return 10}}const I=A}},t=>t(t.s=12587)])));
2
2
  //# sourceMappingURL=itowns_widgets.js.map
@@ -0,0 +1,150 @@
1
+ <html>
2
+ <head>
3
+ <title>Itowns - 3D Tiles loader</title>
4
+
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+
8
+ <link rel="stylesheet" type="text/css" href="css/example.css">
9
+ <link rel="stylesheet" type="text/css" href="css/LoadingScreen.css">
10
+
11
+ <style type="text/css">
12
+ #description {
13
+ z-index: 2;
14
+ right: 10px;
15
+ }
16
+ </style>
17
+
18
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
19
+ </head>
20
+ <body>
21
+ <div id="viewerDiv"></div>
22
+ <div id="description">Specify the URL of a tileset to load:
23
+ <input type="text" id="url" />
24
+ <button onclick="setURL(document.getElementById('url').value)">
25
+ Load
26
+ </button>
27
+ <hr />
28
+ <p><b>Feature Information:</b></p>
29
+ <div id="featureInfo"></div>
30
+ </div>
31
+
32
+ <script src="js/GUI/GuiTools.js"></script>
33
+ <script src="../dist/itowns.js"></script>
34
+ <script src="js/GUI/LoadingScreen.js"></script>
35
+ <script src="../dist/debug.js"></script>
36
+
37
+ <script type="importmap">
38
+ {
39
+ "imports": {
40
+ "three": "https://cdn.jsdelivr.net/npm/three@0.165.0/build/three.module.js",
41
+ "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.165.0/examples/jsm/"
42
+ }
43
+ }
44
+ </script>
45
+
46
+ <script type="module">
47
+ import { AmbientLight } from 'three';
48
+ import {
49
+ zoomToLayer,
50
+ fillHTMLWithPickingInfo,
51
+ } from './jsm/OGC3DTilesHelper.js';
52
+
53
+ const {
54
+ TMSSource, WMTSSource, OGC3DTilesSource,
55
+ ColorLayer, ElevationLayer, OGC3DTilesLayer,
56
+ GlobeView, Coordinates, Fetcher,
57
+ } = itowns;
58
+
59
+ const uri = new URL(location);
60
+ const state = {
61
+ // URL to tileset JSON
62
+ tileset: uri.searchParams.get('tileset'),
63
+ // Cesium ION /
64
+ assetId: uri.searchParams.get('assetId'),
65
+ };
66
+
67
+ function setURL(url) {
68
+ if (!url) return;
69
+
70
+ uri.searchParams.set('tileset', url);
71
+ history.pushState(null, '', `?${uri.searchParams.toString()}`);
72
+
73
+ location.reload();
74
+ }
75
+
76
+ // ---- CREATE A GlobeView FOR SUPPORTING DATA VISUALIZATION ----
77
+
78
+ // Define camera initial position
79
+ const placement = {
80
+ coord: new Coordinates('EPSG:4326', 2.351323, 48.856712),
81
+ range: 12500000,
82
+ };
83
+
84
+ // `viewerDiv` will contain iTowns' rendering area (`<canvas>`)
85
+ const viewerDiv = document.getElementById('viewerDiv');
86
+
87
+ // Create a GlobeView
88
+ const view = new GlobeView(viewerDiv, placement, {});
89
+
90
+ // Add ambient light to globally illuminates all objects
91
+ const light = new AmbientLight(0x404040, 15);
92
+ view.scene.add(light);
93
+
94
+ // Setup loading screen
95
+ setupLoadingScreen(viewerDiv, view);
96
+
97
+ // Setup debug menu
98
+ const menuGlobe = new GuiTools('menuDiv', view, 300);
99
+ debug.createTileDebugUI(menuGlobe.gui, view, view.tileLayer);
100
+
101
+
102
+ // ---- ADD A BASEMAP ----
103
+
104
+ // Add one imagery layer to the scene. This layer's properties are
105
+ // defined in a json file, but it cou ld be defined as a plain js
106
+ // object. See `Layer` documentation for more info.
107
+ Fetcher.json('./layers/JSONLayers/OPENSM.json').then((config) => {
108
+ const layer = new ColorLayer('Ortho', {
109
+ ...config,
110
+ source: new TMSSource(config.source),
111
+ });
112
+ view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe));
113
+ });
114
+
115
+ // ---- ADD 3D TILES TILESET ----
116
+
117
+ // Enable various compression support for 3D Tiles tileset:
118
+ // - `KHR_draco_mesh_compression` mesh compression extension
119
+ // - `KHR_texture_basisu` texture compresion extension
120
+ itowns.enableDracoLoader('./libs/draco/');
121
+ itowns.enableKtx2Loader('./lib/basis/', view.renderer);
122
+
123
+ if (state.tileset) {
124
+ const source = new OGC3DTilesSource({ url: state.tileset });
125
+ const layer = new OGC3DTilesLayer('3DTiles', {
126
+ source,
127
+ });
128
+
129
+ // Add an event for picking the 3D Tiles layer and displaying
130
+ // information about the picked feature in an html div
131
+ const pickingArgs = {
132
+ htmlDiv: document.getElementById('featureInfo'),
133
+ view,
134
+ layer,
135
+ };
136
+
137
+ // Add the layer to our view
138
+ view.addLayer(layer).then((layer) => {
139
+ zoomToLayer(view, layer);
140
+ window.addEventListener('click',
141
+ (event) => fillHTMLWithPickingInfo(event, pickingArgs), false);
142
+ });
143
+
144
+ debug.createOGC3DTilesDebugUI(menuGlobe.gui, view, layer);
145
+ }
146
+
147
+ window.setURL = setURL;
148
+ </script>
149
+ </body>
150
+ </html>
@@ -22,6 +22,10 @@
22
22
  "3dtiles_pointcloud": "Pointcloud classification"
23
23
  },
24
24
 
25
+ "3D Tiles (new)": {
26
+ "3dtiles_loader": "3D Tiles tileset loader"
27
+ },
28
+
25
29
  "Pointcloud": {
26
30
  "potree_25d_map": "Potree 2.5D map",
27
31
  "potree2_25d_map": "Potree 2.5D map 2.0 format",
@@ -0,0 +1,38 @@
1
+ module.exports = {
2
+ extends: [
3
+ 'eslint-config-airbnb-base',
4
+ 'eslint-config-airbnb-base/rules/strict',
5
+ '../.eslintrc.cjs',
6
+ ],
7
+ parserOptions: {
8
+ ecmaVersion: 13,
9
+ sourceType: 'module',
10
+ ecmaFeatures: {
11
+ impliedStrict: true,
12
+ },
13
+ },
14
+ env: {
15
+ browser: true,
16
+ es6: true,
17
+ amd: true,
18
+ commonjs: true,
19
+ },
20
+ globals: {
21
+ itowns: true,
22
+ },
23
+ rules: {
24
+ 'prefer-arrow-callback': 'off',
25
+ 'object-shorthand': 'off',
26
+ 'no-param-reassign': ['error', { props: false }],
27
+ 'no-mixed-operators': ['error', { allowSamePrecedence: true }],
28
+ 'prefer-template': 'off',
29
+ 'prefer-rest-params': 'off',
30
+ 'arrow-parens': ['error', 'as-needed', { requireForBlockBody: true }],
31
+
32
+ // deactivated rules for `examples/`
33
+ 'no-console': 'off',
34
+ // TODO reactivate all the following rules
35
+ 'no-underscore-dangle': 'off',
36
+
37
+ },
38
+ };
@@ -0,0 +1,105 @@
1
+ import { MathUtils, Vector3 } from 'three';
2
+
3
+ const { Coordinates, Extent, CameraUtils } = itowns;
4
+
5
+ /**
6
+ * Function allowing picking on a given 3D tiles layer and filling an html div
7
+ * with information on the picked feature.
8
+ * @param {MouseEvent} event
9
+ * @param {Object} pickingArg
10
+ * @param {HTMLDivElement} pickingArg.htmlDiv - div element which contains the
11
+ * picked information
12
+ * @param {GlobeView} picking.view - iTowns view where the picking must be done
13
+ * @param {OGC3DTilesLayer} pickingArg.layer - the layer on which the picking
14
+ * must be done
15
+ */
16
+ export function fillHTMLWithPickingInfo(event, pickingArg) {
17
+ const { htmlDiv, view, layer } = pickingArg;
18
+
19
+ // Remove content already in html div
20
+ while (htmlDiv.firstChild) {
21
+ htmlDiv.removeChild(htmlDiv.firstChild);
22
+ }
23
+
24
+ // Get intersected objects
25
+ const intersects = view.pickObjectsAt(event, 5, layer);
26
+
27
+ // Get information from intersected objects (from the batch table and
28
+ // eventually the 3D Tiles extensions
29
+ const closestC3DTileFeature =
30
+ layer.getC3DTileFeatureFromIntersectsArray(intersects);
31
+
32
+ if (closestC3DTileFeature) {
33
+ // eslint-disable-next-line
34
+ htmlDiv.appendChild(createHTMLListFromObject(closestC3DTileFeature));
35
+ }
36
+ }
37
+
38
+ function zoomToSphere(view, tile, sphere) {
39
+ const transform = tile.cached.transform;
40
+
41
+ const center = new Vector3().fromArray(sphere).applyMatrix4(transform);
42
+ const radius = sphere[3] * transform.getMaxScaleOnAxis();
43
+
44
+ // Get the distance to sphere where the diameter cover the whole screen
45
+ // This is similar to SSE computation where sse = screen height.
46
+ const fov = view.camera3D.fov * MathUtils.DEG2RAD;
47
+ const distance = radius * Math.tan(fov * 2);
48
+
49
+ return {
50
+ coord: new Coordinates('EPSG:4978', center),
51
+ range: distance + radius,
52
+ };
53
+ }
54
+
55
+ function zoomToBox(view, tile, box) {
56
+ const radius = Math.max(
57
+ new Vector3().fromArray(box, 3).length(),
58
+ new Vector3().fromArray(box, 6).length(),
59
+ new Vector3().fromArray(box, 9).length(),
60
+ );
61
+
62
+ // Approximate zoomToBox with sphere
63
+ const sphere = [box[0], box[1], box[2], radius];
64
+ return zoomToSphere(view, tile, sphere);
65
+ }
66
+
67
+ function zoomToRegion(view, region) {
68
+ const extent = new Extent('EPSG:4326',
69
+ region[0] * MathUtils.RAD2DEG, // west
70
+ region[2] * MathUtils.RAD2DEG, // east
71
+ region[1] * MathUtils.RAD2DEG, // south
72
+ region[3] * MathUtils.RAD2DEG, // north
73
+ );
74
+
75
+ return CameraUtils.getCameraTransformOptionsFromExtent(
76
+ view,
77
+ view.camera3D,
78
+ extent,
79
+ );
80
+ }
81
+
82
+ function zoomToTile(view, tile) {
83
+ const { region, box, sphere } = tile.boundingVolume;
84
+
85
+ let cameraTransform;
86
+ if (region) {
87
+ cameraTransform = zoomToRegion(view, region);
88
+ } else if (box) {
89
+ cameraTransform = zoomToBox(view, tile, box);
90
+ } else {
91
+ cameraTransform = zoomToSphere(view, tile, sphere);
92
+ }
93
+
94
+ view.controls.lookAtCoordinate({
95
+ coord: cameraTransform.coord,
96
+ range: 1.25 * cameraTransform.range, // zoom out a little bit
97
+ tilt: 60,
98
+ });
99
+ }
100
+
101
+ export function zoomToLayer(view, layer) {
102
+ const root = layer.tilesRenderer.root;
103
+
104
+ zoomToTile(view, root);
105
+ }
@@ -145,7 +145,8 @@
145
145
  });
146
146
 
147
147
  // Load a glTF resource
148
- itowns.glTFLoader.load(
148
+ var gltfLoader = new itowns.iGLTFLoader();
149
+ gltfLoader.load(
149
150
  // resource URL
150
151
  "https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/models/lampadaire/scene.gltf",
151
152
 
package/lib/Core/View.js CHANGED
@@ -94,6 +94,9 @@ function _preprocessLayer(view, layer, parentLayer) {
94
94
  return layer;
95
95
  });
96
96
  }
97
+ if (layer.isOGC3DTilesLayer) {
98
+ layer._setup(view);
99
+ }
97
100
  return layer;
98
101
  }
99
102
  const _eventCoords = new THREE.Vector2();
@@ -54,7 +54,7 @@ function object3DHasFeature(object3d) {
54
54
  class C3DTilesLayer extends GeometryLayer {
55
55
  #fillColorMaterialsBuffer;
56
56
  /**
57
- * Constructs a new instance of 3d tiles layer.
57
+ * @deprecated Deprecated 3D Tiles layer. Use {@link OGC3DTilesLayer} instead.
58
58
  * @constructor
59
59
  * @extends GeometryLayer
60
60
  *