From 18a6c45d71d10e50dbdd475e5e2aab6ab559b729 Mon Sep 17 00:00:00 2001 From: fly Date: Wed, 25 Oct 2023 12:47:56 +0000 Subject: [PATCH] Leaflet map working with top and second level and it performs well! Signed-off-by: fly --- managment/www/download-links.php | 52 ++++++++- managment/www/map.js | 193 +++++++++++++++++++++---------- 2 files changed, 184 insertions(+), 61 deletions(-) diff --git a/managment/www/download-links.php b/managment/www/download-links.php index 3214681..8425114 100644 --- a/managment/www/download-links.php +++ b/managment/www/download-links.php @@ -1,4 +1,5 @@ { + "topLevel": { 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": { +query($sql)->fetch_all(MYSQLI_ASSOC); if ($ret != False) @@ -37,7 +85,6 @@ { $ns = "s"; } - $y = (abs($i - 80) / 10) * 25; for ($j = -180; $j < 180; $j += 1) { if ($first) @@ -57,8 +104,9 @@ $ew = "e"; } $name = $ew . clipNumber($j, 3) . $ns . clipNumber($i, 2); - echo '"' . $name . '": {"name": "' . $name . '", "color": "' . $tiles[$name] . '"}'; + echo '"' . $name . '": "' . $tiles[$name] . '"'; } } ?> + } } diff --git a/managment/www/map.js b/managment/www/map.js index cb40616..8f78ceb 100644 --- a/managment/www/map.js +++ b/managment/www/map.js @@ -4,77 +4,152 @@ * Uses Leaflet. */ +// feature group to hold the scenery-bucket rectangles +var top_layer = L.featureGroup(); +var second_layer = L.featureGroup(); + /** * Create interactive map. */ function setup_map (config) { - /** - * Parse a bucket name to get the lat/lon - */ - function parse_bucket_name(name) { - let lon = parseInt(name.substr(1, 3)); - let lat = parseInt(name.substr(5, 2)); - if (name.substr(0, 1).toLowerCase() == 'w') { - lon *= -1; - } - if (name.substr(4, 1).toLowerCase() == 's') { - lat *= -1; - } - return [lat, lon]; - } + /** + * Parse a bucket name to get the lat/lon + */ + function parse_bucket_name(name) { + let lon = parseInt(name.substr(1, 3)); + let lat = parseInt(name.substr(5, 2)); + if (name.substr(0, 1).toLowerCase() == 'w') { + lon *= -1; + } + if (name.substr(4, 1).toLowerCase() == 's') { + lat *= -1; + } + return [lat, lon]; + } - - /** - * Start a download in the user's browser - */ - function download(tile) { - var a = document.getElementById("progressinfo"); - a.setAttribute("src", "progressinfo.php?minor=" + tile); - } + + /** + * Start a download in the user's browser + */ + function download(tile) { + var a = document.getElementById("progressinfo"); + a.setAttribute("src", "progressinfo.php?minor=" + tile); + } - - // the Leaflet map object - let map = L.map('map').setView([45, -100], 4); + function norm(num, length) { + var ret = String(Math.abs(num)); + while (ret.length < length) + { + ret = '0' + ret; + } + return ret; + } - // add OpenStreetMap tiles - L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { - maxZoom: 15, - attribution: '© OpenStreetMap' - }).addTo(map); + + // the Leaflet map object + let map = L.map('map').setView([0, 0], 1); - // feature group to hold the scenery-bucket rectangles - let rectangle_layer = L.featureGroup(); + // add OpenStreetMap tiles + L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 15, + attribution: '© OpenStreetMap' + }).addTo(map); - // Create a rectangle for each bucket - for (const [bucket_name, props] of Object.entries(config)) { - 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); + // Create a rectangle for each bucket + 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); - // add the bucket name to the rect - rect.bucket_name = bucket_name; + // add the bucket name to the rect + rect.bucket_name = bucket_name; - // show the bucket name on mouseover - rect.bindTooltip(bucket_name); + // show the bucket name on mouseover + rect.bindTooltip(bucket_name); - // Download when the user clicks on an area - rect.on('click', (e) => { - console.log(props); - download(props.name); - }) + // add to the bucket group (for now, skip unavailable buckets) + top_layer.addLayer(rect); + } - // add to the bucket group (for now, skip unavailable buckets) - rectangle_layer.addLayer(rect); - } + function showLayers() { + if (map.getZoom() <= 4) { + if (!map.hasLayer(top_layer)) map.addLayer(top_layer); + 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 the bucket group to the map - map.addLayer(rectangle_layer); + function updateSecondLayer() { + 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); - // set the map's zoom - map.fitBounds(rectangle_layer.getBounds()); + // add the bucket name to the rect + rect.bucket_name = bucket_name; + + // show the bucket name on mouseover + 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 () { - // download the config file - response = await fetch('download-links.php'); - config = await response.json(); + // download the config file + response = await fetch('download-links.php'); + config = await response.json(); - // draw the map - setup_map(config); + // draw the map + setup_map(config); };