README
This commit is contained in:
parent
efffad1a94
commit
d793c9fa6d
1 changed files with 208 additions and 0 deletions
208
README.md
208
README.md
|
|
@ -0,0 +1,208 @@
|
||||||
|
|
||||||
|
# 🗺️ GeoTIFF-Viewer – Dokumentation
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
|
||||||
|
Interaktive Visualisierung von **GeoTIFF-Dateien** mit Farbcodierung und zusätzlichen **GeoJSON-Overlays** (z. B. Stadtgrenzen). Die Anwendung basiert auf Leaflet und ist per Docker containerisiert.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projektstruktur
|
||||||
|
|
||||||
|
```bash
|
||||||
|
geotiff-viewer/
|
||||||
|
├── data/
|
||||||
|
│ ├── class_Mainz_maxlike_gold.tif # GeoTIFF Rasterdaten
|
||||||
|
│ ├── stadtgrenze.geojson # GeoJSON für Overlay (z. B. Stadtgrenzen)
|
||||||
|
│ └── index.html # Weboberfläche mit Leaflet + GeoRaster
|
||||||
|
└── docker-compose.yaml # Nginx-Container zur Bereitstellung
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Anforderungen
|
||||||
|
|
||||||
|
- Docker
|
||||||
|
- Nginx Proxy Manager zur Weiterleitung via Subdomain
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Docker-Setup
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
geotiff-viewer:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: geotiff-viewer
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./data:/usr/share/nginx/html:ro
|
||||||
|
networks:
|
||||||
|
- npm-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
npm-network:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Weboberfläche (`index.html`)
|
||||||
|
|
||||||
|
### Funktionen
|
||||||
|
|
||||||
|
- Anzeige des GeoTIFFs als farbige Heatmap mittels [chroma.js](https://gka.github.io/chroma.js/)
|
||||||
|
- Einblendung zusätzlicher GeoJSON-Layer
|
||||||
|
- Legende mit Farbskala & Layer-Steuerung
|
||||||
|
- Lizenzhinweis im Footer
|
||||||
|
|
||||||
|
### HTML-Code
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>GeoTIFF Viewer</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
|
||||||
|
<style>
|
||||||
|
html, body, #map { height: 100%; margin: 0; padding: 0; }
|
||||||
|
.legend {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
background: white;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.2;
|
||||||
|
box-shadow: 0 0 5px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
.legend-gradient {
|
||||||
|
height: 10px;
|
||||||
|
width: 200px;
|
||||||
|
background: linear-gradient(to right, #440154, #3b528b, #21918c, #5ec962, #fde725);
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.legend-labels {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="map"></div>
|
||||||
|
<div class="legend">
|
||||||
|
<div class="legend-gradient"></div>
|
||||||
|
<div class="legend-labels">
|
||||||
|
<span id="min-val">min</span>
|
||||||
|
<span id="max-val">max</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
||||||
|
<script src="https://unpkg.com/georaster"></script>
|
||||||
|
<script src="https://unpkg.com/georaster-layer-for-leaflet"></script>
|
||||||
|
<script src="https://unpkg.com/chroma-js/chroma.min.js"></script>
|
||||||
|
<script>
|
||||||
|
const map = L.map("map").setView([50.0, 8.25], 10);
|
||||||
|
|
||||||
|
// Basiskarte
|
||||||
|
const baseLayer = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||||
|
attribution: "© OpenStreetMap contributors"
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
const overlayLayers = {};
|
||||||
|
|
||||||
|
// GeoTIFF laden
|
||||||
|
fetch("class_Mainz_maxlike_gold.tif")
|
||||||
|
.then(response => response.arrayBuffer())
|
||||||
|
.then(tiffData => {
|
||||||
|
parseGeoraster(tiffData).then(georaster => {
|
||||||
|
const min = georaster.mins[0];
|
||||||
|
const max = georaster.maxs[0];
|
||||||
|
|
||||||
|
const colorScale = chroma.scale("viridis").domain([min, max]);
|
||||||
|
|
||||||
|
document.getElementById("min-val").textContent = min.toFixed(2);
|
||||||
|
document.getElementById("max-val").textContent = max.toFixed(2);
|
||||||
|
|
||||||
|
const geotiffLayer = new GeoRasterLayer({
|
||||||
|
georaster: georaster,
|
||||||
|
pixelValuesToColorFn: values => {
|
||||||
|
const val = values[0];
|
||||||
|
if (val === null || isNaN(val)) return null;
|
||||||
|
return colorScale(val).alpha(0.7).css();
|
||||||
|
},
|
||||||
|
resolution: 64
|
||||||
|
});
|
||||||
|
|
||||||
|
geotiffLayer.addTo(map);
|
||||||
|
map.fitBounds(geotiffLayer.getBounds());
|
||||||
|
overlayLayers["GeoTIFF Heatmap"] = geotiffLayer;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// GeoJSON laden
|
||||||
|
fetch("stadtgrenze.geojson")
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(geojson => {
|
||||||
|
const geojsonLayer = L.geoJSON(geojson, {
|
||||||
|
style: {
|
||||||
|
color: "blue",
|
||||||
|
weight: 2
|
||||||
|
},
|
||||||
|
onEachFeature: (feature, layer) => {
|
||||||
|
if (feature.properties?.name) {
|
||||||
|
layer.bindPopup(feature.properties.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
overlayLayers["Stadtgrenze"] = geojsonLayer;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Layer-Steuerung hinzufügen
|
||||||
|
setTimeout(() => {
|
||||||
|
L.control.layers({ "OpenStreetMap": baseLayer }, overlayLayers, { collapsed: false }).addTo(map);
|
||||||
|
}, 1000);
|
||||||
|
</script>
|
||||||
|
<div style="
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
background: rgba(255,255,255,0.8);
|
||||||
|
text-align: center;
|
||||||
|
font-size: 11px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
padding: 3px 6px;
|
||||||
|
z-index: 999;
|
||||||
|
">
|
||||||
|
©GeoBasis-DE / LVermGeoRP 2025, dl-de/by-2-0, <a href="https://www.lvermgeo.rlp.de" target="_blank">www.lvermgeo.rlp.de</a> [Daten bearbeitet]
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Overlays
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features": [{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [[[8.20, 50.00], [8.30, 50.00], [8.30, 50.05], [8.20, 50.05], [8.20, 50.00]]]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"name": "Stadtgrenze Mainz"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
Loading…
Add table
Add a link
Reference in a new issue