Props coming from App.js like below
<div className="app__maps">
<h3>I am map</h3>
<Map countries={mapCountries} center={mapCenter} zoom={mapZoom} />
</div>
Map.js code as follows, Data is fine but inside showDataOnMap() is not adding circle in MapContainer
import React from "react";
import "./Map.css";
import { MapContainer, TileLayer, Marker, Popup, Circle } from "react-leaflet";
const casesTypeColors = {
cases: { hex: "#cc1034", multiplier: 800, },
recovered: {hex: "#7dd71d", multiplier: 1200, },
death: { hex: "#fb4443", multiplier: 2000, },
};
const showDataOnMap = (data, casesType = "cases") => {
data.map((country) => {
<Circle
center={[country.countryInfo.lat, country.countryInfo.long]}
fillOpacity={0.4}
color={casesTypeColors[casesType].hex}
fillColor={casesTypeColors[casesType].hex}
radius={
Math.sqrt(country[casesType]) * casesTypeColors[casesType].multiplier
}
>
<Popup>
<h4>I am popup</h4>
</Popup>
</Circle>;
});
};
function Map({ countries, casesType, center, zoom }) {
return (
<div className="map">
<MapContainer
center={center}
zoom={zoom}
doubleClickZoom={true}
scrollWheelZoom={true}
>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{showDataOnMap(countries, casesType)}
</MapContainer>
</div>
);
}
export default Map;
Data Generating like below data image
please help why data is not rendering on my map?
result should be like below image
You are not returning anything inside showDataOnMap that is the reason you do not see any circles. Use return keyword or don't use curly braces to return the result of the loop and the function itself.
const showDataOnMap = (data, casesType = "cases") => {
return data.map((country) => {
return <Circle
center={[country.countryInfo.lat, country.countryInfo.long]}
fillOpacity={0.4}
color={casesTypeColors[casesType].hex}
fillColor={casesTypeColors[casesType].hex}
radius={
Math.sqrt(country[casesType]) * casesTypeColors[casesType].multiplier
}
>
<Popup>
<h4>I am popup</h4>
</Popup>
</Circle>;
});
};
Demo
Related
I want to move the position in the Basemap Gallery Leaflet to the top near the Leaflet zoom on the Map but am confused about how to move the coding, here it is:
Basemap Gallery Brochure wants to move up and near Zoom.
Sample image: Images
Example of desired Basemap Gallery position:
Example of Basemap Gallery position
Here is my code and what I need to change in my code:
import { React, useState, useEffect } from 'react'
import {
LayersControl,
MapContainer,
TileLayer,
Marker,
Popup,
useMapEvents,
} from 'react-leaflet'
import List from '../Component/List'
import L from 'leaflet'
import SearchControl from './SearchControl'
const { BaseLayer } = LayersControl
function LocationMarker() {
const [position, setPosition] = useState(null)
const map = useMapEvents({
locationfound(e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
},
})
return position === null ? null : (
<Marker position={position}>
<Popup>Location Me</Popup>
</Marker>
)
}
function MyLocationMe() {
const [map, setMap] = useState(null)
const [position, setPosition] = useState(null)
useEffect(() => {
if (!map) return
L.easyButton('fa-map-marker', () => {
map.locate().on('locationfound', function (e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
})
}).addTo(map)
}, [map])
return (
<div className="flex ml-auto">
<List />
<div className="w-4/5">
<MapContainer
center={{ lat: 51.505, lng: -0.09 }}
zoom={20}
style={{ height: '100vh' }}
whenCreated={setMap}
>
<SearchControl className="MarkerIcon" position="topright" />
<LayersControl position="topleft">
<BaseLayer checked name="OpenStreetMap">
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png "
/>
</BaseLayer>
</LayersControl>
<LocationMarker />
</MapContainer>
</div>
</div>
)
}
export default MyLocationMe
The easiest way to do that is to change the left css property of the relevant css class by making position absolute
Add this to your styles.css
.leaflet-control-layers.leaflet-control {
position: absolute;
left: 50px;
}
Demo
I want to move the position on the BasemapGallery Leaflet and GeoSearch Leaflet on the Map but for confusion how to move in coding, here is:
The BasemapGallery leaflet wants to move to the right, and
The GeoSearch leaflet wants to move to the left.
Sample image:
Image
Here is my code and what I need to change in my code:
import { React, useState, useEffect } from 'react'
import {
LayersControl,
MapContainer,
TileLayer,
Marker,
Popup,
useMapEvents,
} from 'react-leaflet'
import List from '../Component/List'
import L from 'leaflet'
import SearchControl from './SearchControl'
const { BaseLayer } = LayersControl
function LocationMarker() {
const [position, setPosition] = useState(null)
const map = useMapEvents({
locationfound(e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
},
})
return position === null ? null : (
<Marker position={position}>
<Popup>Location Me</Popup>
</Marker>
)
}
function MyLocationMe() {
const [map, setMap] = useState(null)
const [position, setPosition] = useState(null)
useEffect(() => {
if (!map) return
L.easyButton('fa-map-marker', () => {
map.locate().on('locationfound', function (e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
})
}).addTo(map)
}, [map])
return (
<div className="flex ml-auto">
<List />
<div className="w-4/5">
<MapContainer
center={{ lat: 51.505, lng: -0.09 }}
zoom={20}
style={{ height: '100vh' }}
whenCreated={setMap}
>
<SearchControl className="MarkerIcon" />
<LayersControl>
<BaseLayer checked name="OpenStreetMap">
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png "
/>
</BaseLayer>
</LayersControl>
<LocationMarker />
</MapContainer>
</div>
</div>
)
}
export default MyLocationMe
There should be a position attribute for the controls:
<SearchControl className="MarkerIcon" position="topright" />
and
<LayersControl position="topleft">
<BaseLayer checked name="OpenStreetMap">
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png "
/>
</BaseLayer>
</LayersControl>
I'm trying to get coordinates of where the mouse clicks on the map but .locate() only returns the center coordinates of the map.
Is there a way?
ps. I am not using class based react.
Thanks
<MapContainer
center={[ 33.8735578, 35.86379]}
zoom={9}
scrollWheelZoom={true}
>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
you can get coordinates of mouse click by useMapEvents hook.
try this one.
const MapEvents = () => {
useMapEvents({
click(e) {
// setState your coords here
// coords exist in "e.latlng.lat" and "e.latlng.lng"
console.log(e.latlng.lat);
console.log(e.latlng.lng);
},
});
return false;
}
return (
<MapContainer
center={[ 33.8735578, 35.86379]}
zoom={9}
scrollWheelZoom={true}
>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<MapEvents />
</MapContainer>
)
Question and where is your code? You are not new to this site so you should know to show what you have done so far.
Okay, I will be gracious today ;)
I don't want to cut and clean the code, so I paste as is.
import { useEffect } from 'react';
import { MapContainer, useMap, TileLayer, } from 'react-leaflet';
import L from 'leaflet';
import tileLayer from '../util/tileLayer';
const center = [52.22977, 21.01178];
const GetCoordinates = () => {
const map = useMap();
useEffect(() => {
if (!map) return;
const info = L.DomUtil.create('div', 'legend');
const positon = L.Control.extend({
options: {
position: 'bottomleft'
},
onAdd: function () {
info.textContent = 'Click on map';
return info;
}
})
map.on('click', (e) => {
info.textContent = e.latlng;
})
map.addControl(new positon());
}, [map])
return null
}
const MapWrapper = () => {
return (
<MapContainer center={center} zoom={18} scrollWheelZoom={false}>
<TileLayer {...tileLayer} />
<GetCoordinates />
</MapContainer>
)
}
export default MapWrapper;
I'm using react-leaflet, and after webpack triggers a hot reload, GeoJSON features remain on the map, but none are present if we check map._layers on load, like this:
map.whenReady(() => console.log(map._layers))
Similarly, using map.eachLayer doesn't work, since leaflet apparently doesn't yet know about the layers.
But if I open the Chrome console and check map._layers manually, the layers are present. Why is this delay happening, and how can I wait for them to load so I can clear them?
If you take a look at the React-Leaflet docs, you can see that the whenReady method doesn't take in the map instance. The whenCreated method, however, does:
If you want to access the map instance once the map has been rendered, you should be using the whenCreated map method rather than the whenReady method.
You can also use the whenCreated method to set the map to state and access it in a useEffect hook, for eaxmple. Here is an example component:
import React, { useState, useEffect } from 'react';
import L from 'leaflet';
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
const MapComponent = () => {
const [map, setMap] = useState(null);
const position = [51.505, -0.09];
useEffect(() => {
if (!map) return;
if (map) {
console.log(map.eachLayer((layer) => console.log('USE EFFECT:', layer)));
}
}, [map]);
return (
<>
<MapContainer
center={position}
zoom={13}
scrollWheelZoom={false}
style={{ height: '100vh', width: '100%', padding: 0 }}
whenCreated={(map) => {
console.log('MAP:', map);
console.log(map.eachLayer((layer) => console.log('LAYER:', layer)));
setMap(map);
}}
>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={position}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</MapContainer>
</>
);
};
export default MapComponent;
Here is a demo on StackBlitz you can play around with: DEMO
If you want to access the map instance from the useMap or any other hook, you just have to make sure that you are using the hook in a descendant of a MapContainer:
import React, { useState, useEffect } from 'react';
import L from 'leaflet';
import { MapContainer, TileLayer, Marker, Popup, useMap } from 'react-leaflet';
const ChildOfMapContainer = (props) => {
// Set up the useMap hook in the descendant of MapContainer
const map = useMap();
// Access the map instance:
useEffect(() => {
// map.eachLayer((layer) => console.log('Layer:', layer));
map.whenReady(() => map.eachLayer((layer) => console.log(layer)));
}, [props, map]);
return (
<>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={props.position}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</>
);
};
const MapComponent = () => {
const position = [51.505, -0.09];
return (
<>
<MapContainer
center={position}
zoom={13}
scrollWheelZoom={false}
style={{ height: '100vh', width: '100%', padding: 0 }}
>
<ChildOfMapContainer position={position} />
</MapContainer>
</>
);
};
export default MapComponent;
Sandbox with this example
I'm trying to create a react-leaflet Map that onClick creates a Marker on the click's Lat and Lng. The problem is that the marker is created at an offset, towards the bottom right instead of on the mouse cursor.
import React, { useState, useContext } from "react";
import classes from "./WorldMap.module.css";
import { Map, TileLayer, Marker } from "react-leaflet";
import L from "leaflet";
import RoundInformationDisplay from "./RoundInfoDisplay/RoundInfoDisplay";
import ConfirmGuessButton from "./ConfirmGuessButton/ConfirmGuessButton";
import { AppContext } from "../../../../context/appContext";
interface Props {
handleEndOfRound: () => void;
}
const WorldMap: React.FC<Props> = (props) => {
const { currentRoundGuess, setCurrentRoundGuess } = useContext(AppContext);
const icon = L.icon({ iconUrl: require("../../../../static/marker.svg") });
const [selected, setSelected] = useState<boolean>(false);
const handleMapClick = (e: any) => {
setCurrentRoundGuess({ ...e.latlng });
setSelected(true);
};
return (
<div className={classes.WorldMapContainer}>
<div className={classes.InfoDisplay}>
<RoundInformationDisplay />
</div>
<Map
center={[45.4, -75.7]}
zoom={3}
className={classes.Map}
onClick={(e: any) => handleMapClick(e)}
>
{selected ? (
<Marker
position={[currentRoundGuess.lat, currentRoundGuess.lng]}
icon={icon}
/>
) : (
<p></p>
)}
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
</Map>
<div className={classes.ConfirmButton}>
<ConfirmGuessButton
selected={selected}
handleEndOfRound={props.handleEndOfRound}
/>
</div>
</div>
);
};
export default WorldMap;
A video showcasing the issue: https://streamable.com/g5uusl
What could be causing this problem? Thank you in advance.
As was mentioned in comments icon.iconanchor property allows to align the icon position relative to marker's location, in case of react-leaflet library, icon.iconanchor property could be specified as demonstrated below:
function MapExample(props) {
const [selectedPos, setSelectedPos] = useState(props.center);
function getMarkerIcon() {
const icon = new L.Icon({
iconSize: [32, 37], // size of the icon
iconAnchor: [16, 37],
iconUrl: "/bigcity_green.png",
});
return icon;
}
function handleMapClick(e) {
setSelectedPos(e.latlng);
}
return (
<Map center={props.center} zoom={props.zoom} onclick={handleMapClick}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
{selectedPos && <Marker position={selectedPos} icon={getMarkerIcon()} />}
</Map>
);
}