import { countriesData, getColorByPenetration, getRegionColor } from './data/countries-data.js'; import { citiesData, getCityRadius, getCityColor, getConnections } from './data/cities-data.js'; // Mapbox access token mapboxgl.accessToken = 'pk.eyJ1IjoibGludXhpc2Nvb2wiLCJhIjoiY2w3ajM1MnliMDV4NDNvb2J5c3V5dzRxZyJ9.wJukH5hVSiO74GM_VSJR3Q'; // Initialize map with globe projection const map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/dark-v11', projection: 'globe', center: [20, 20], zoom: 1.5 }); // Layer state management const layerState = { countries: true, cities: true, connections: true, labels: true }; // Add atmosphere styling map.on('style.load', () => { map.setFog({ color: 'rgb(186, 210, 235)', 'high-color': 'rgb(36, 92, 223)', 'horizon-blend': 0.02, 'space-color': 'rgb(11, 11, 25)', 'star-intensity': 0.6 }); }); // Load and display data map.on('load', () => { // Add country data source map.addSource('countries', { type: 'geojson', data: countriesData }); // Add cities data source map.addSource('cities', { type: 'geojson', data: citiesData }); // Add connections data source const connections = getConnections(); map.addSource('connections', { type: 'geojson', data: connections }); // Layer 1: Country fill layer (choropleth) - Internet penetration map.addLayer({ id: 'country-fills', type: 'circle', source: 'countries', paint: { 'circle-radius': [ 'interpolate', ['linear'], ['zoom'], 1, ['/', ['get', 'population'], 2000000], 5, ['/', ['get', 'population'], 500000] ], 'circle-color': [ 'interpolate', ['linear'], ['get', 'internetPenetration'], 0, '#cc0000', 30, '#ff3300', 40, '#ff6600', 50, '#ff9900', 60, '#ffcc00', 70, '#33cc33', 80, '#00b300', 90, '#004d00' ], 'circle-opacity': 0.7, 'circle-stroke-width': 1, 'circle-stroke-color': '#ffffff', 'circle-stroke-opacity': 0.3 } }); // Layer 2: Tech hub circles - sized by importance map.addLayer({ id: 'tech-hubs', type: 'circle', source: 'cities', paint: { 'circle-radius': [ 'interpolate', ['linear'], ['get', 'importance'], 45, 4, 60, 6, 75, 9, 90, 13, 100, 18 ], 'circle-color': [ 'match', ['get', 'type'], 'Internet Exchange', '#ff6b6b', 'Tech Hub', '#4ecdc4', '#95e1d3' ], 'circle-opacity': 0.85, 'circle-stroke-width': 2, 'circle-stroke-color': '#ffffff', 'circle-blur': 0.2 } }); // Layer 3: Connection lines between major hubs map.addLayer({ id: 'hub-connections', type: 'line', source: 'connections', layout: { 'line-join': 'round', 'line-cap': 'round' }, paint: { 'line-color': '#00d4ff', 'line-width': [ 'interpolate', ['linear'], ['get', 'strength'], 400, 0.5, 600, 1, 800, 1.5, 1000, 2 ], 'line-opacity': 0.4, 'line-gradient': [ 'interpolate', ['linear'], ['line-progress'], 0, '#00d4ff', 0.5, '#00ffaa', 1, '#00d4ff' ] } }); // Layer 4: City labels for top tech hubs map.addLayer({ id: 'city-labels', type: 'symbol', source: 'cities', filter: ['>=', ['get', 'importance'], 75], layout: { 'text-field': ['get', 'city'], 'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'], 'text-size': [ 'interpolate', ['linear'], ['get', 'importance'], 75, 10, 90, 12, 100, 14 ], 'text-offset': [0, 1.5], 'text-anchor': 'top' }, paint: { 'text-color': '#ffffff', 'text-halo-color': '#000000', 'text-halo-width': 1.5 } }); // Add interactivity setupInteractivity(); // Initialize UI controls setupUIControls(); // Add legend createLegend(); // Add info panel createInfoPanel(); // Rotate globe let userInteracting = false; const spinGlobe = () => { if (!userInteracting) { const center = map.getCenter(); center.lng += 0.05; map.easeTo({ center, duration: 1000, easing: t => t }); } }; map.on('mousedown', () => { userInteracting = true; }); map.on('mouseup', () => { userInteracting = false; }); map.on('dragend', () => { userInteracting = false; }); map.on('pitchend', () => { userInteracting = false; }); map.on('rotateend', () => { userInteracting = false; }); setInterval(spinGlobe, 1000); }); // Setup interactivity function setupInteractivity() { // Change cursor on hover map.on('mouseenter', 'country-fills', () => { map.getCanvas().style.cursor = 'pointer'; }); map.on('mouseleave', 'country-fills', () => { map.getCanvas().style.cursor = ''; }); map.on('mouseenter', 'tech-hubs', () => { map.getCanvas().style.cursor = 'pointer'; }); map.on('mouseleave', 'tech-hubs', () => { map.getCanvas().style.cursor = ''; }); // Click on countries map.on('click', 'country-fills', (e) => { const properties = e.features[0].properties; new mapboxgl.Popup() .setLngLat(e.lngLat) .setHTML(`

${properties.name}

Internet Penetration: ${properties.internetPenetration}%

Digital Index: ${properties.digitalIndex}

Region: ${properties.region}

Population: ${(properties.population / 1000000).toFixed(1)}M

`) .addTo(map); }); // Click on cities map.on('click', 'tech-hubs', (e) => { const properties = e.features[0].properties; new mapboxgl.Popup() .setLngLat(e.lngLat) .setHTML(`

${properties.city}

Type: ${properties.type}

Importance Score: ${properties.importance}

Connections: ${properties.connections}

Data Centers: ${properties.datacenters}

`) .addTo(map); }); } // Setup UI controls function setupUIControls() { // Layer toggles document.getElementById('toggle-countries').addEventListener('change', (e) => { layerState.countries = e.target.checked; map.setLayoutProperty('country-fills', 'visibility', e.target.checked ? 'visible' : 'none'); }); document.getElementById('toggle-cities').addEventListener('change', (e) => { layerState.cities = e.target.checked; map.setLayoutProperty('tech-hubs', 'visibility', e.target.checked ? 'visible' : 'none'); }); document.getElementById('toggle-connections').addEventListener('change', (e) => { layerState.connections = e.target.checked; map.setLayoutProperty('hub-connections', 'visibility', e.target.checked ? 'visible' : 'none'); }); document.getElementById('toggle-labels').addEventListener('change', (e) => { layerState.labels = e.target.checked; map.setLayoutProperty('city-labels', 'visibility', e.target.checked ? 'visible' : 'none'); }); // Region filter document.getElementById('region-filter').addEventListener('change', (e) => { const region = e.target.value; if (region === 'all') { map.setFilter('country-fills', null); map.setFilter('tech-hubs', null); } else { map.setFilter('country-fills', ['==', ['get', 'region'], region]); // For cities, we need to join with country data to filter by region const regionCountries = countriesData.features .filter(f => f.properties.region === region) .map(f => f.properties.country); map.setFilter('tech-hubs', ['in', ['get', 'country'], ['literal', regionCountries]]); } }); // Metric filter document.getElementById('metric-filter').addEventListener('change', (e) => { const metric = e.target.value; if (metric === 'penetration') { map.setPaintProperty('country-fills', 'circle-color', [ 'interpolate', ['linear'], ['get', 'internetPenetration'], 0, '#cc0000', 30, '#ff3300', 40, '#ff6600', 50, '#ff9900', 60, '#ffcc00', 70, '#33cc33', 80, '#00b300', 90, '#004d00' ]); } else if (metric === 'digital-index') { map.setPaintProperty('country-fills', 'circle-color', [ 'interpolate', ['linear'], ['get', 'digitalIndex'], 0, '#1a1a1a', 25, '#4d4d4d', 50, '#808080', 75, '#b3b3b3', 100, '#e6e6e6' ]); } updateLegend(metric); }); // Opacity controls document.getElementById('country-opacity').addEventListener('input', (e) => { const opacity = parseFloat(e.target.value); map.setPaintProperty('country-fills', 'circle-opacity', opacity); document.getElementById('country-opacity-value').textContent = Math.round(opacity * 100) + '%'; }); document.getElementById('city-opacity').addEventListener('input', (e) => { const opacity = parseFloat(e.target.value); map.setPaintProperty('tech-hubs', 'circle-opacity', opacity); document.getElementById('city-opacity-value').textContent = Math.round(opacity * 100) + '%'; }); document.getElementById('connection-opacity').addEventListener('input', (e) => { const opacity = parseFloat(e.target.value); map.setPaintProperty('hub-connections', 'line-opacity', opacity); document.getElementById('connection-opacity-value').textContent = Math.round(opacity * 100) + '%'; }); } // Create legend function createLegend() { const legend = document.getElementById('legend'); legend.innerHTML = `

Internet Penetration

90-100%
80-90%
70-80%
60-70%
50-60%
40-50%
30-40%
0-30%

Tech Hubs

Tech Hub
Internet Exchange

Connections

Hub Links
`; } // Update legend based on metric function updateLegend(metric) { const legend = document.getElementById('legend'); if (metric === 'digital-index') { legend.innerHTML = `

Digital Infrastructure Index

75-100
50-75
25-50
0-25

Tech Hubs

Tech Hub
Internet Exchange

Connections

Hub Links
`; } else { createLegend(); } } // Create info panel function createInfoPanel() { const info = document.getElementById('info'); // Calculate statistics const totalCountries = countriesData.features.length; const avgPenetration = (countriesData.features.reduce((sum, f) => sum + f.properties.internetPenetration, 0) / totalCountries).toFixed(1); const totalCities = citiesData.features.length; const topHubs = citiesData.features.filter(f => f.properties.importance >= 90).length; const connections = getConnections().features.length; info.innerHTML = `

Global Statistics

Countries: ${totalCountries}
Avg. Internet Penetration: ${avgPenetration}%
Tech Hubs: ${totalCities}
Tier 1 Hubs: ${topHubs}
International Links: ${connections}
`; }