index.html (4673B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>xfnw's weather radar</title> 5 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 8 <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css"/> 9 <script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script> 10 </head> 11 <body> 12 <div style="text-align:center; position: absolute;bottom: 0px; left: 0; right: 0; height: 80px;color:white;font-family: mono,monospace,fixed-width;z-index:10000"><span id="timestamp"></span><br>Radar data © RainViewer, Map data © Carto CC BY 3.0 and OpenStreetMap</div> 13 14 <input style="position: absolute;bottom:10px;right: 10px;z-index:10000;background-color:black;font-family:mono,monospace,fixed-width;color:white;border:1px solid white" type="button" onclick="playStop();" value="Play" /> 15 16 17 <div id="mapid" style="position: absolute; top: 0px; left: 0; bottom: 0; right: 0;background-color: black"></div> 18 19 <script> 20 21 var map = L.map('mapid').setView([39.132190775931036, -77.19543457031251], 9); 22 /* 23 L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { 24 attributions: 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors' 25 }).addTo(map); 26 */ 27 28 29 L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png', { 30 attributions: 'Map data © Carto CC BY 3.0 and <a href="https://openstreetmap.org">OpenStreetMap</a> contributors' 31 }).addTo(map); 32 33 /** 34 * RainViewer radar animation part 35 * @type {number[]} 36 */ 37 var timestamps = []; 38 var radarLayers = []; 39 40 var animationPosition = 0; 41 var animationTimer = false; 42 43 /** 44 * Load actual radar animation frames timestamps from RainViewer API 45 */ 46 var apiRequest = new XMLHttpRequest(); 47 apiRequest.open("GET", "https://api.rainviewer.com/public/maps.json", true); 48 apiRequest.onload = function(e) { 49 50 // save available timestamps and show the latest frame: "-1" means "timestamp.lenght - 1" 51 timestamps = JSON.parse(apiRequest.response); 52 showFrame(-1); 53 }; 54 apiRequest.send(); 55 56 /** 57 * Animation functions 58 * @param ts 59 */ 60 function addLayer(ts) { 61 if (!radarLayers[ts]) { 62 radarLayers[ts] = new L.TileLayer('https://tilecache.rainviewer.com/v2/radar/' + ts + '/256/{z}/{x}/{y}/2/1_1.png', { 63 tileSize: 256, 64 opacity: 0.01, 65 zIndex: ts 66 }); 67 } 68 if (!map.hasLayer(radarLayers[ts])) { 69 map.addLayer(radarLayers[ts]); 70 } 71 } 72 73 /** 74 * Display particular frame of animation for the @position 75 * If preloadOnly parameter is set to true, the frame layer only adds for the tiles preloading purpose 76 * @param position 77 * @param preloadOnly 78 */ 79 function changeRadarPosition(position, preloadOnly) { 80 while (position >= timestamps.length) { 81 position -= timestamps.length; 82 } 83 while (position < 0) { 84 position += timestamps.length; 85 } 86 87 var currentTimestamp = timestamps[animationPosition]; 88 var nextTimestamp = timestamps[position]; 89 90 addLayer(nextTimestamp); 91 92 if (preloadOnly) { 93 return; 94 } 95 96 animationPosition = position; 97 98 if (radarLayers[currentTimestamp]) { 99 radarLayers[currentTimestamp].setOpacity(0); 100 } 101 radarLayers[nextTimestamp].setOpacity(0.3); 102 103 document.getElementById("timestamp").innerHTML = (new Date(nextTimestamp * 1000)).toString(); 104 } 105 106 /** 107 * Check avialability and show particular frame position from the timestamps list 108 */ 109 function showFrame(nextPosition) { 110 var preloadingDirection = nextPosition - animationPosition > 0 ? 1 : -1; 111 112 changeRadarPosition(nextPosition); 113 114 // preload next next frame (typically, +1 frame) 115 // if don't do that, the animation will be blinking at the first loop 116 changeRadarPosition(nextPosition + preloadingDirection, true); 117 } 118 119 /** 120 * Stop the animation 121 * Check if the animation timeout is set and clear it. 122 */ 123 function stop() { 124 if (animationTimer) { 125 clearTimeout(animationTimer); 126 animationTimer = false; 127 return true; 128 } 129 return false; 130 } 131 132 function play() { 133 showFrame(animationPosition + 1); 134 135 // Main animation driver. Run this function every 500 ms 136 animationTimer = setTimeout(play, 500); 137 } 138 139 function playStop() { 140 if (!stop()) { 141 play(); 142 } 143 } 144 </script> 145 146 </body> 147 </html> 148 149