arenos-map/index.html

187 lines
7.0 KiB
HTML
Raw Normal View History

2025-08-30 13:59:12 +02:00
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8"/>
<title>Arenos Map</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<style>
html,body,#map {height:100%;margin:0}
.coords{position:absolute;left:6px;bottom:6px;z-index:1000;background:rgba(255,255,255,.85);
padding:3px 6px;font-size:12px;border-radius:4px;font-family:system-ui,Segoe UI,Arial}
2025-09-14 15:25:37 +02:00
.center-dot{position:absolute;top:50%;left:50%;width:5px;height:5px;background:red;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 2px rgba(255,255,255,.95),0 0 2px rgba(0,0,0,.35);pointer-events:none;z-index:1001}
2025-08-30 13:59:12 +02:00
.copy-btn{position:absolute;left:6px;bottom:36px;z-index:1000;background:#ef4444;color:#fff;border:0;border-radius:6px;padding:6px 10px;font:600 12px/1 system-ui,Segoe UI,Arial;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.25)}
.copy-btn:active{transform:translateY(1px)}
</style>
</head>
<body>
<div id="map"></div>
<div class="center-dot" aria-hidden="true" title="Kartenmitte"></div>
<div class="coords"></div>
<button class="copy-btn" title="Aktuelle Kartenmitte als Marker-Code kopieren">Marker Koords</button>
<script>
// === Parameter (wie Export) ===
const ORIG_W = 49152; // px
const ORIG_H = 32768; // px
const TILE = 256; // px
const MAX_Z = 7; // 0..7, 0=weit, 7=Originalgröße
// === CRS an Export anpassen: z=7 → scale=1 (1px = 1 Einheits-Pixel), z=0 → 1/128 ===
const CRS_TILES = L.Util.extend({}, L.CRS.Simple, {
transformation: new L.Transformation(1, 0, 1, 0), // y nach unten positiv
scale: z => Math.pow(2, z - MAX_Z), // 7→1, 6→1/2, …, 0→1/128
zoom: s => Math.log(s) / Math.LN2 + MAX_Z
});
// Karte
const bounds = [[0, 0], [ORIG_H, ORIG_W]]; // Pixelkoordinaten (oben/links → unten/rechts)
const map = L.map('map', {
crs: CRS_TILES,
minZoom: 0,
maxZoom: MAX_Z,
preferCanvas: true,
zoomControl: true,
inertia: false,
keepBuffer: 0
});
map.fitBounds(bounds);
map.setMaxBounds(bounds);
// Hilfsfunktion: Tile-Grid je Zoom (wie Exporter)
function gridForZoom(z){
const scale = Math.pow(2, MAX_Z - z); // z=7 → 1
const wZ = Math.ceil(ORIG_W / scale);
const hZ = Math.ceil(ORIG_H / scale);
const tilesX= Math.ceil(wZ / TILE);
const tilesY= Math.ceil(hZ / TILE);
const offX = Math.floor(tilesX / 2);
const offY = Math.floor(tilesY / 2);
return { tilesX, tilesY, offX, offY };
}
// Debug: zeige beim ersten Tile die berechneten Werte
let first = true;
const CenteredTiles = L.GridLayer.extend({
createTile: function (coords, done) {
const img = document.createElement('img');
img.decoding = 'async';
img.referrerPolicy = 'no-referrer';
img.loading = 'lazy';
const { tilesX, tilesY, offX, offY } = gridForZoom(coords.z);
const xC = coords.x - offX; // zentrierte Namen
const yC = coords.y - offY;
const minX = -offX, maxX = tilesX - offX - 1;
const minY = -offY, maxY = tilesY - offY - 1;
if (first) {
console.log(`[z=${coords.z}] tilesX=${tilesX} tilesY=${tilesY} offX=${offX} offY=${offY}`);
console.log('tile coords →', coords, '→ centered', xC, yC, 'validX', minX, maxX, 'validY', minY, maxY);
first = false;
}
// Außerhalb? → transparent (keine HTTP-Requests)
if (xC < minX || xC > maxX || yC < minY || yC > maxY) {
img.width = img.height = TILE;
img.src = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
img.onload = () => done(null, img);
return img;
}
img.onload = () => done(null, img);
img.onerror = () => {
img.src = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">\
<rect width="100%" height="100%" fill="%23ddd"/>\
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle"\
font-family="monospace" font-size="14">no tile</text></svg>';
done(null, img);
};
img.src = `tiles/${coords.z}/${xC}/${yC}.png`;
return img;
}
});
2025-09-02 12:42:12 +02:00
// === check URL hash ===
2025-09-02 09:18:48 +02:00
// Format: #X,Y,Z (z.B. #22884,8249,5)
const hash = window.location.hash.slice(1).split(',');
if (hash.length >= 2) {
const x = parseFloat(hash[0]);
const y = parseFloat(hash[1]);
const z = hash.length >= 3 ? parseInt(hash[2]) : 5;
2025-09-02 12:42:12 +02:00
if (!isNaN(x) && !isNaN(y)) {
2025-09-02 09:22:38 +02:00
map.setView([y, x], isNaN(z) ? 5 : z);
2025-09-02 12:42:12 +02:00
}
2025-09-02 09:22:38 +02:00
}
2025-09-02 09:18:48 +02:00
2025-08-30 13:59:12 +02:00
new CenteredTiles({
tileSize: TILE,
noWrap: true,
bounds: bounds,
minNativeZoom: 0,
maxNativeZoom: MAX_Z
}).addTo(map);
// Koordinatenanzeige
const box = document.querySelector('.coords');
function show(){
const c = map.getCenter();
box.textContent = `X: ${c.lng.toFixed(0)} Y: ${c.lat.toFixed(0)} Z: ${map.getZoom()}`;
}
map.on('move zoom', show); show();
// Button: Marker-Code mit aktuellen (Mitte-)Koordinaten in die Zwischenablage
const copyBtn = document.querySelector('.copy-btn');
function copyText(text){
if (navigator.clipboard && window.isSecureContext){
return navigator.clipboard.writeText(text);
} else {
// Fallback für HTTP/unsichere Kontexte: verstecktes Textfeld + execCommand
const ta = document.createElement('textarea');
ta.value = text;
ta.setAttribute('readonly','');
ta.style.position = 'fixed';
ta.style.left = '-9999px';
ta.style.top = '-9999px';
document.body.appendChild(ta);
ta.focus();
ta.select();
let ok = false;
try { ok = document.execCommand('copy'); } catch(e) { ok = false; }
document.body.removeChild(ta);
return ok ? Promise.resolve() : Promise.reject(new Error('copy failed'));
}
}
copyBtn.addEventListener('click', () => {
const c = map.getCenter();
const X = Math.round(c.lng); // Anzeige links unten: X zuerst
const Y = Math.round(c.lat); // dann Y
const snippet = ` L.marker([${Y},${X}])
.addTo(map)
.bindTooltip("NAME")
.on('click',()=>window.open(
'WIKI_LINK','_blank'
));`;
copyText(snippet).then(() => {
const old = copyBtn.textContent; copyBtn.textContent = 'Kopiert!';
setTimeout(()=> copyBtn.textContent = old, 1200);
}).catch(err => {
console.error(err);
// Letzter Ausweg: Prompt anzeigen, manuell STRG+C drücken
window.prompt('Kopieren fehlgeschlagen. Bitte STRG+C drücken und mit OK schließen:', snippet);
});
});
</script>
<script src="markers.js"></script>
2025-10-14 15:41:39 +02:00
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
2025-08-30 13:59:12 +02:00
</body>
</html>