I'd like to ask if I'm using the map from React Leaflet (https://react-leaflet.js.org/) but how do I add the Base Map Gallery button to the map? like this example Basemap Gallery button on the image that I marked with red arrow and do I need to change or delete any of my code?
Example view of BasemapGallery but map from React-Leaflet - ReactJS:
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
Example view of BasemapGallery but map from React-Leaflet - ReactJS:
Images
Related
I have a project using React, react-leaflet and Framework 7. In one component I have a Fab-Button from Framework 7 and a Map from react-leaflet. My Map.jsx component looks like this:
import React, { useState } from "react";
import { MapContainer, TileLayer, useMapEvents, Marker, Popup } from "react-leaflet";
import "../css/leaflet.css";
import "../css/app.css";
import {Fab, Icon, PageContent} from "framework7-react";
export default function Map(){
function LocationMarker() {
const [position, setPosition] = useState(null)
const map = useMapEvents({
click() {
map.locate()
},
locationfound(e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
},
locationerror(e) {
alert("Unfortunately, we could not find your location")
}
})
return position === null ? null : (
<Marker position={position}>
<Popup>You are here</Popup>
</Marker>
)
}
function fabGoToCurrentPosition() {
//probably something like this:
map.locate()
}
return (
<>
<Fab position="right-bottom" slot="fixed" id="fab-button" onClick={() => {
fabGoToCurrentPosition()
}}>
<Icon f7="placemark_fill" ios="f7:placemark_fill" aurora="f7:placemark_fill"></Icon>
</Fab>
<PageContent className='page-content-map'>
<MapContainer center={[51.505, -0.09]} zoom={13} scrollWheelZoom={true} id="map">
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<LocationMarker/>
</MapContainer>
</PageContent>
</>
);
}
The function "LocationMarker" is from a react-leaflet tutorial and sets the position of the Map to the current location of the user if the Map is clicked. My aim is that the position is set if the user clicks the Fab-Button instead of the Map.
I'd like to ask if I'm using the map from React Leaflet (https://react-leaflet.js.org/) but how do I add the Base Map Gallery button to the map? like this example Basemap Gallery button on the image that I marked with red arrow.
And pictures in the link:
Example of an arrow Basemap Gallery
An example on my map where I want to add Basemap Gallery
And how to show the Basemap Gallery button, where do you save it from my coding?
import { React, useState, useEffect } from 'react'
import {
LayersControl,
MapContainer,
TileLayer,
Marker,
Popup,
useMapEvents,
} from 'react-leaflet'
import L from 'leaflet'
import 'leaflet-easybutton/src/easy-button'
import 'leaflet-easybutton/src/easy-button.css'
import 'font-awesome/css/font-awesome.min.css'
const { BaseLayer } = LayersControl;
export default function MyMaps() {
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">
<div className="w-4/5">
<MapContainer
center={[51.505, -0.09]}
zoom={20}
style={{ height: "100vh" }}
whenCreated={setMap}
>
<LayersControl>
<BaseLayer checked name="OpenStreetMap">
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png "
/>
</BaseLayer>
</LayersControl>
</MapContainer>
</div>
</div>
);
}
I am unable to set view of the map for the input IP address while the Marker can move to the new location on the map for given input IP address. Map seems to stay at initial location whereas the Marker moves to new location.
So, When I type in a new IP address in input, it should change the map to a new location.
import React, { useEffect, useState} from "react";
import Result from "../src/Components/Result";
import {MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
function App() {
const APP_KEY = PERSONAL_KEY;
const [IPdata, SetIPData] = useState([]);
const [search, setSearch] = useState("");
const [query, setQuery] = useState("8.8.8.8");
const [loaded, setLoaded] = useState(false);
useEffect(() => {
getIp();
setLoaded(true);
}, [query]);
async function getIp() {
const response = await fetch(`https://geo.ipify.org/api/v1?apiKey=${APP_KEY}&ipAddress=${query}`);
const data = await response.json();
console.log(data);
SetIPData(data)
}
function handleChange(event) {
setSearch(event.target.value);
console.log(event.target.value);
}
function handleSubmit(event) {
event.preventDefault();
setQuery(search);
setSearch('');
}
return (
loaded ? (
<div>
<div className="container">
<div className="input-section">
<h1 className="header"> IP Address Tracker</h1>
<form onSubmit={handleSubmit} className="search-form">
<input className="search-input" type="text" placeholder="Search for any IP address or domain" onChange={handleChange} />
<button className="search-button" type="submit"> Go! </button>
</form>
</div>
<div className="result-container">
<Result
heading={"IP Address"}
searchResult={IPdata.ip}
/>
<Result
heading={"Location"}
searchResult={IPdata?.location?.country}
/>
<Result
heading={"Timezone"}
searchResult={"UTC" + IPdata?.location?.timezone}
/>
<Result
heading={"ISP"}
searchResult={IPdata.isp}
/>
</div>
</div>
{IPdata.location && (
<MapContainer
center={[IPdata.location?.lat, IPdata.location?.lng]}
zoom={13}
scrollWheelZoom={true}
>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={[IPdata?.location?.lat, IPdata?.location?.lng]}>
<Popup>Your IP Location</Popup>
</Marker>
</MapContainer>
)
}
</div>) : <p>Loading...</p>
)
}
export default App;
You cannot change the center with state because of this...
Except for its children, MapContainer props are immutable: changing
them after they have been set a first time will have no effect on the
Map instance or its container.
However, I believe it may work if you add a key prop. You can try to see if it works.
<MapContainer
center={[IPdata.location?.lat, IPdata.location?.lng]}
zoom={13}
scrollWheelZoom={true}
key={`${IPdata.location?.lat}${IPdata.location?.lng}`}
>
Updated: There's another solution provided here using setView -> React leaflet center attribute does not change when the center state changes
function ChangeView({ center, zoom }) {
const map = useMap();
map.setView(center, zoom);
return null;
}
function Map({ center, zoom }) {
return (
<div className="map">
<MapContainer center={center} zoom={zoom} scrollWheelZoom={false}>
<ChangeView center={center} zoom={zoom} />
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
</MapContainer>
</div>
);
}
I currently have this map
import React, { useEffect } from "react";
import "./App.css";
import { MapContainer, TileLayer, Marker } from "react-leaflet";
function App() {
useEffect(() => {
console.log("first run");
}, []);
return (
<div className="App">
<div id="mapid">
<MapContainer
style={{ height: "100vh", width: "100vw" }}
center={[51.505, -0.09]}
zoom={13}
scrollWheelZoom={true}
>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={[51.505, -0.09]}></Marker>
<Marker position={[51.490114, -0.09066]}></Marker>
</MapContainer>
</div>
</div>
);
}
export default App;
And i somehow need to find the latitude min, latitude max, longitude min, longitude max
But i cannot find how to do it with hooks / useeffect
After taking the map reference, when the component mounts, you can get the map bounds using map.getBounds(). It contains the current or the updated coordinates of southWest, southEast, northWest, northEast etc.
useEffect(() => {
if (!map) return;
console.log(map.getBounds());
}, [map]);
and if you want to take the new ones after you zoom in or out you can add a zoomend event
useEffect(() => {
if (!map) return;
console.log(map.getBounds());
map.on("zoomend", function () {
console.log(map.getBounds());
});
}, [map]);
Demo
I have a problem with displays icons on google map.
Here is my code:
import React, { Component } from 'react'
import { compose, withProps, withStateHandlers } from 'recompose'
import { withScriptjs, withGoogleMap, GoogleMap, Marker, InfoWindow } from 'react-google-maps'
import MapStyles from './data/MapStyles'
export const Map = compose(
withStateHandlers(() => ({
isOpen: false,
}), {
onToggleOpen: ({ isOpen }) => () => ({
isOpen: !isOpen,
})
}),
withScriptjs,
withGoogleMap
)(props => {
return (
<GoogleMap
defaultZoom={13}
defaultCenter={{ lat: 52.229676, lng: 21.012229 }}
defaultOptions={{ styles: MapStyles }}
mapTypeControl={false}
>{ props.markers.map(marker => {
console.log(marker.location);
<Marker
{...marker}
key={marker.place_id}
position={marker.location}
title={marker.title}
icon={{
url: 'icons/icon.png'
}}
onClick={props.onToggleOpen}
>
{props.isOpen &&
<InfoWindow onCloseClick={props.onToggleOpen}>
<div>Open</div>
</InfoWindow>}
</Marker>
})}
</GoogleMap>
);})
export default Map
Positions for markers are displayed in console by console.log, but they don't display on a map ... I don't know why .... Maybe some of you know, why is this happen ... Here is link to this project on Github: https://github.com/hajczek/Neighborhood---Warsaw-Cultural-Map
Thanks for any hints.
Your missing a return in the map projection -
>{ props.markers.map(marker => {
console.log(marker.location);
<Marker
add a return before <Marker
>{ props.markers.map(marker => {
console.log(marker.location);
return <Marker
Working sample on codesandbox