Diese Karte zeigt die Orte, an denen der Konsum von Cannabis verboten ist. Um jeden Ort wird ein Kreis mit Radius von 100 Metern (gemäß Beschlussempfehlung § 5 Konsumverbot) gezeichnet.
Oben rechts können die verschiedenen Arten von Orten an- und abgeschaltet werden
Datenquelle: OpenStreetMaps via Overpass
Keine Garantie für Korrektheit!
` ) .addTo(map); map.on('moveend', async () => { await fetchData(); }); let loading = false; function showBuffer() { console.time('prepare'); map.attributionControl.setPrefix('Berechne Zone'); const fs = Object.entries(buffers) .filter(([k]) => map.hasLayer(features[k as keyof typeof features])) .flatMap(([_, buff]) => { const fs: Feature[] = buff.flatMap((f) => f.type === 'Feature' ? [f] : f.features ); return fs; }); if (fs.length > 0) { exclusionZone.clearLayers(); console.timeEnd('prepare'); try { console.time('dissolve'); const b = dissolve(featureCollection(fs)); const zone = new GeoJSON(b, { style: { color: 'red', fillOpacity: 0.1, weight: 1 } }); console.timeEnd('dissolve'); console.time('render'); exclusionZone.addLayer(zone); console.timeEnd('render'); exclusionZone.bringToBack(); } catch (err) { console.error('dissolve', err); } } map.attributionControl.setPrefix(''); } Object.values(features).forEach((f) => { f.on('add', showBuffer); f.on('remove', showBuffer); }); async function fetchData() { if (map.getZoom() < 12 || loading) { return; } loading = true; map.attributionControl.setPrefix('Lädt...'); const bounds = map.getBounds(); const query = `[out:json][timeout:25][bbox:${bounds.getSouth()},${bounds.getWest()},${bounds.getNorth()},${bounds.getEast()}]; ( nwr["amenity"="school"]; nwr["building"="school"]; nwr["building"="university"]; nwr["leisure"="playground"]; nwr["amenity"="kindergarten"]; nwr["community_centre"="youth_centre"]; nwr["leisure"="sports_centre"]; nwr["leisure"="sports_hall"]; nwr["leisure"="stadium"]; nwr["leisure"="track"]; nwr["leisure"="pitch"]; nwr["sport"]["amenity"!="restaurant"]["amenity"!="pub"]["amenity"!="cafe"]["tourism"!="hotel"]; nwr["highway"="pedestrian"]["area"!="yes"]; ); out geom;`; const elements = await fetch('https://overpass-api.de/api/interpreter', { headers: { 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8' }, body: 'data=' + encodeURIComponent(query), method: 'POST' }) .then((b) => b.json()) .catch(() => ({ elements: [] })) .then((r) => r.elements as NWRElement[]); loading = false; console.time('parse'); map.attributionControl.setPrefix('Berechne Orte...'); const ids = elements.map((e) => e.id); const exclude: ExclusionCircle[] = []; Object.values(buffers).forEach((b) => b.splice(0)); Object.values(features).forEach((f) => f.eachLayer((l) => { const id = (l as ExclusionCircle).id; if (ids.includes(id)) { exclude.push(l as ExclusionCircle); return; } f.removeLayer(l); }) ); elements.forEach((e) => { let marker = exclude.find((it) => it.id === e.id); if (!marker) { marker = new ExclusionCircle(e); } features[marker.reason].addLayer(marker); try { const b = buffer(marker.toGeoJSON(), 100, { units: 'meters' }); // new GeoJSON(b).addTo(map); buffers[marker.reason].push(truncate(b)); } catch (err) { console.error( `Buffer calc for id=${e.id}, type=${e.type} failed`, e, err ); } }); console.timeEnd('parse'); queueMicrotask(showBuffer); map.attributionControl.setPrefix(''); } new Control.Layers( {}, Object.fromEntries( Object.entries(features).map(([k, v]) => [ ` ${k}`, v ]) ) ).addTo(map); easyButton( '📍', function () { if (!navigator.geolocation) { return; } navigator.geolocation.getCurrentPosition( (p) => map.panTo([p.coords.latitude, p.coords.longitude]), undefined, { enableHighAccuracy: true } ); } ).addTo(map); fetchData();