CINXE.COM
Blue Marble Navigator - Night Lights
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <meta name="description" content="Google-Maps-like viewer of night-time satellite imagery."> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1.0, user-scalable=no"> <meta property="og:image" content="http://blue-marble.de/night/nightLightsTeaser2022.jpg" /> <link rel="canonical" href="https://blue-marble.de/nightlights" /> <title>Blue Marble Navigator - Night Lights</title> <style type="text/css"> html, body, #map { width: 100%; height: 100%; margin: 0; padding: 0; font-family: sans-serif; } #target { width: 14em; background-color:rgba(255,255,255,0.8); margin: 10px; font-size: 18px; } #toggle_panel { color: white; font-size: 22px; margin: 10px; } #toggle_panel input { width:18px; height:18px; } #custom_attribution { position: absolute; font-size: 70%; color: #ccc; bottom: 0.1em; left: 80px; z-index: 5; } div.gm-style-mtc-bbw { flex-wrap: wrap; right: 2em; } </style> <script type="text/javascript"> /* Note: This application constructs URLs for Google Maps' tiles to facilitate the combination of the road layer with night lights. There appeared to be no alternative, but it should also not matter to Google as long as this is done in the context of the Maps API. Also see: http://code.google.com/p/gmaps-api-issues/issues/detail?id=3635 */ // Helper functions concerning coordinates and map tiles function padTileCoordinate(number, zoomlevel) { switch(Math.floor(Math.log(Math.pow(2,zoomlevel))/Math.log(10)) - Math.floor(Math.log(number == 0 ? 1 : number)/Math.log(10))) { case 4: return '0000' + number; case 3: return '000' + number; case 2: return '00' + number; case 1: return '0' + number; default: return number; } } function getParam(name) { name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]'); var regexS = '[\\?&]' + name + '=([^&#]*)'; var regex = new RegExp(regexS); var results = regex.exec(window.location.href); if (results == null) return null; else return results[1]; } function getNormalizedCoord(tile, zoom) { if(zoom != Math.round(zoom)) return null; var tileRange = 1 << zoom; if(tile.y < 0 || tile.y >= tileRange) return null; return { x: (tile.x % tileRange + tileRange) % tileRange, y: tile.y }; } // Preparations for the appearance of the map var lastLabelChoice = true; var map; var transparentLabelsType; function toggleLabels(deliberate) { document.getElementById('labels_toggle').checked ? map.overlayMapTypes.push(transparentLabelsType) : map.overlayMapTypes.clear(); if(deliberate) lastLabelChoice = document.getElementById('labels_toggle').checked; // document.getElementById('labels_toggle').checked ? map.overlayMapTypes.insertAt(0, transparentLabelsType) : map.overlayMapTypes.removeAt(0, transparentLabelsType); // map.overlayMapTypes.forEach(function(elem,number) {alert(elem + ' ' + number)}); } function LabelControl(controlDiv, map, hideLabels) { var controlInput = document.createElement('input'); controlInput.type = 'checkbox'; controlInput.checked = !hideLabels; controlInput.id = 'labels_toggle'; controlInput.addEventListener('click', function() { toggleLabels(true); }); controlDiv.appendChild(controlInput); var newlabel = document.createElement('label'); newlabel.setAttribute('for', controlInput.id); newlabel.innerHTML = 'Labels'; controlDiv.id = 'toggle_panel'; controlDiv.appendChild(newlabel); } function getNightMapFromYear(year, maxZoom, suffix) { return new google.maps.ImageMapType({ getTileUrl: function(tile, zoom) { tile = getNormalizedCoord(tile, zoom); if(!tile) return null; var resolution = String('000000'+256*Math.pow(2,zoom)).slice(-6); var yCoo = padTileCoordinate(tile.y,zoom); var xCoo = padTileCoordinate(tile.x,zoom); var subDir = resolution;// + (zoom==10 ? '/' + yCoo.toString().substring(0,2) : ''); return 'https://blue-marble.de/google/tiles_n' + year + '/' + subDir + '/' + resolution + '_' + yCoo + '_' + xCoo + '.jpg' }, tileSize: new google.maps.Size(256, 256), maxZoom: maxZoom, name: /*'馃寵 ' +*/ year + suffix, alt: 'Night-time imagery for ' + year }) } function initialize() { transparentLabelsType = new google.maps.ImageMapType({ getTileUrl: function(tile, zoom) { tile = getNormalizedCoord(tile, zoom); if(!tile) return null; return 'https://mt0.google.com/vt/v=apt.116&hl=se&x=' + tile.x + '&y=' + tile.y + '&z=' + zoom + '&s=G&lyrs=h'; }, tileSize: new google.maps.Size(256, 256), isPng: false, maxZoom: 20, name: 'Transparent labels' }); var maxZoom = 11; var paramLL = getParam('ll') || getParam('c'); var hideMarker = getParam('c'); var hideLabels = getParam('h') !== null; var viewOptions = getParam('vo') !== null ? getParam('vo').split(',') : null; lastLabelChoice = !hideLabels; var latlon; try { latlon = paramLL.split(','); } catch {} var zoomLevel = 5; var setMarker = false; if(paramLL === null || isNaN(latlon[0]) || isNaN(latlon[1])) { var lat = 50.9; var lon = 7.6; } else { var lat = latlon[0]; var lon = latlon[1]; zoomLevel = 7; setMarker = (hideMarker === null); } let allMapTypes = [ google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.SATELLITE, 'night12', 'night15', 'night17', 'night19', 'night21', 'night22', 'night23' ]; let mapTypes = []; if (viewOptions !== null) { for (let viewOption of viewOptions) { switch (viewOption) { case 'map': mapTypes.push(google.maps.MapTypeId.ROADMAP); break; case 'day': mapTypes.push(google.maps.MapTypeId.SATELLITE); break; default: if (allMapTypes.includes(viewOption)) { mapTypes.push(viewOption); } } } } else { mapTypes = allMapTypes; } map = new google.maps.Map(document.getElementById('map'), { backgroundColor: '#00011d', center: new google.maps.LatLng(lat, lon), zoom: zoomLevel, isFractionalZoomEnabled: false, mapTypeControlOptions: { mapTypeIds: mapTypes, // style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, }, mapTypeControl: true, scaleControl: true, zoomControl: true, fullscreenControl: true, disableDefaultUI: true, streetViewControl: false, overviewMapControl: true, overviewMapControlOptions: { opened: true } }); map.mapTypes.set('night23', getNightMapFromYear('2023', maxZoom, '')); // third parameter: month extension like '-03' map.mapTypes.set('night22', getNightMapFromYear('2022', maxZoom, '')); map.mapTypes.set('night21', getNightMapFromYear('2021', maxZoom, '')); map.mapTypes.set('night19', getNightMapFromYear('2019', maxZoom, '')); map.mapTypes.set('night17', getNightMapFromYear('2017', maxZoom, '')); map.mapTypes.set('night15', getNightMapFromYear('2015', maxZoom, '')); map.mapTypes.set('night12', getNightMapFromYear('2012', maxZoom, '')); let defaultViewOption = 'night23'; map.setMapTypeId(defaultViewOption); if (viewOptions !== null && !viewOptions.includes(defaultViewOption) && allMapTypes.includes(viewOptions[viewOptions.length - 1])) { map.setMapTypeId(viewOptions[viewOptions.length - 1]); } if (!hideLabels) map.overlayMapTypes.insertAt(0, transparentLabelsType); // Add label controls var labelControlDiv = document.createElement('div'); LabelControl(labelControlDiv, map, hideLabels); map.controls[google.maps.ControlPosition.LEFT_TOP].push(labelControlDiv); // Initial Marker if(setMarker) var marker = new google.maps.Marker({ position: new google.maps.LatLng(lat, lon), map: map }); // Enable switching of map modes google.maps.event.addListener(map, 'maptypeid_changed', function() { switch(map.getMapTypeId()) { case google.maps.MapTypeId.ROADMAP: document.getElementById('custom_attribution').style.display = 'none'; document.getElementById('labels_toggle').checked = false; toggleLabels(); break; case google.maps.MapTypeId.SATELLITE: document.getElementById('custom_attribution').style.display = 'none'; if(document.getElementById('labels_toggle').checked != lastLabelChoice) { document.getElementById('labels_toggle').checked = !document.getElementById('labels_toggle').checked; toggleLabels(); } break; default: document.getElementById('custom_attribution').style.display = '';//visibility='visible'; if(document.getElementById('labels_toggle').checked != lastLabelChoice) { document.getElementById('labels_toggle').checked = !document.getElementById('labels_toggle').checked; toggleLabels(); } break; } }); // :: END initialize() } </script> </head> <body> <div id="custom_attribution">Night-lights imagery by Earth Observation Group, Colorado School of Mines | <a target="_blank" style="color:lightgrey" href="https://sites.google.com/view/urs-enke-de/policy">Privacy Policy</a> </div> <div id="map"></div> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCS9X7nawCyIjfPR_f95iSdtXdgwdUrheA&callback=initialize&v=weekly" defer ></script> </body> </html>