site

my website
git clone https://xfnw.ttm.sh/git/site.git
Log | Files | Refs

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 &copy; RainViewer, Map data &copy; 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