Widget:LeafletWWW: Unterschied zwischen den Versionen
HorstR (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
HorstR (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
| Zeile 21: | Zeile 21: | ||
<style> | <style> | ||
#map { | #map{width:100%;height:88vh;border:3px solid black;border-radius:10px;} | ||
width:100%; | |||
height:88vh; | |||
border:3px solid black; | |||
border-radius:10px; | |||
} | |||
.layerbox{ | .layerbox{ | ||
| Zeile 46: | Zeile 41: | ||
} | } | ||
#map-frame{ | #map-frame{position:relative;} | ||
position:relative; | |||
} | |||
#map-title{ | #map-title{ | ||
| Zeile 76: | Zeile 69: | ||
} | } | ||
#map-footer a{ | #map-footer a{color:red;text-decoration:none;font-weight:bold;} | ||
color:red; | |||
text-decoration:none; | |||
font-weight:bold; | |||
} | |||
</style> | </style> | ||
| Zeile 86: | Zeile 75: | ||
<script> | <script> | ||
document.addEventListener("DOMContentLoaded", function(){ | document.addEventListener("DOMContentLoaded",function(){ | ||
var map = L.map('map',{ | var map=L.map('map',{ | ||
preferCanvas:true, | preferCanvas:true, | ||
tap:window.screen.width<600, | |||
zoomSnap:0.5, | zoomSnap:0.5, | ||
zoomDelta:0.5 | zoomDelta:0.5 | ||
| Zeile 95: | Zeile 85: | ||
var osm = L.tileLayer( | var osm=L.tileLayer( | ||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png', | 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', | ||
{maxZoom:19, attribution:'© OpenStreetMap'} | {maxZoom:19, attribution:'© OpenStreetMap'} | ||
); | ); | ||
var satellite = L.tileLayer( | var satellite=L.tileLayer( | ||
'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', | 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', | ||
{attribution:'Tiles © Esri'} | {attribution:'Tiles © Esri'} | ||
| Zeile 107: | Zeile 97: | ||
osm.addTo(map); | osm.addTo(map); | ||
L.control.layers( | L.control.layers({ | ||
{ | "Open Street Map":osm, | ||
" | |||
"Satellit":satellite | "Satellit":satellite | ||
} | }).addTo(map); | ||
).addTo(map); | |||
L.Control.geocoder({ | L.Control.geocoder({ | ||
position:'topleft', | position:'topleft', | ||
defaultMarkGeocode:true, | |||
placeholder:"Suche ..." | placeholder:"Suche ..." | ||
}).addTo(map); | }).addTo(map); | ||
| Zeile 148: | Zeile 137: | ||
var geojsonLayer = L.geoJSON(null,{ | var geojsonLayer=L.geoJSON(null,{ | ||
renderer:L.canvas(), | renderer:L.canvas(), | ||
style:function(feature){ | style:function(feature){ | ||
return{ | return{ | ||
color:nutzungColors[feature.properties.Nutzung] || "black", | color:nutzungColors[feature.properties.Nutzung]||"black", | ||
weight:2, | weight:2, | ||
fillOpacity:0.4 | fillOpacity:0.4 | ||
| Zeile 168: | Zeile 157: | ||
function | var highlightedLayers=[]; | ||
map.on('click',function(e){ | |||
var clickedFeatures=[]; | |||
highlightedLayers.forEach(layer=>geojsonLayer.resetStyle(layer)); | |||
highlightedLayers=[]; | |||
geojsonLayer.eachLayer(function(layer){ | |||
if(!map.hasLayer(layer)) return; | |||
if(layer instanceof L.Polygon && pointInLayer(e.latlng,layer)){ | |||
clickedFeatures.push(layer.feature.properties); | |||
highlightedLayers.push(layer); | |||
layer.setStyle({color:'yellow',weight:4,fillOpacity:0.6}); | |||
} | |||
}); | |||
if(clickedFeatures.length>0) showPopup(clickedFeatures,e.latlng); | |||
}); | |||
function showPopup(features,latlng){ | |||
var | var content="<div style='max-height:50vh;overflow-y:auto;min-width:200px;'>"; | ||
features.forEach(function(props){ | |||
var name=props.Name||"Unbekannt"; | |||
var | var nutzung=props.Nutzung||"-"; | ||
var | var von=props.von||"?"; | ||
var bis=props.bis||"?"; | |||
var info=props.Info||""; | |||
content+="<div style='margin-bottom:18px;border-bottom:1px solid #ccc;padding-bottom:12px;'>"+ | |||
"<b>"+name+"</b><br>"+ | |||
"<small><i>"+nutzung+"</i></small><br>"+ | |||
"<b>Zeit:</b> "+von+" bis "+bis+"<br>"+ | |||
"<p>"+info+"</p>"+ | |||
"</div>"; | |||
}); | }); | ||
content+="</div>"; | |||
L.popup({maxWidth:400}) | |||
.setLatLng(latlng) | |||
.setContent(content) | |||
.openOn(map); | |||
} | |||
function pointInLayer(latlng,layer){ | |||
var | var lat=latlng.lat,lng=latlng.lng; | ||
var polys=layer.getLatLngs(); | |||
if(layer.feature.geometry.type==="MultiPolygon"){ | |||
return polys.some(polyPart=>insidePolygon([lat,lng],polyPart[0])); | |||
} | } | ||
return insidePolygon([lat,lng],polys[0]); | |||
} | } | ||
function insidePolygon(point,vs){ | |||
var x=point[0],y=point[1],inside=false; | |||
for(var i=0,j=vs.length-1;i<vs.length;j=i++){ | |||
var xi=vs[i].lat,yi=vs[i].lng; | |||
var xj=vs[j].lat,yj=vs[j].lng; | |||
var | var intersect=((yi>y)!=(yj>y))&&(x<(xj-xi)*(y-yi)/(yj-yi)+xi); | ||
if(intersect) inside=!inside; | |||
} | |||
return inside; | |||
} | } | ||
function buildLayerbox(data){ | |||
var div=L.DomUtil.create('div','layerbox'); | |||
div.innerHTML=` | |||
<h4 id="layerToggle">☰ Layer</h4> | |||
<div id="layerContent"> | |||
<input type="text" id="searchName" placeholder="Suche nach Name ..." class="search-input"> | |||
<b>Historische Orte</b> | |||
<div id="gruppen"></div> | |||
</div> | |||
`; | |||
L.DomEvent.disableClickPropagation(div); | |||
var | var layerBox=L.control({position:'topright'}); | ||
layerBox.onAdd=function(){return div}; | |||
layerBox.addTo(map); | |||
var gruppenDiv=document.getElementById('gruppen'); | |||
var groups={}; | |||
data.features.forEach(f=>{ | |||
if(!groups[f.properties.Gruppe]) groups[f.properties.Gruppe]={}; | |||
if(!groups[f.properties.Gruppe][f.properties.Nutzung]) groups[f.properties.Gruppe][f.properties.Nutzung]=0; | |||
groups[f.properties.Gruppe][f.properties.Nutzung]++; | |||
}); | }); | ||
for(var g in groups){ | |||
var gDiv=document.createElement('div'); | |||
gDiv.innerHTML="<b>"+g+"</b><br>"; | |||
for(var n in groups[g]){ | |||
var color=nutzungColors[n]||"black"; | |||
gDiv.innerHTML+=` | |||
<label style="display:flex;align-items:center;gap:4px;"> | |||
<span style="width:14px;height:14px;background:${color};display:inline-block;border:1px solid #000;"></span> | |||
<input type="checkbox" class="layerNutzung" data-gruppe="${g}" data-nutzung="${n}" checked> | |||
${n} (${groups[g][n]}) | |||
</label><br> | |||
`; | |||
} | } | ||
gruppenDiv.appendChild(gDiv); | |||
} | } | ||
} | } | ||
Version vom 14. März 2026, 17:59 Uhr
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/> <link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css"/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> <script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>
<style>
- map{width:100%;height:88vh;border:3px solid black;border-radius:10px;}
.layerbox{ background:rgba(255,255,255,0.9); padding:10px; border-radius:6px; box-shadow:0 0 10px rgba(0,0,0,0.3); font-size:14px; max-height:70vh; overflow-y:auto; }
.search-input{ width:100%; margin-bottom:6px; padding:4px; border:1px solid #ccc; border-radius:4px; }
- map-frame{position:relative;}
- 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;}
</style>
<script>
document.addEventListener("DOMContentLoaded",function(){
var map=L.map('map',{ preferCanvas:true, tap:window.screen.width<600, zoomSnap:0.5, zoomDelta:0.5 }).setView([50.95,6.95],12);
var osm=L.tileLayer(
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
{maxZoom:19, attribution:'© OpenStreetMap'}
);
var satellite=L.tileLayer( 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {attribution:'Tiles © Esri'} );
osm.addTo(map);
L.control.layers({ "Open Street Map":osm, "Satellit":satellite }).addTo(map);
L.Control.geocoder({
position:'topleft',
defaultMarkGeocode:true,
placeholder:"Suche ..."
}).addTo(map);
var nutzungColors={
'Hof':'red',
'Mühle':'blue',
'Fabrik':'black',
'Gewerbe':'gray',
'Verwaltung':'orange',
'Bahn':'brown',
'Brücke':'navy',
'Hafen':'blue',
'Flughafen':'green',
'Versorgung':'gray',
'Tankstelle':'maroon',
'Brauerei':'yellow',
'Ziegelei':'red',
'Kloster':'orange',
'Kirche':'purple',
'Synagoge':'violet',
'Krankenhaus':'red',
'Friedhof':'green',
'Hochbunker':'black',
'Militär':'green',
'Wohnen':'brown',
'Schule':'red',
'Freizeit':'green'
};
var geojsonLayer=L.geoJSON(null,{
renderer:L.canvas(),
style:function(feature){
return{
color:nutzungColors[feature.properties.Nutzung]||"black",
weight:2,
fillOpacity:0.4
};
}
}).addTo(map);
fetch('/alteskoeln/WasWarWo.geojson')
.then(res=>res.json())
.then(data=>{
geojsonLayer.addData(data);
buildLayerbox(data);
});
var highlightedLayers=[];
map.on('click',function(e){
var clickedFeatures=[];
highlightedLayers.forEach(layer=>geojsonLayer.resetStyle(layer)); highlightedLayers=[];
geojsonLayer.eachLayer(function(layer){
if(!map.hasLayer(layer)) return;
if(layer instanceof L.Polygon && pointInLayer(e.latlng,layer)){
clickedFeatures.push(layer.feature.properties);
highlightedLayers.push(layer);
layer.setStyle({color:'yellow',weight:4,fillOpacity:0.6});
}
});
if(clickedFeatures.length>0) showPopup(clickedFeatures,e.latlng);
});
function showPopup(features,latlng){
var content="
features.forEach(function(props){
var name=props.Name||"Unbekannt"; var nutzung=props.Nutzung||"-"; var von=props.von||"?"; var bis=props.bis||"?"; var info=props.Info||"";
content+="""+name+"
"+
""+nutzung+"
"+
"Zeit: "+von+" bis "+bis+"
"+
"+info+"
"+ "});
content+="";
L.popup({maxWidth:400}) .setLatLng(latlng) .setContent(content) .openOn(map);
}
function pointInLayer(latlng,layer){
var lat=latlng.lat,lng=latlng.lng;
var polys=layer.getLatLngs();
if(layer.feature.geometry.type==="MultiPolygon"){ return polys.some(polyPart=>insidePolygon([lat,lng],polyPart[0])); }
return insidePolygon([lat,lng],polys[0]);
}
function insidePolygon(point,vs){
var x=point[0],y=point[1],inside=false;
for(var i=0,j=vs.length-1;i<vs.length;j=i++){
var xi=vs[i].lat,yi=vs[i].lng; var xj=vs[j].lat,yj=vs[j].lng;
var intersect=((yi>y)!=(yj>y))&&(x<(xj-xi)*(y-yi)/(yj-yi)+xi);
if(intersect) inside=!inside;
}
return inside;
}
function buildLayerbox(data){
var div=L.DomUtil.create('div','layerbox');
div.innerHTML=`
☰ Layer
<input type="text" id="searchName" placeholder="Suche nach Name ..." class="search-input"> Historische Orte
`;
L.DomEvent.disableClickPropagation(div);
var layerBox=L.control({position:'topright'}); layerBox.onAdd=function(){return div}; layerBox.addTo(map);
var gruppenDiv=document.getElementById('gruppen');
var groups={};
data.features.forEach(f=>{ if(!groups[f.properties.Gruppe]) groups[f.properties.Gruppe]={}; if(!groups[f.properties.Gruppe][f.properties.Nutzung]) groups[f.properties.Gruppe][f.properties.Nutzung]=0; groups[f.properties.Gruppe][f.properties.Nutzung]++; });
for(var g in groups){
var gDiv=document.createElement('div');
gDiv.innerHTML=""+g+"
";
for(var n in groups[g]){
var color=nutzungColors[n]||"black";
gDiv.innerHTML+=`
<label style="display:flex;align-items:center;gap:4px;">
<input type="checkbox" class="layerNutzung" data-gruppe="${g}" data-nutzung="${n}" checked>
${n} (${groups[g][n]})
</label>
`;
}
gruppenDiv.appendChild(gDiv);
}
}
});
</script>
