127 lines
4 KiB
HTML
127 lines
4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="{{ DEFAULT_LANG }}">
|
|
<head>
|
|
<base target="_top">
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
<title>{{ page.name }}</title>
|
|
|
|
<link rel="shortcut icon" type="image/x-icon" href="/images/favicon.ico" />
|
|
<link rel="stylesheet" href="{{ SITEURL }}/theme/local.css">
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin=""/>
|
|
<style>
|
|
html, body { height: 100%; margin: 0; padding: 0; }
|
|
h1 {
|
|
font-size: 4em;
|
|
margin: 0;
|
|
}
|
|
</style>
|
|
<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
|
|
|
|
</head>
|
|
<body>
|
|
<div id='map'></div>
|
|
<script>
|
|
BITS = [16, 8, 4, 2, 1];
|
|
BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
|
|
function encodeGeoHash(latitude, longitude) {
|
|
var is_even=1;
|
|
var i=0;
|
|
var lat = []; var lon = [];
|
|
var bit=0;
|
|
var ch=0;
|
|
var precision = 10;
|
|
geohash = "";
|
|
|
|
lat[0] = -90.0; lat[1] = 90.0;
|
|
lon[0] = -180.0; lon[1] = 180.0;
|
|
|
|
while (geohash.length < precision) {
|
|
if (is_even) {
|
|
mid = (lon[0] + lon[1]) / 2;
|
|
if (longitude > mid) {
|
|
ch |= BITS[bit];
|
|
lon[0] = mid;
|
|
} else
|
|
lon[1] = mid;
|
|
} else {
|
|
mid = (lat[0] + lat[1]) / 2;
|
|
if (latitude > mid) {
|
|
ch |= BITS[bit];
|
|
lat[0] = mid;
|
|
} else
|
|
lat[1] = mid;
|
|
}
|
|
|
|
is_even = !is_even;
|
|
if (bit < 4)
|
|
bit++;
|
|
else {
|
|
geohash += BASE32[ch];
|
|
bit = 0;
|
|
ch = 0;
|
|
}
|
|
}
|
|
return geohash;
|
|
}
|
|
|
|
function copyToClipboard() {
|
|
var copyText = document.getElementById("geohash").innerText;
|
|
navigator.clipboard.writeText(copyText).then(() => {
|
|
alert("Copied " + copyText + " to clipboard");
|
|
});
|
|
}
|
|
|
|
var bluedot = L.icon({
|
|
iconUrl: '/theme/bluedot.svg',
|
|
iconSize: [18, 18],
|
|
iconAnchor: [9, 9],
|
|
popupAnchor: [0, -10]
|
|
});
|
|
|
|
const map = L.map('map').fitWorld();
|
|
|
|
const tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
maxZoom: 19,
|
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
|
}).addTo(map);
|
|
|
|
var locationMarker, locationCircle;
|
|
|
|
function onLocationFound(e) {
|
|
|
|
if (locationMarker) {
|
|
map.removeLayer(locationMarker);
|
|
map.removeLayer(locationCircle);
|
|
}
|
|
|
|
const radius = e.accuracy / 2;
|
|
locationMarker = L.marker(e.latlng, {icon: bluedot}).addTo(map);
|
|
locationCircle = L.circle(e.latlng, radius).addTo(map);
|
|
info.update(e);
|
|
}
|
|
|
|
function onLocationError(e) {
|
|
alert(e.message);
|
|
}
|
|
|
|
map.on('locationfound', onLocationFound);
|
|
map.on('locationerror', onLocationError);
|
|
map.locate({setView: true, watch: true});
|
|
|
|
var info = L.control({position: 'topright'});
|
|
|
|
info.onAdd = function (map) {
|
|
this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info"
|
|
return this._div;
|
|
};
|
|
|
|
info.update = function (e) {
|
|
this._div.innerHTML = this._div.innerHTML = '<h1 id="geohash" onclick="copyToClipboard()">' + encodeGeoHash(e.latlng.lat, e.latlng.lng) + '</h1>';
|
|
};
|
|
|
|
info.addTo(map);
|
|
</script>
|
|
</body>
|
|
</html>
|