import Globe from 'globe.gl'; import { orphanages } from './data.js'; const globeEl = document.getElementById('globe'); const panelEl = document.getElementById('panel'); const resetBtn = document.getElementById('reset-view'); const hintEl = document.getElementById('hint'); const countryListEl = document.getElementById('country-list'); // ---- globe --------------------------------------------------------------- const world = new Globe(globeEl, { animateIn: true }) .backgroundColor('rgba(0,0,0,0)') .showAtmosphere(true) .atmosphereColor('#4ea8de') .atmosphereAltitude(0.18) .globeImageUrl('https://unpkg.com/three-globe/example/img/earth-night.jpg') .bumpImageUrl('https://unpkg.com/three-globe/example/img/earth-topology.png') .pointsData(orphanages) .pointLat(d => d.lat) .pointLng(d => d.lng) .pointAltitude(0.012) .pointRadius(0.55) .pointColor(d => '#d6a05c') .pointLabel(d => `
${d.city} · ${d.country}
${d.name}
~${d.children} children · founded ${d.founded}
`) .onPointClick(d => selectOrphanage(d)) .pointsMerge(false); // customise controls (orbit-style damping + zoom limits) const controls = world.controls(); controls.autoRotate = false; controls.enableDamping = true; controls.dampingFactor = 0.08; controls.rotateSpeed = 0.6; controls.zoomSpeed = 0.8; controls.minDistance = 180; controls.maxDistance = 700; // sizing function resize() { const w = globeEl.clientWidth; const h = globeEl.clientHeight; world.width(w).height(h); } resize(); window.addEventListener('resize', resize); // default view (a nice angle that shows all 10) world.pointOfView({ lat: 24, lng: 38, altitude: 2.4 }, 0); resetBtn.addEventListener('click', () => { world.pointOfView({ lat: 24, lng: 38, altitude: 2.4 }, 900); renderEmpty(); }); // ---- panel rendering ------------------------------------------------------ function renderEmpty() { panelEl.innerHTML = `
🌍

Pick a marker on the globe

You'll see the orphanage's name, the city and country, a short biography, photos, and roughly how many children live there.

`; fillCountryList(); } function fillCountryList() { const ul = document.getElementById('country-list'); if (!ul) return; ul.innerHTML = orphanages .map( (o, i) => `
  • ${i + 1}. ${o.name}${o.children}
  • ` ) .join(''); } function selectOrphanage(o) { // fly to the marker world.pointOfView({ lat: o.lat, lng: o.lng, altitude: 1.6 }, 900); panelEl.innerHTML = `
    ${o.city}

    ${o.name}

    ${o.country}
    ${o.children}
    Children
    City
    ${o.city}
    Country
    ${o.country}
    Founded
    ${o.founded}
    Community
    ${o.religion}

    ${o.bio}

    ${o.photos .map( (url, i) => `
    ${o.name} photo ${i + 1} Photo ${i + 1} · click to zoom
    ` ) .join('')}
    `; // photo lightbox panelEl.querySelectorAll('.photo').forEach(el => { el.addEventListener('click', () => openLightbox(el.dataset.url)); }); if (hintEl) hintEl.textContent = `Viewing · ${o.name}`; } function openLightbox(url) { const lb = document.createElement('div'); lb.className = 'lightbox open'; lb.innerHTML = `Enlarged photo`; lb.addEventListener('click', () => lb.remove()); document.body.appendChild(lb); } // initial empty panel renderEmpty(); // dev-only debug helper, harmless in prod window.__select = id => { const o = orphanages.find(x => x.id === id); if (o) selectOrphanage(o); };