Altes Köln

Widget:LeafletWWW: Unterschied zwischen den Versionen

Aus Altes Köln
Wechseln zu:Navigation, Suche
Keine Bearbeitungszusammenfassung
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,
"OpenStreetMap":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 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);


var div = L.DomUtil.create('div','layerbox');
layer.setStyle({color:'yellow',weight:4,fillOpacity:0.6});


div.innerHTML=`
}
<h4>Layer</h4>
 
<input type="text" id="searchName" placeholder="Suche nach Name ..." class="search-input">
});
<div id="gruppen"></div>
 
`;
if(clickedFeatures.length>0) showPopup(clickedFeatures,e.latlng);


L.DomEvent.disableClickPropagation(div);
});


var layerBox = L.control({position:'topright'});
layerBox.onAdd=function(){return div;};
layerBox.addTo(map);


function showPopup(features,latlng){


var gruppenDiv=document.getElementById('gruppen');
var content="<div style='max-height:50vh;overflow-y:auto;min-width:200px;'>";


var groups={};
features.forEach(function(props){


data.features.forEach(f=>{
var name=props.Name||"Unbekannt";
var g=f.properties.Gruppe || "Sonstiges";
var nutzung=props.Nutzung||"-";
var n=f.properties.Nutzung || "Unbekannt";
var von=props.von||"?";
var bis=props.bis||"?";
var info=props.Info||"";


if(!groups[g]) groups[g]={};
content+="<div style='margin-bottom:18px;border-bottom:1px solid #ccc;padding-bottom:12px;'>"+
if(!groups[g][n]) groups[g][n]=0;
"<b>"+name+"</b><br>"+
"<small><i>"+nutzung+"</i></small><br>"+
"<b>Zeit:</b> "+von+" bis "+bis+"<br>"+
"<p>"+info+"</p>"+
"</div>";


groups[g][n]++;
});
});


content+="</div>";


for(var g in groups){
L.popup({maxWidth:400})
.setLatLng(latlng)
.setContent(content)
.openOn(map);


var gDiv=document.createElement('div');
}


gDiv.innerHTML=`<b>${g}</b><br>`;


for(var n in groups[g]){
function pointInLayer(latlng,layer){


var color=nutzungColors[n] || "black";
var lat=latlng.lat,lng=latlng.lng;


gDiv.innerHTML+=`
var polys=layer.getLatLngs();
<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>
`;


if(layer.feature.geometry.type==="MultiPolygon"){
return polys.some(polyPart=>insidePolygon([lat,lng],polyPart[0]));
}
}


gruppenDiv.appendChild(gDiv);
return insidePolygon([lat,lng],polys[0]);


}
}




document.querySelectorAll('.layerNutzung').forEach(cb=>{
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++){


cb.addEventListener('change',function(){
var xi=vs[i].lat,yi=vs[i].lng;
var xj=vs[j].lat,yj=vs[j].lng;


var gruppe=this.dataset.gruppe;
var intersect=((yi>y)!=(yj>y))&&(x<(xj-xi)*(y-yi)/(yj-yi)+xi);
var nutzung=this.dataset.nutzung;


geojsonLayer.eachLayer(layer=>{
if(intersect) inside=!inside;


if(layer.feature.properties.Gruppe===gruppe &&
}
layer.feature.properties.Nutzung===nutzung){


if(cb.checked) map.addLayer(layer);
return inside;
else map.removeLayer(layer);


}
}


});


});
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>
`;


document.getElementById('searchName').addEventListener('input',function(){
L.DomEvent.disableClickPropagation(div);


var val=this.value.toLowerCase();
var layerBox=L.control({position:'topright'});
layerBox.onAdd=function(){return div};
layerBox.addTo(map);


geojsonLayer.eachLayer(layer=>{


if(!layer.feature.properties.Name) return;
var gruppenDiv=document.getElementById('gruppen');


if(layer.feature.properties.Name.toLowerCase().includes(val)){
var groups={};


layer.setStyle({
data.features.forEach(f=>{
color:'yellow',
if(!groups[f.properties.Gruppe]) groups[f.properties.Gruppe]={};
weight:4,
if(!groups[f.properties.Gruppe][f.properties.Nutzung]) groups[f.properties.Gruppe][f.properties.Nutzung]=0;
fillOpacity:0.6
groups[f.properties.Gruppe][f.properties.Nutzung]++;
});
});


}else{


geojsonLayer.resetStyle(layer);
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>

Was War Wo

<style>

  1. 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; }

  1. map-frame{position:relative;}
  1. 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); }

  1. 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); }

  1. 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>