1/** 2 * Leaflet-Karte mit mehreren Markern für die FokusThema-Detailseite. 3 */ 4export default class FokusThemaMap { 5 constructor(containerSelector = '#fokus-thema-map-container') { 6 this.container = document.querySelector(containerSelector); 7 8 if (this.container && document.getElementById('fokus-thema-map')) { 9 this.init(); 10 } 11 } 12 13 init() { 14 let markers; 15 try { 16 markers = JSON.parse(this.container.getAttribute('data-markers') || '[]'); 17 } catch (e) { 18 console.warn('FokusThemaMap: Ungültige Marker-Daten', e); 19 return; 20 } 21 22 if (!markers.length) return; 23 24 const validMarkers = markers.filter(m => !isNaN(parseFloat(m.lat)) && !isNaN(parseFloat(m.lng)) 25 && parseFloat(m.lat) !== 0 && parseFloat(m.lng) !== 0); 26 27 if (!validMarkers.length) return; 28 29 const osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { 30 attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' 31 }); 32 33 const satellite = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { 34 attribution: 'Tiles © Esri — Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' 35 }); 36 37 const map = L.map('fokus-thema-map', { layers: [osm] }); 38 39 const mapEl = document.getElementById('fokus-thema-map'); 40 let isSatellite = false; 41 42 const btn = document.createElement('button'); 43 btn.className = 'map-layer-toggle'; 44 btn.textContent = 'Satellit'; 45 btn.addEventListener('click', () => { 46 isSatellite = !isSatellite; 47 if (isSatellite) { 48 map.removeLayer(osm); 49 map.addLayer(satellite); 50 mapEl.classList.add('satellite-active'); 51 btn.textContent = 'Karte'; 52 } else { 53 map.removeLayer(satellite); 54 map.addLayer(osm); 55 mapEl.classList.remove('satellite-active'); 56 btn.textContent = 'Satellit'; 57 } 58 }); 59 mapEl.appendChild(btn); 60 61 const locationIcon = L.icon({ 62 iconUrl: '/img/icon-location.svg', 63 iconSize: [32, 36], 64 iconAnchor: [16, 32], 65 popupAnchor: [0, -32] 66 }); 67 68 const leafletMarkers = validMarkers.map(m => { 69 const marker = L.marker([parseFloat(m.lat), parseFloat(m.lng)], { icon: locationIcon }); 70 if (m.title || m.url) { 71 const imgHtml = m.image 72 ? `<img src="https://baukunst-nrw.de/backend/img/objekte/M/${m.image}" style="width:160px;height:100px;object-fit:cover;display:block;margin-bottom:6px;" alt="${m.title}">` 73 : ''; 74 const titleHtml = m.url 75 ? `<a href="${m.url}" class="fw-bold">${m.title}</a>` 76 : `<span class="fw-bold">${m.title}</span>`; 77 marker.bindPopup(`${imgHtml}${titleHtml}`, { maxWidth: 180 }); 78 } 79 return marker.addTo(map); 80 }); 81 82 // Karte auf alle Marker einpassen 83 const group = L.featureGroup(leafletMarkers); 84 map.fitBounds(group.getBounds().pad(0.15)); 85 86 setTimeout(() => { 87 map.invalidateSize(); 88 }, 500); 89 } 90}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.