feat: add Map with Layer Group and Layers Control as src/components/map-object

This commit is contained in:
dancingCycle 2024-01-04 15:37:53 +01:00
parent feb536cf8c
commit 8dbc45f396
7 changed files with 257 additions and 5 deletions

View File

@ -0,0 +1,71 @@
import React, { useEffect, useState } from 'react';
import MapObject from './map-object';
import { get } from '../utils/request';
// import JSON
import jsonOsmQuery from '../osm-query.json';
export default function JsonOsmQuery(){
const rryOsmQuery = jsonOsmQuery.queries;
console.log('rry.lngth: ' + rryOsmQuery.length);
const [mp, setMp] = useState(null);
/*fetch array in a JavaScript function*/
const fetch = async () => {
try {
const mpRsp = new Map()
console.log('mpRsp.lngth: ' + mpRsp.size);
for ( let i = 0; i < rryOsmQuery.length; i++ ) {
console.log('i: ' + i );
const query = rryOsmQuery[i];
console.log('query title: ' + query.title);
const address = query.query;
console.log("Fetch:fetch(): address: " + address);
const res = await get(address);
console.log("Fetch:fetch(): res.length: "+res.elements.length);
mpRsp.set(query.title, res.elements)
}
setMp((mp) => mpRsp);
} catch (err) {
console.error('err.message: ' + err.message);
setMp((array) => null);
}
};
useEffect(() => {
/*effect goes here*/
fetch();
/*use an empty dependency array to ensure the hook is running only once*/
/*TODO study dependency array: https://reactjs.org/docs/hooks-effect.html*/
}, []);
if ( mp !== undefined && mp !== null && mp.size > 0 ) {
/*return a React element*/
return (
<>
<p>JsonOsmQuery</p>
<MapObject
object={mp}
/>
</>
);
}else{
return (
<>
<p>JsonOsmQuery</p>
<p>Loading...</p>
</>
);
}
};

View File

@ -1,5 +1,6 @@
import React, { useEffect, useRef, useState } from 'react'
import L from 'leaflet'
import PropTypes from 'prop-types';
import React, { useEffect, useRef, useState } from 'react'
import "leaflet/dist/leaflet.css";
import icon from "leaflet/dist/images/marker-icon.png";
@ -13,8 +14,8 @@ shadowUrl: iconShadow,
export default function MapArray( { array } ) {
console.log('map-array:MapArray: array.lngth: ' + array.length);
/*center map in the middle of RVB*/
const mapCenter = [52.16594, 10.52673];
/*center map at Node: Umweltzentrum Braunschweig (3650315388)*/
const mapCenter = [52.2671189, 10.5221905];
const mapRef = useRef();
@ -85,7 +86,7 @@ export default function MapArray( { array } ) {
layers : [baseLayerOsm, overlayMrkr]}
).setView(
mapCenter,
3
10
);
//layout control
@ -126,3 +127,7 @@ export default function MapArray( { array } ) {
};
//https://github.com/azaharyan/react-leaflet-example
MapArray.propTypes = {
array: PropTypes.array
};

View File

@ -4,7 +4,7 @@ import { get } from '../utils/request';
//TODO adjust config usage
import config from '../utils/config';
import Map from '../components/map-array';
import Map from './map-array';
export default function MapLGroup(){

View File

@ -0,0 +1,153 @@
import L from 'leaflet'
import PropTypes from 'prop-types';
import React, { useEffect, useRef, useState } from 'react'
import "leaflet/dist/leaflet.css";
import icon from "leaflet/dist/images/marker-icon.png";
import iconShadow from "leaflet/dist/images/marker-shadow.png";
let DefaultIcon = L.icon({
iconUrl: icon,
shadowUrl: iconShadow,
});
export default function MapObject( { object } ) {
console.log('map-object:MapObject: object.size: ' + object.size);
/*center map at Node: Umweltzentrum Braunschweig (3650315388)*/
const mapCenter = [52.2671189, 10.5221905];
const mapRef = useRef();
useEffect(() => {
//base layer
const baseLayerOsm = L.tileLayer(
"http://{s}.tile.osm.org/{z}/{x}/{y}.png",
{
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
maxZoom: 18,
scrollWheelZoom: false,
}
);
//map
const map = L.map(
mapRef.current,
{attributionControl: true,
layers : [baseLayerOsm]}
).setView(
mapCenter,
10
);
const rryTitleKeys = new Array();
const rryLayerValues = new Array();
//iterate over osm rsp objects
for (const [title, elements] of object) {
console.log(`The value for key ${title} is ${elements}`);
//add title
rryTitleKeys.push(title);
//add layer
//marker array
const rryMrkr = elements.map( function( value, key ) {
//console.log('map-object:MapObject:map() value: ' +JSON.stringify(value));
//get entity properties
const id = value.id;
const type = value.type;
const name = value.tags.name;
let lat, lon = null;
if ( type === "node"){
lat = value.lat;
lon = value.lon;
} else if ( type === "way" || type === "relation" ) {
lat = value.center.lat;
lon = value.center.lon;
} else {
console.error("map-entities: OSM type (" + type + ") NOT known");
}
//verify entity properties
if(lat !== undefined && lat !== null && lon !== undefined && lon !== null ){
//TODO
/*
var marker = L.marker([lat, lon]).addTo(map);
const popupText ='name: <b>' + name + '</b><br />id: ' + id + '<br />type: ' + type;
marker.bindPopup(popupText);
*/
L.Marker.prototype.options.icon = DefaultIcon;
const marker = L.marker(
[lat, lon],
{alt: 'marker name: ' + name}
);
const popupText ='name: <b>' + name + '</b><br />lat: ' + lat + '<br />lon: ' + lon;
//console.log('popupText: ' + popupText);
marker.bindPopup(popupText);
return marker
} else {
console.error('map-entities: lat or lon undefined or null');
}
});
console.log('rryMrkr: ' + rryMrkr.length);
//layer group
const overlayMrkr = L.layerGroup(rryMrkr);
rryLayerValues.push(overlayMrkr);
}
console.log('rryLayerValues.lngth: ' + rryLayerValues.length);
console.log('rryTitleKeys.lngth: ' + rryTitleKeys.length);
const overlayMaps = new Object();
for (let i = 0; i < rryTitleKeys.length; i++) {
const ttl = rryTitleKeys[i];
const lyr = rryLayerValues[i];
console.log('i: ' + i + ', ttl: ' + ttl);
overlayMaps[ttl] = lyr;
}
//ERROR console.log('overlayMaps: ' + JSON.stringify(overlayMaps));
//layout control
const baseMaps = {
"OpenStreetMap": baseLayerOsm
};
const layerControl = L.control.layers(baseMaps, overlayMaps).addTo(map);
// unmount map function
//You should unmount the function in react.js to remove the existing map.
return () => map.remove();
}, []);
if ( object !== undefined && object !== null && object.size > 0 ) {
return (
<>
<p>MapObject</p>
<div
style={{padding: 0, margin: 0, width: "75%", height: "23vh",}}
ref={el => mapRef.current = el}>
</div>
</>
);
}else{
//TODO Why does mapRef have to be present?
return (
<>
<p>MapObject loading...</p>
<div
ref={el => mapRef.current = el}>
</div>
</>
);
}
};
//https://github.com/azaharyan/react-leaflet-example
MapObject.propTypes = {
array: PropTypes.array
};

View File

@ -21,6 +21,7 @@ export default function Map ({array, title}){
);
}
};
Map.propTypes = {
array: PropTypes.array,
title: PropTypes.string

20
src/osm-query.json Normal file
View File

@ -0,0 +1,20 @@
{
"queries": [
{
"title": "Second hand shops",
"query": "https://overpass-api.de/api/interpreter?data=[out:json][timeout:60];relation(62531);map_to_area;nwr[shop=second_hand](area)->.shops;nwr[second_hand=yes](area)->.secondHands;(.shops;.secondHands;);out body center qt;"
},
{
"title": "Organic bakeries",
"query": "https://overpass-api.de/api/interpreter?data=[out:json][timeout:60];relation(62531);map_to_area;nwr[shop=bakery][organic=yes](area);out body center qt;"
},
{
"title": "Organic only shops",
"query": "https://overpass-api.de/api/interpreter?data=[out:json][timeout:60];relation(62531);map_to_area;nwr[shop][organic=only](area);out body center qt;"
},
{
"title": "Public bookcases",
"query": "https://overpass-api.de/api/interpreter?data=[out:json][timeout:60];relation(62531);map_to_area;nwr[amenity=public_bookcase](area);out body center qt;"
}
]
}

View File

@ -3,6 +3,7 @@ import { Link} from 'react-router-dom';
import List from '../components/list';
import MapLGroup from '../components/map-lgroup';
import JsonOsmQuery from '../components/json-osm-query';
export default function Home(){
@ -10,6 +11,7 @@ export default function Home(){
<>
<List />
<MapLGroup />
<JsonOsmQuery />
</>
);
}