How to move BasemapGallery position in ReactJS Leaflet? - javascript

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

Related

How to change button position in reactJS Leaflet?

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>

How to get coordinates of current mouse click in leaflet react js

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;

From where is leaflet loading data after hot module reload?

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

How to find lat/long properties in leaflet React

I've been trying to integrate leaflet into my react app. Can't figure out how to read properties from the marker. I managed to do it in vanilla JavaScript, but can't apply it to React JS project. How do i find lat and long properties of a draggable marker?
import React, { useState, useEffect } from "react";
import { Map as LeafletMap, TileLayer, Marker, Popup } from "react-leaflet";
import RangeSlider from "react-bootstrap-range-slider";
import L from "leaflet";
const MapComponent = () => {
const [position, setPosition] = useState({
lat: 51.505,
lng: -0.09,
});
const [value, setValue] = useState();
return (
<div>
<LeafletMap
center={[50, 10]}
zoom={6}
maxZoom={10}
attributionControl={true}
zoomControl={true}
doubleClickZoom={true}
scrollWheelZoom={true}
dragging={true}
animate={true}
easeLinearity={0.35}
>
<TileLayer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png" />
<Marker position={[50, 10]} draggable>
<Popup>Popup for any custom information.</Popup>
</Marker>
</LeafletMap>
<RangeSlider
value={value}
className="slider"
max={2020}
onChange={(e) => setValue(e.target.value)}
/>
</div>
);
};
export default MapComponent;
Listen to marker's onDragEnd event to be able to extract the new marker coordinates:
<Marker
position={[50, 10]}
draggable
icon={icon}
ondragend={handleDragEnd}
>
...
const handleDragEnd = (e) => {
const { lat, lng } = e.target.getLatLng();
console.log(`Lat: ${lat}, Lon: ${lng}`);
};
Demo
Actually, I imported leaflet library to use the icon on my Marker:
import Leaflet from 'leaflet';
import mapMarkerImg from "../Smile-map.svg";
const mapIcon = Leaflet.icon({
iconUrl: mapMarkerImg,
iconSize:[58, 68],
iconAnchor:[29, 68],
popupAnchor:[170,2]
})
and then I can apply it on Marker component:
<Marker icon={mapIcon} position={[-22.9094183, -43.1850019]}>
<Popup
closeButton={false}
minWidth={240}
maxWidth={240}
className={"map-popup"}
>
Lar das meninas
<Link to="/orphanages/1">
<FiArrowRight size={20} color="#FFF" />
</Link>
</Popup>
</Marker>

When creating a Marker onClick, the marker is offset and not directly where the mouse cursor is

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

Categories

Resources