I want to clear my leaflet map by clicking a button...how to do this... I want to clear all drawed shapes on the map, so the map to be clear
This is my code of the leaflet map in the return statement:
<Map
key={this.state.keyMAP}
style={{ height: "50vh" }}
center={position}
zoom={13}
onClick={this.handleClick}
onCreate={this.onCreate}
onLocationfound={this.handleLocationFound}
>
{/* startDirectly */}
<TileLayer
attribution='© OpenStreetMap contributors'
url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"
layers="NDVI"
// baseUrl="https://services.sentinel-hub.com/ogc/wms/bb1c8a2f-5b11-42bb-8ce4-dbf7f5300663"
/>
<FeatureGroup>
{viewMap && (
<EditControl
position="topleft"
onEdited={this._onEditPath}
onCreated={this.onCreate}
onDeleted={this._onDeleted}
onMounted={this._mounted}
onEditStart={this._onEditStart}
onEditStop={this._onEditStop}
onDeleteStart={this._onDeleteStart}
onDeleteStop={this._onDeleteStop}
draw={{
rectangle: false,
marker: false,
circleMarker: false,
circle: false,
circlemarker: false,
}}
/>
)}
</FeatureGroup>
</Map>
Button:
<button
className="waves-effect waves-light btn"
onClick={this.resetMap}
>
Clear map
</button>
Clear method:
resetMap() {
console.log("Reset");
}
Full code of my component:
https://github.com/SoilViews/SoilViews/blob/master/src/components/dashboard/Dashboard.js
I will propose two solutions so that you can choose whichever suits you best. You just need to create DOM references of your map/feature group in React(depends on the chosen method).
How to create a reference:
On your constructor, insert the following line:
this.mapRef = React.createRef(); // Create a Map reference
OR
this.fgRef = React.createRef(); // Create a Feature group reference
Then at your <Map> or <FeatureGroup> components you should add the following attributes accordingly:
<Map ref={this.mapRef}
key={this.state.keyMAP}
....rest of the code
OR
<FeatureGroup ref={this.fgRef}>
{viewMap && (
....rest of the code
If you choose the map clearing method, you can proceed like this:
function clearMap() {
const map = this.mapRef.current.leafletElement;
map.eachLayer(function (layer) {
map.removeLayer(layer);
});
}
Or, if you choose the Feature Group method:
function clearFeatureGroup() {
const fg = this.fgRef.current.leafletElement;
fg.clearLayers();
}
Finally, in your button you can call the according method:
<button onClick={clearMap}>
Clear!
</button>
OR
<button onClick={clearFeatureGroup}>
Clear!
</button>
Related
im using react-leaflet in Next js but when reloading page shows "window is not defined" even i am using dynamic import with ssr:false,
i saw this question made by others here and tried answers that they offered but didn't work, also tried to make the map mounted after component but again no result,
my code:
function ContactPage() {
const MapWithNoSSR = dynamic(() => import('../Map/Map'), {
ssr: false,
})
return (
<div className={styles.map}>
<MapWithNoSSR/>
</div>
)
}
function Map(){
const [markers, setMarkers]= useState([
{cord:[12.3774729,20.446257]},
{cord:[45.3774729,10.45224757]},
{cord:[40.3774729,15.4364757]},
])
<MapContainer center={[12.374729,22.4464757]} zoom={13} scrollWheelZoom={true} style={{height: "100%", width: "100%",zIndex:'1'}}>
<TileLayer
url={`example.com`}
attribution='Map data © <a>Mapbox</a>'
/>
{markers?.map((element,idx)=>{
return <Marker
position={element?.cord}
draggable={true}
animate={true}
key={idx}
>
<Popup>
Test PopUP
</Popup>
</Marker>
})}
</MapContainer>
}}
}
as you were told in the comment, dynamic () has to go outside of the component or screen you are going to return, e. g.
import dynamic from "next/dynamic"
const MyAwesomeMap = dynamic(() => import("../components/Map/index"), { ssr:false })
export default function inicio() {
return(
<>
<p>Example Map</p>
<MyAwesomeMap />
</>
)
}
Your Map component doesn't return anything
I tried to pass property with <MarkerClusterGroup {...markerclusterOptions}>
by let markerclusterOptions but i think it is not a good way, because it does not work!
in documentation (# React leaflet markercluster v2.0.0):
Since now you don't need to use options prop to pass Leaflet.markercluster option into <MarkerClusterGroup />.
I do not understand how do to that.
import React from 'react';
import MarkerClusterGroup from 'react-leaflet-markercluster';
let markerclusterOptions: {
maxClusterRadius: 10;
spiderfyDistanceMultiplier: 2;
spiderfyOnMaxZoom: true;
showCoverageOnHover: false;
zoomToBoundsOnClick: true;
};
// == Composant
const Map: React.FC<Props> = ({ lights }) => (
<div className="map">
<MapContainer
center={[46.362205, 1.523151]}
zoom={5}
minZoom={2}
>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png?api_key=******"
/>
<SetViewOnClick />
<MarkerClusterGroup {...markerclusterOptions}>{
lights.map((light) => (
<Marker
key={light.id}
position={[light.latitude, light.longitude]}
icon={iconPerson}
>
<Tooltip>
Name: {light.user_description} (I{light.index}.G{light.group})
<br />
Power: {light.power_level} %
<br />
Rf Quality: {light.rfquality}/5
</Tooltip>
</Marker>
))
}
</MarkerClusterGroup>
</MapContainer>
</div>
);
export default Map;
Most probably a typo:
let markerclusterOptions: { // with colon ":" you declare a type
maxClusterRadius: 10;
spiderfyDistanceMultiplier: 2;
spiderfyOnMaxZoom: true;
showCoverageOnHover: false;
zoomToBoundsOnClick: true;
}; // no assignment, value is undefined
Should have been:
let markerclusterOptions = { // with equal you assign a value
maxClusterRadius: 10,
spiderfyDistanceMultiplier: 2,
spiderfyOnMaxZoom: true,
showCoverageOnHover: false,
zoomToBoundsOnClick: true,
};
So I am trying to have an active marker that is different from the rest of the non active marker.
So basically I want something like this.
To display all of the icon I am using the following.
that is displayed inside the map
{parkdata.features.map(park =>(
<Marker key = {park.properties.PARK_ID} position={[
park.geometry.coordinates[1],
park.geometry.coordinates[0]
]}
onClick={()=>{this.selected(park);
The selected function that was intended to be used to change the active icon. But it does not seem to be doing anything
selected(park){
return(
<Marker key = {park.properties.PARK_ID} position={[
park.geometry.coordinates[1],
park.geometry.coordinates[0]
]}
icon= {active}
/>
)
}
UPDATE:
This is what I have now.
SO when I click on one of the markers I want to change to a different icon. For now, it just does not do anything.
The following example demonstrates how to create a markers and update icon property on marker click:
function createIcon(url) {
return new L.Icon({
iconUrl: url,
});
}
function MapExample(props) {
const [selectedIndex, setSelectedIndex] = useState(-1);
function handleClick(e) {
setSelectedIndex(e.target.options.index) //get index via custom marker property
}
function getMarkerIcon(index) {
if(index === selectedIndex)
return createIcon("/bigcity_red.png");
return createIcon("/bigcity_green.png");
}
return (
<Map center={props.center} zoom={props.zoom}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
{props.data.map((item, index) => (
<Marker
key={index}
index={index}
position={item.position}
icon={getMarkerIcon(index)}
onclick={handleClick}
/>
))}
</Map>
);
}
Notes:
icon property for Marker component expects the value of L.Icon type
selectedIndex state is used to keep track of selected Marker (index)
Here is a demo for your reference
I use some markers on react-leaflet map to show various text.
But I can not find a flag for the autoOpen tooltip.
I get (position, children, onOpen, onClose) as available attributes.
render() {
return (
<div className={'ShapeLayer'}>
{
this.shapes.map(shape => {
return (
<Marker key={shape['id']} position={shape['coordinates']} draggable={false} opacity={1}>
<Popup>
<span>{shape['text']}</span>
</Popup>
</Marker>
);
})
}
</div>
)
}
This is done with this code on native leaflet
var marker = L.marker(shapess[i]['coordinates'], {
opacity: 0.01
}).bindTooltip(shapess[i]['text'],
{
permanent: true,
className: "shapesText" + i,
offset: [0, 0],
direction: "center"
}
).openTooltip().addTo(mymap);
How can I do the same on react_leflet
You can use Tooltip instead of a Popup if it's just for text and then use permanent attribute on the Tooltip.
<Marker key={shape['id']} position={shape['coordinates']} draggable={false} opacity={1}>
<Tooltip permanent>
<span>{shape['text']}</span>
</Tooltip>
</Marker>
Here is the source for more examples :
react-leaflet/example/components/tooltip.js
I'd like to add a poly line to my map but can't seem to get it to render on button click. Here is the code I currently have:
<button onClick={
function(){
console.log(asset.past);
var pathLine = new L.Polyline(asset.past, {
color: 'red',
weight: 3,
opacity: 0.5,
smoothFactor: 1
}
);
leafletMap.addLayer(pathLine);}
}
className="btn btn-info eachBtn">Go</button>
Thanks, Ed.
It appears that you're trying to manage the map state outside the context of react-leaflet. I'm not even sure if you're using the react-leaflet package or sort of trying to roll your own react website that happens to have leaflet.
If you are indeed using react-leaflet, you should be maintaining a list of polylines that you want to render in the component's state or a property that is updated and sent by a parent component. Then, in your render function you would iterate over these polylines and render each of them as react-leaflet polylines.
Something like this:
render() {
return (
<Map
center={[51.505, -0.09]}
zoom={13}
>
<TileLayer
attribution='© OpenStreetMap contributors'
url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
/>
{this.state.polylines.map((positions, idx) =>
<Polyline key={`polyline-${idx}`} positions={positions} />
)}
</Map>
);
}
Also, see the example over here of a similar react-leaflet application that adds markers after points are clicked on the map.