Mercurial > lbo > hg > geohub
view assets/livemap.html @ 95:ebc250ea457f
Update livemap screenshot
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Tue, 08 Dec 2020 22:05:04 +0100 |
parents | c683521147c7 |
children | ea32bfe4de7f |
line wrap: on
line source
<html> <head> <link rel="stylesheet" href="thirdparty/leaflet.css" /> <link rel="stylesheet" href="style.css" /> <title>GeoHub: LiveMap</title> </head> <body> <script src="thirdparty/leaflet.js"></script> <script src="shared.js"></script> <span id="livemapTitle">GeoHub LiveMap</span> <div> <span id="inputFields"> Client: <input type="text" value="" id="inputClient" class="field" /> Secret: <input type="text" value="" id="inputSecret" class="field" /> <input type="button" value="Go!" id="inputGoButton" onclick="buttonGoClicked()" /> </span> </div> <div id="infoFields" class="timeChanged"> <b>Last Update:</b> <span id="outputLastUpdate"> </span> <b>Download:</b> <a href="" id="gpxDownloadLink">GPX</a> <a href="" id="jsonDownloadLink">JSON</a> </div> <div id="mapid"> </div> <script> // Set up map. const initial = [50, 10]; var mapZoomed = false; var mymap = L.map('mapid').setView(initial, 5); var accessToken = 'pk.eyJ1IjoiZGVybWVzc2VyIiwiYSI6ImNraTdwZmUxZTE2OGgydW1oYTU5eW9qYm4ifQ.f9OxY_U78h6iefp-jN9-9w'; L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', { attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>', maxZoom: 18, id: 'mapbox/streets-v11', tileSize: 512, zoomOffset: -1, accessToken: accessToken, }).addTo(mymap); var url = new URL(window.location); var allMarkers = []; // Set the current location, called on every new point. Updates the marker and adds // a new point (former position). var current_marker = L.marker([0,0]).addTo(mymap); var current_circle = L.circle([0,0], {}).addTo(mymap); function setCurrentLocation(lat, lng, accuracy) { var oldCoord = current_marker.getLatLng(); current_marker.setLatLng(L.latLng(lat, lng)); // Show accuracy of current location const currentCircleProps = { color: 'aqua', fillColor: 'aqua', fillOpacity: 0.1, radius: accuracy ? accuracy : 3, }; current_circle.remove(); current_circle = L.circle([lat, lng], currentCircleProps).addTo(mymap); // Show last locations as blue points. addMarker(oldCoord.lat, oldCoord.lng, accuracy); } function addMarker(lat, lng, accuracy) { const circleProps = { color: 'blue', fillColor: 'blue', fillOpacity: 0.1, radius: accuracy ? accuracy : 3, }; var circle = L.circle([lat, lng], circleProps); circle.addTo(mymap); allMarkers.push(circle); } // Remove all points from the map (except for the "current position" marker). function clearAllMarkers() { for (var i = 0; i < allMarkers.length; i++) { allMarkers[i].remove(); } } // New points are available. Display them on the map and update the marker. function xhrcallback(xhr) { //console.log('xhrcallback called.', xhr.readyState, xhr.status); if (xhr.readyState === XMLHttpRequest.DONE && xhr.status == 200) { const response = xhr.response; //console.log("Client update for", response.client); if (response.client != getClient()) { console.log("Received outdated client update."); return; } if (response.client == getClient() && response.geo) { const features = response['geo']['features']; if (features.length == 0) { return; } const lastfeature = features[0]; console.log(`xhrcallback: ${features.length} elements received.`); // Backfill old circles. This happens when called from a // backfill() triggered request to `/last` or when a client sent // several points at once. if (features.length > 0) { for (i = 1; i < features.length; i++) { var coords = features[i]['geometry']['coordinates']; addMarker(coords[1], coords[0], features[i].properties.accuracy); } } var coords = lastfeature['geometry']['coordinates']; console.log('Received update:', coords, 'last:', response); setCurrentLocation(coords[1], coords[0], lastfeature.properties.accuracy); // 13 is a good default zoom for an updated point. mymap.setView([coords[1], coords[0]], mapZoomed ? mymap.getZoom() : 13); mapZoomed = true; updateUI(lastfeature.properties.time); } // Install next XHR. waitforupdate(); } else { return; } }; // Fetch the most recent point for this client and display them. function backfill(args) { var xhr = new XMLHttpRequest(); var client = getClient(); var secret = getSecret(); if (!client) { return; } var limit = getLimit(); var url = `../../geo/${client}/retrieve/last?secret=${secret}&limit=${limit}`; console.log('Requesting URL (backfill) ' + url); xhr.responseType = 'json'; xhr.open('GET', url, true); xhr.onreadystatechange = function() { xhrcallback(xhr); }; xhr.send(); } var lastXHR = null; // Ask for updates. This request will hang until timeout is reached or // an update arrives. function waitforupdate() { var xhr = new XMLHttpRequest(); var client = getClient(); var secret = getSecret(); if (!client) { return; } var secretparam = secret == null ? '' : `secret=${secret}`; var url = `../../geo/${client}/retrieve/live?${secretparam}&timeout=30`; console.log('Requesting URL ' + url); xhr.responseType = 'json'; xhr.open('GET', url, true); xhr.onreadystatechange = function() { xhrcallback(xhr) }; xhr.send(); lastXHR = xhr; } function updateUI(time) { if (time) { var timefield = document.getElementById('outputLastUpdate'); var infofields = document.getElementById('infoFields'); // This dance restarts the green "update" animation. infofields.style.animation = 'none'; infofields.offsetHeight; infofields.style.animation = null; timefield.textContent = (new Date(time)).toString().replace(/\([\w\s]+\)/,''); } } function updateLinks() { var gpxLink = document.getElementById('gpxDownloadLink'); var jsonLink = document.getElementById('jsonDownloadLink'); var client = getClient(); var secret = getSecret(); gpxLink.href = `../${client}/retrieve/gpx?secret=${secret}`; jsonLink.href = `../${client}/retrieve/json?secret=${secret}`; } // "Go!" was clicked - clear markers and fetch data for new source. function buttonGoClicked() { clearAllMarkers(); if (lastXHR) { lastXHR.abort(); } updateURL(getClient(), getSecret()); updateLinks(); // Accelerate display. backfill(); } updateLinks(); // Once data is backfilled, we wait for the update. backfill(); </script> </body> </html>