1import { createGlobeScene } from './globe-scene.js'; 2 3const TAG_NAME = 'loopdive-globe'; 4 5const template = document.createElement('template'); 6template.innerHTML = ` 7 <style> 8 :host { 9 position: absolute; 10 inset: 0; 11 display: block; 12 pointer-events: none; 13 touch-action: none; 14 -webkit-touch-callout: none; 15 -webkit-user-select: none; 16 user-select: none; 17 } 18 19 .globe-host { 20 position: absolute; 21 inset: 0; 22 overflow: hidden; 23 opacity: 0; 24 pointer-events: auto; 25 overscroll-behavior: none; 26 touch-action: none; 27 -webkit-touch-callout: none; 28 -webkit-user-select: none; 29 user-select: none; 30 transition: opacity 420ms ease; 31 } 32 33 .globe-host.is-ready { 34 opacity: 1; 35 } 36 37 :host([interactive='false']) .globe-host { 38 pointer-events: none; 39 } 40 41 .globe-host canvas { 42 display: block; 43 width: 100%; 44 height: 100%; 45 touch-action: none; 46 -webkit-touch-callout: none; 47 -webkit-user-select: none; 48 user-select: none; 49 } 50 51 .globe-labels { 52 position: absolute; 53 inset: 0; 54 pointer-events: none; 55 opacity: 0; 56 transition: opacity 180ms ease; 57 } 58 59 .globe-labels.is-ready { 60 opacity: 1; 61 } 62 </style> 63 <div class="globe-host" part="host"></div> 64 <div class="globe-labels" part="labels"></div> 65`; 66 67class LoopdiveGlobeElement extends HTMLElement { 68 constructor() { 69 super(); 70 this._scene = null; 71 this._revealPrepared = false; 72 this.attachShadow({ mode: 'open' }); 73 this.shadowRoot.appendChild(template.content.cloneNode(true)); 74 this._hostNode = this.shadowRoot.querySelector('.globe-host'); 75 this._labelNode = this.shadowRoot.querySelector('.globe-labels'); 76 } 77 78 disconnectedCallback() { 79 this.destroy(); 80 } 81 82 mountScene(options) { 83 this.destroy(); 84 this._scene = createGlobeScene({ 85 ...options, 86 host: this._hostNode, 87 labelHost: this._labelNode, 88 }); 89 return this; 90 } 91 92 reveal() { 93 requestAnimationFrame(() => { 94 requestAnimationFrame(() => { 95 this._hostNode.classList.add('is-ready'); 96 this._labelNode.classList.add('is-ready'); 97 }); 98 }); 99 } 100 101 prepareReveal() { 102 this.resetReveal(); 103 this._revealPrepared = true; 104 } 105 106 resetReveal() { 107 this._revealPrepared = false; 108 this._hostNode.classList.remove('is-ready'); 109 this._labelNode.classList.remove('is-ready'); 110 } 111 112 goTo(entry) { 113 this._scene?.goTo(entry); 114 } 115 116 buildWorld(world) { 117 this._scene?.buildWorld(world); 118 } 119 120 hydrateWorldContours(world) { 121 return this._scene?.hydrateWorldContours(world) || Promise.resolve(false); 122 } 123 124 applyProps() { 125 this._scene?.applyProps(); 126 } 127 128 invalidate() { 129 this._scene?.invalidate(); 130 } 131 132 setAutoRotateEnabled(active) { 133 this._scene?.setAutoRotateEnabled(active); 134 } 135 136 setCapitalLookup(lookup) { 137 this._scene?.setCapitalLookup(lookup); 138 } 139 140 setStreetMapModeActive(active) { 141 this._scene?.setStreetMapModeActive(active); 142 } 143 144 setViewState(view) { 145 this._scene?.setViewState(view); 146 } 147 148 setGlobeOffsetX(offsetX) { 149 this._scene?.setGlobeOffsetX(offsetX); 150 } 151 152 locateUser(location) { 153 this._scene?.locateUser(location); 154 } 155 156 destroy() { 157 if (this._scene) { 158 this._scene.destroy(); 159 this._scene = null; 160 } 161 this.resetReveal(); 162 } 163} 164 165export const defineLoopdiveGlobeElement = () => { 166 if (!customElements.get(TAG_NAME)) { 167 customElements.define(TAG_NAME, LoopdiveGlobeElement); 168 } 169 return customElements.get(TAG_NAME); 170};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.