Leaflet map working with top and second level and it performs well!

Signed-off-by: fly <merspieler@airmail.cc>
This commit is contained in:
fly 2023-10-25 12:47:56 +00:00
parent 0a8f428651
commit 18a6c45d71
2 changed files with 184 additions and 61 deletions

View file

@ -1,4 +1,5 @@
{ {
"topLevel": {
<?php <?php
include("config.php"); include("config.php");
// Returns numbers in string format as needed for file names // Returns numbers in string format as needed for file names
@ -16,6 +17,53 @@
{ {
quit(); quit();
} }
$sql = "SELECT topLevel.name AS name, status.color AS color FROM topLevel JOIN status ON topLevel.status_id = status.id";
$ret = $con->query($sql)->fetch_all(MYSQLI_ASSOC);
if ($ret != False)
{
$tiles = [];
foreach($ret as $row)
{
$tiles[$row["name"]] = $row["color"];
}
}
$first = true;
for ($i = 80; $i >= -90; $i -= 10)
{
if ($i >= 0)
{
$ns = "n";
}
else
{
$ns = "s";
}
for ($j = -180; $j < 180; $j += 10)
{
if ($first)
{
$first = false;
}
else
{
echo ",";
}
if ($j < 0)
{
$ew = "w";
}
else
{
$ew = "e";
}
$name = $ew . clipNumber($j, 3) . $ns . clipNumber($i, 2);
echo '"' . $name . '": "' . $tiles[$name] . '"';
}
}
?>
},
"secondLevel": {
<?php
$sql = "SELECT secondLevel.name AS name, status.color AS color FROM secondLevel JOIN status ON secondLevel.status_id = status.id"; $sql = "SELECT secondLevel.name AS name, status.color AS color FROM secondLevel JOIN status ON secondLevel.status_id = status.id";
$ret = $con->query($sql)->fetch_all(MYSQLI_ASSOC); $ret = $con->query($sql)->fetch_all(MYSQLI_ASSOC);
if ($ret != False) if ($ret != False)
@ -37,7 +85,6 @@
{ {
$ns = "s"; $ns = "s";
} }
$y = (abs($i - 80) / 10) * 25;
for ($j = -180; $j < 180; $j += 1) for ($j = -180; $j < 180; $j += 1)
{ {
if ($first) if ($first)
@ -57,8 +104,9 @@
$ew = "e"; $ew = "e";
} }
$name = $ew . clipNumber($j, 3) . $ns . clipNumber($i, 2); $name = $ew . clipNumber($j, 3) . $ns . clipNumber($i, 2);
echo '"' . $name . '": {"name": "' . $name . '", "color": "' . $tiles[$name] . '"}'; echo '"' . $name . '": "' . $tiles[$name] . '"';
} }
} }
?> ?>
}
} }

View file

@ -4,77 +4,152 @@
* Uses Leaflet. * Uses Leaflet.
*/ */
// feature group to hold the scenery-bucket rectangles
var top_layer = L.featureGroup();
var second_layer = L.featureGroup();
/** /**
* Create interactive map. * Create interactive map.
*/ */
function setup_map (config) { function setup_map (config) {
/** /**
* Parse a bucket name to get the lat/lon * Parse a bucket name to get the lat/lon
*/ */
function parse_bucket_name(name) { function parse_bucket_name(name) {
let lon = parseInt(name.substr(1, 3)); let lon = parseInt(name.substr(1, 3));
let lat = parseInt(name.substr(5, 2)); let lat = parseInt(name.substr(5, 2));
if (name.substr(0, 1).toLowerCase() == 'w') { if (name.substr(0, 1).toLowerCase() == 'w') {
lon *= -1; lon *= -1;
} }
if (name.substr(4, 1).toLowerCase() == 's') { if (name.substr(4, 1).toLowerCase() == 's') {
lat *= -1; lat *= -1;
} }
return [lat, lon]; return [lat, lon];
} }
/** /**
* Start a download in the user's browser * Start a download in the user's browser
*/ */
function download(tile) { function download(tile) {
var a = document.getElementById("progressinfo"); var a = document.getElementById("progressinfo");
a.setAttribute("src", "progressinfo.php?minor=" + tile); a.setAttribute("src", "progressinfo.php?minor=" + tile);
} }
function norm(num, length) {
var ret = String(Math.abs(num));
while (ret.length < length)
{
ret = '0' + ret;
}
return ret;
}
// the Leaflet map object // the Leaflet map object
let map = L.map('map').setView([45, -100], 4); let map = L.map('map').setView([0, 0], 1);
// add OpenStreetMap tiles // add OpenStreetMap tiles
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 15, maxZoom: 15,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>' attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map); }).addTo(map);
// feature group to hold the scenery-bucket rectangles // Create a rectangle for each bucket
let rectangle_layer = L.featureGroup(); for (const [bucket_name, color] of Object.entries(config.topLevel)) {
const [lat, lon] = parse_bucket_name(bucket_name);
const bounds = [[lat, lon], [lat+10, lon+10]];
const style = { color: color, weight: 1};
const rect = L.rectangle(bounds, style);
// Create a rectangle for each bucket // add the bucket name to the rect
for (const [bucket_name, props] of Object.entries(config)) { rect.bucket_name = bucket_name;
const [lat, lon] = parse_bucket_name(bucket_name);
const bounds = [[lat, lon], [lat+1, lon+1]];
const style = { color: props.color, weight: 1};
const rect = L.rectangle(bounds, style);
// add the bucket name to the rect // show the bucket name on mouseover
rect.bucket_name = bucket_name; rect.bindTooltip(bucket_name);
// show the bucket name on mouseover // add to the bucket group (for now, skip unavailable buckets)
rect.bindTooltip(bucket_name); top_layer.addLayer(rect);
}
// Download when the user clicks on an area function showLayers() {
rect.on('click', (e) => { if (map.getZoom() <= 4) {
console.log(props); if (!map.hasLayer(top_layer)) map.addLayer(top_layer);
download(props.name); if (map.hasLayer(second_layer)) map.removeLayer(second_layer);
}) }
else if (map.getZoom() > 4) {
if (!map.hasLayer(second_layer)) map.addLayer(second_layer);
if (map.hasLayer(top_layer)) map.removeLayer(top_layer);
}
}
// add to the bucket group (for now, skip unavailable buckets) function updateSecondLayer() {
rectangle_layer.addLayer(rect); if (map.getZoom() > 4) {
} second_layer.clearLayers();
bounds = map.getBounds();
i = Math.floor(bounds.getWest());
iMax = Math.ceil(bounds.getEast());
while (i < iMax)
{
j = Math.floor(bounds.getSouth());
jMax = Math.ceil(bounds.getNorth())
while (j < jMax)
{
if (j < 0)
{
var sn = "s";
}
else
{
var sn = "n";
}
if (i < 0)
{
var we = "w";
}
else
{
var we = "e";
}
const bucket_name = we + norm(i, 3) + sn + norm(j, 2);
const bounds = [[j, i], [j+1, i+1]];
const style = { color: config.secondLevel[bucket_name], weight: 1};
const rect = L.rectangle(bounds, style);
// add the bucket group to the map // add the bucket name to the rect
map.addLayer(rectangle_layer); rect.bucket_name = bucket_name;
// set the map's zoom // show the bucket name on mouseover
map.fitBounds(rectangle_layer.getBounds()); rect.bindTooltip(bucket_name);
// Download when the user clicks on an area
rect.on('click', (e) => {
console.log(bucket_name);
download(bucket_name);
})
// add to the bucket group (for now, skip unavailable buckets)
second_layer.addLayer(rect);
j++;
}
i++;
}
}
}
map.on('zoomend', function(evt) {
showLayers();
updateSecondLayer();
});
map.on('moveend', function(evt) {
updateSecondLayer();
});
// add the bucket group to the map
map.addLayer(top_layer);
} }
// //
@ -82,10 +157,10 @@ function setup_map (config) {
// //
window.onload = async function () { window.onload = async function () {
// download the config file // download the config file
response = await fetch('download-links.php'); response = await fetch('download-links.php');
config = await response.json(); config = await response.json();
// draw the map // draw the map
setup_map(config); setup_map(config);
}; };