Files
recorder/docroot/views/leafletmap.html
2024-01-28 11:10:33 +00:00

143 lines
4.5 KiB
HTML

<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>OwnTracks @@@LABEL@@@</title>
<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, initial-scale=1.0">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="icon" sizes="192x192" href="../static/recorder.png">
<link rel="apple-touch-icon" href="../static/recorder.png">
<link rel="stylesheet" href="../utils/map.css">
<link rel="stylesheet" href="../static/leaflet/leaflet.css">
<script src="../static/leaflet/leaflet.js"></script>
<script type="module">
import { fetchApiData } from "../utils/network.js";
import { generatePopupHTML } from "../utils/map.js";
import { markerStyle, strokeStyle } from "../utils/map_leaflet.js";
const map = L.map('map-canvas').setView([0.0, 0.0], 1);
let lastLatLng = L.latLng(0.0, 0.0);
const osm_layer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(map);
const baseMaps = { "OpenStreetMap": osm_layer };
L.control.layers(baseMaps); // .addTo(map);
const empty_geojson = {
type: "FeatureCollection",
features: [],
};
const trackLayer = new L.GeoJSON( empty_geojson, {
style: function(feature) {
return strokeStyle;
},
coordsToLatLng: function(coords) {
return coordsToLatLng(coords);
},
});
// this defines how the data obtained from @@@LASTPOS@@@ will be rendered
const lastposLayer = new L.GeoJSON( empty_geojson , {
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, markerStyle);
},
onEachFeature: function(feature, layer) {
if (feature.geometry.type === "Point") {
const description = generatePopupHTML({
...feature.properties,
lat: feature.geometry.coordinates[1].toFixed(4),
lon: feature.geometry.coordinates[0].toFixed(4),
});
layer.bindPopup(description);
}
},
style: function(feature) {
if (feature.geometry.type === "Point") {
return {};
} else {
return strokeStyle;
}
},
coordsToLatLng: function(coords) {
return coordsToLatLng(coords);
},
});
map.addLayer(trackLayer);
map.addLayer(lastposLayer);
lastposLayer.bringToFront();
load_track();
async function load_track() {
lastLatLng = L.latLng(0.0, 0.0);
const data = await fetchApiData({ url: "@@@GEO@@@" });
trackLayer.clearLayers();
trackLayer.addData(data);
update_lastpos(false);
if (trackLayer.getBounds().isValid()) map.fitBounds(trackLayer.getBounds());
else map.openTooltip('No Data!',L.latLng(0.0,0.0));
}
// this will update the lastposLayer to fetch and show updated latest positions
async function update_lastpos(fitBounds) {
const data = await fetchApiData({ url: "@@@LASTPOS@@@" });
data.data.forEach(function(latest) {
const latLng = coordsToLatLng([latest.lon, latest.lat]);
const latest_geojson = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ latLng.lng, latLng.lat ],
},
"properties": latest,
};
lastposLayer.clearLayers();
lastposLayer.addData(latest_geojson);
if(fitBounds) {
if (lastposLayer.getBounds().isValid()) map.fitBounds(lastposLayer.getBounds());
else map.openTooltip('No Data!',L.latLng(0.0,0.0));
}
});
}
function coordsToLatLng([ lon, lat ]) {
const dist0 = Math.abs(lon - lastLatLng.lng);
const dist1 = Math.abs(lon + 360.0 - lastLatLng.lng);
const dist2 = Math.abs(lon - 360.0 - lastLatLng.lng);
if (dist0 > dist1 || dist0 > dist2) {
if (dist0 > dist1) {
lon += 360.0;
} else {
lon -= 360.0;
}
}
const latLng = L.GeoJSON.coordsToLatLng([lon, lat]);
lastLatLng = latLng;
return latLng;
}
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>