Widget:WWW-Siedlungen
<!DOCTYPE html> <html> <head>
<title>Siedlungsentwicklung</title> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/> <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> <link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css"/> <script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>
<style>
body { padding:10px; font-family:sans-serif; }
#map-frame { border-radius:8px; position: relative;}
#map { width: 100%; height: 88vh; /* größere Karte */ border: 3px solid black; border-radius: 10px; }
#map-title { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); z-index: 1000; background: rgba(255,255,255,0.85); padding: 6px 14px; font-weight: bold; font-size: 18px; border-radius: 6px; box-shadow: 0 0 6px rgba(0,0,0,0.3); }
#map-footer { position: absolute; bottom: 10px; left: 10px; z-index: 1000; background: rgba(255,255,255,0.85); padding: 4px 10px; border-radius: 6px; font-size: 13px; box-shadow: 0 0 6px rgba(0,0,0,0.3); }
#map-footer a { color: red; text-decoration: none; font-weight: bold; }
/* Slider über der Karte, mittig unten */
.leaflet-control-time {
position: absolute;
left: 50%;
bottom: 20px;
transform: translateX(-50%);
background: rgba(255,255,255,0.95);
padding: 10px 20px;
border-radius:10px;
box-shadow:0 4px 12px rgba(0,0,0,0.35);
z-index: 1000;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}
#yearSlider { width: 300px; }
#yearLabel { font-weight:bold; min-width:45px; text-align:center; }
.time-axis { width: 100%; display: flex; justify-content: space-between; font-size: 12px; margin-top: 4px; }
.legend{
line-height:20px;
background:white;
padding:10px;
border-radius:6px;
box-shadow:0 0 10px rgba(0,0,0,0.3);
font-size:14px;
}
.legend i{width:18px;height:18px;float:left;margin-right:8px;}
.legend-header{
cursor:pointer;
font-weight:bold;
display:flex;
justify-content:space-between;
align-items:center;
border-bottom:1px solid #ccc;
margin-bottom:5px;
padding-bottom:3px;
}
.popup-card{width:270px;font-family:sans-serif;}
.popup-img{width:100%;max-height:220px;object-fit:cover;border-radius:8px 8px 0 0;cursor:pointer;}
.popup-body{padding:10px;}
.popup-title{font-size:18px;font-weight:bold;margin-bottom:4px;}
.popup-sub{font-style:italic;color:#666;margin-bottom:6px;}
.popup-info{font-size:13px;line-height:1.4;margin-bottom:8px;}
.popup-text{font-size:14px;line-height:1.4;}
.popup-link{margin-top:8px;font-weight:bold;}
.leaflet-popup-content-wrapper{border-radius:10px;box-shadow:0 6px 20px rgba(0,0,0,0.35);}
</style>
</head>
<body>
<script>
var map = L.map('map').setView([50.95,6.95],12);
var intervals=[
{from:50,to:949,color:'#ffffcc'},
{from:950,to:1105,color:'#ffeda0'},
{from:1106,to:1179,color:'#fed976'},
{from:1180,to:1879,color:'#feb24c'},
{from:1880,to:1918,color:'#fd8d3c'},
{from:1919,to:1945,color:'#fc4e2a'},
{from:1946,to:1959,color:'#e31a1c'},
{from:1960,to:1979,color:'#bd0026'},
{from:1980,to:1999,color:'#800026'},
{from:2000,to:2026,color:'#4d0018'}
];
function getColor(jahr){
for(var i=0;i<intervals.length;i++){
if(jahr>=intervals[i].from && jahr<=intervals[i].to) return intervals[i].color;
}
return "#999";
}
// --- Kartenlayer ---
var osm = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png',{maxZoom:19, attribution:'© OpenStreetMap'}).addTo(map);
var satellite = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',{attribution:'Tiles © Esri'});
L.control.layers({"OpenStreetMap":osm,"Satellit":satellite}).addTo(map);
L.Control.geocoder({position:'topleft', defaultMarkGeocode:true, placeholder:"Suche ..."}).addTo(map);
var highlightedLayer=null; var popupFeatures=[]; var popupIndex=0; var geojsonLayer=null;
function isPointInPolygon(latlng,layer){
var coords=layer.getLatLngs();
if(layer.feature.geometry.type==="MultiPolygon"){
return coords.some(part=>isInside(latlng,part[0]));
}
return isInside(latlng,coords[0]);
}
function isInside(latlng,poly){
var x=latlng.lat; var y=latlng.lng; var inside=false;
for(var i=0,j=poly.length-1;i<poly.length;j=i++){
var xi=poly[i].lat, yi=poly[i].lng, xj=poly[j].lat, yj=poly[j].lng;
var intersect=((yi>y)!=(yj>y)) && (x<(xj-xi)*(y-yi)/(yj-yi)+xi);
if(intersect) inside=!inside;
}
return inside;
}
function showPopup(index,latlng){
popupIndex=index;
var props=popupFeatures[index];
var name=props.Name||"Unbekannt";
var nutzung=props.Nutzung||"-";
var jahr=props.Jahr||"?";
var gebiet=props.Gebiet||"-";
var zeitraum=props.Zeitraum||"-";
var info=props.Info||"";
var bild=props.Bild?'<img class="popup-img" src="'+props.Bild+'" onclick="window.open(\+props.Bild+'\')">':;
var link=props.Link?'
':;
var nav="";
if(popupFeatures.length>1){
nav='
'<button onclick="changeFeature(-1)">◀</button>'+
''+(index+1)+' / '+popupFeatures.length+''+
'<button onclick="changeFeature(1)">▶</button>'+
'';
}
var content='
Gebiet: '+gebiet+'
Zeitraum: '+zeitraum+'
';
L.popup({maxWidth:300}).setLatLng(latlng).setContent(content).openOn(map);
}
function changeFeature(step){
popupIndex+=step;
if(popupIndex<0) popupIndex=popupFeatures.length-1;
if(popupIndex>=popupFeatures.length) popupIndex=0;
showPopup(popupIndex,map.getCenter());
}
// --- GeoJSON laden ---
fetch("Siedlung.geojson").then(res=>res.json()).then(data=>{
geojsonLayer=L.geoJSON(data,{
style:function(feature){
var jahr=feature.properties.Jahr;
if(!jahr || jahr===0) return {opacity:0, fillOpacity:0, stroke:false, interactive:false};
return {color:"#555", weight:1, fillColor:getColor(jahr), fillOpacity:0.7};
},
onEachFeature:function(feature,layer){
layer.on({
mouseover:function(e){
var l=e.target;
var currentYear=parseInt(document.getElementById("yearSlider").value);
if(l!==highlightedLayer && (feature.properties.Jahr||0)<=currentYear){
l.setStyle({weight:3,color:"#000",fillOpacity:0.9});
}
},
mouseout:function(e){
var l=e.target;
var currentYear=parseInt(document.getElementById("yearSlider").value);
if(l!==highlightedLayer){
if((feature.properties.Jahr||0)>currentYear){
l.setStyle({fillOpacity:0,opacity:0});
}else{
geojsonLayer.resetStyle(l);
}
}
},
click:function(e){
var l=e.target;
var currentYear=parseInt(document.getElementById("yearSlider").value);
if((feature.properties.Jahr||0)<=currentYear){
if(highlightedLayer) geojsonLayer.resetStyle(highlightedLayer);
highlightedLayer=l;
// --- Highlight setzen ---
l.setStyle({weight:4, color:"cyan", fillOpacity:1, fillColor: "yellow" });
// --- Zoom auf angeklicktes Polygon ---
map.flyToBounds(l.getBounds(), {padding:[40,40], maxZoom:16, duration:0.8});
popupFeatures=[feature.properties];
showPopup(0,e.latlng);
}
}
});
}
}).addTo(map);
});
// --- Timeslider ---
var sliderControl = L.DomUtil.create('div','leaflet-control-time');
sliderControl.innerHTML = '<input type="range" id="yearSlider" min="50" max="2026" value="2026" step="1">'+
'2026'+
'
intervals.map(i=>''+i.from+'').join()+
'';
L.DomEvent.disableClickPropagation(sliderControl);
document.getElementById('map').appendChild(sliderControl);
var yearSlider=document.getElementById("yearSlider");
var yearLabel=document.getElementById("yearLabel");
yearSlider.addEventListener("input", function(){ var year = parseInt(this.value); yearLabel.innerText = year;
// Array für alle sichtbaren Layer dieses Jahres var visibleLayers = [];
geojsonLayer.eachLayer(function(layer){ var featureJahr = layer.feature.properties.Jahr; if(featureJahr && featureJahr > 0){ if(featureJahr <= year){ layer.setStyle({fillOpacity:0.7, opacity:1, stroke:true}); visibleLayers.push(layer); } else { layer.setStyle({fillOpacity:0, opacity:0, stroke:false}); } } else { layer.setStyle({fillOpacity:0, opacity:0, stroke:false}); } });
// Zoom auf alle sichtbaren Layer if(visibleLayers.length > 0){ var group = L.featureGroup(visibleLayers); map.fitBounds(group.getBounds(), {padding:[40,40]}); } });
// --- Legende ---
var legend=L.control({position:"bottomright"});
legend.onAdd=function(map){
var div=L.DomUtil.create("div","legend");
div.innerHTML=
'
'Zeit (Jahr)'+ '−'+'
'+ '
intervals.map(i=>''+i.from+' – '+i.to+''
').join()+
';
L.DomEvent.disableClickPropagation(div);
L.DomEvent.on(div.querySelector('#legend-header'),'click',function(){
var body=document.getElementById("legend-body");
var icon=document.getElementById("legend-toggle-icon");
if(body.style.display==="none"){body.style.display="block"; icon.innerHTML="−";}
else{body.style.display="none"; icon.innerHTML="+";}
});
return div;
};
legend.addTo(map);
</script>
</body> </html>
