is there a better way to load 1000 markers to the react leaflet map. it takes a while
useEffect(() => {
//get Marker coordinates from db
setMarkerData(data)
}, []);
<Map
center={[0,0]}
maxZoom={18} //shows map
minZoom={3}
id="map"
zoomControl={false}
ref={(e) => {
setMapInstance(e);
}}>
<MarkerClusterGroup>
{MarkerData.map((marker, index) => {
const post = [marker.latitude, marker.longitude];
return (
<Marker
key={index}
position={post}
data={marker}
<Popup>
<strong>{marker.title}</strong>
</Popup>
</Marker>
I am trying to get display the markers on the map with the coordinates fetched from the database. Would it be better to periodically fetch a number of markers at X interval?
Related
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'm using react-leaflet. to show the map in my react app. I'm also showing marker on the map too. The problem is the zoom level is not appropriate because sometimes the marker might be quite near to each other and sometimes they will be very far apart. Is there any way to set the zoom level depending on the distance of the markers so that the user can see all the markers at once?
Here is my code
<Map center={center} maxZoom={9} zoom={5}>
<MarkerClusterGroup showCoverageOnHover={false}>
{
markers.map(({fillColor, position, id}) =>
<CircleMarker fillColor={fillColor} color={darken(0.1, fillColor)} radius={10} fillOpacity={1} key={id} center={position} onClick={this.onClick} />
}
</MarkerClusterGroup>
</Map>
P.S: My react-leaflet version is 2.4.0
Assuming MarkerClusterGroup is a component from react-leaflet-markercluster package, the following example demonstartes how to auto-zoom to cover visible markers:
function CustomLayer(props) {
const groupRef = useRef(null);
const { markers } = props;
const mapContext = useLeaflet();
const { map} = mapContext; //get map instance
useEffect(() => {
const group = groupRef.current.leafletElement; //get leaflet.markercluster instance
map.fitBounds(group.getBounds()); //zoom to cover visible markers
}, []);
return (
<MarkerClusterGroup ref={groupRef} showCoverageOnHover={false}>
{markers.map(({ fillColor, position, id }) => (
<CircleMarker
fillColor={fillColor}
radius={10}
fillOpacity={1}
key={id}
center={position}
/>
))}
</MarkerClusterGroup>
);
}
Usage
function MapExample(props) {
const { markers, center } = props;
return (
<Map center={center} maxZoom={9} zoom={5}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
<CustomLayer markers={markers} />
</Map>
);
}
I have custom markers being rendered to my map and do so exactly as I want. I'm using Custom Marker which is a View, Image, and then text specific to an event over the image.
For some reason using a custom marker view is blocking the onPress on the Marker component.
I've tested the onPress event as similiar to below for testing:
<Marker onPress={() => {console.log('Pressed')}}> ... but only logs the press message when I remove my custom marker view inside the Marker component.
Is there a reason why the custom marker view would be stopping the onPress? How do I get around this and fire an onPress event for a custom marker?
Added full code below for better look. Right now it is working but only because I am using the onSelect event for iOS. The onPress works the way it is for Android but not iOS.
<MapView
style={styles.map}
ref={ map => {this.map = map }}
region={this.state.region}
onRegionChangeComplete={this.onRegionChange}
rotateEnabled={false}
loadingEnabled={true}
>
{matches.map((marker, index) => {
return (
<MapMarker
key={index}
mapMarker={marker}
handlePress={() => {
this.map.animateToRegion({
latitude: marker.location.latlng.latitude,
longitude: marker.location.latlng.longitude
}, 100)
}}
/>
)
})}
</MapView>
MapMarker.js
render() {
const { mapMarker } = this.props;
return (
<Marker
ref={(ref) => {this.markerRef = ref; }}
coordinate={mapMarker.location.latlng}
title={mapMarker.location.streetName}
stopPropagation={true}
pointerEvents='auto'
onPress={() => console.log('pressed')}
onSelect={() => {
this.props.handlePress();
}}
>
<CustomMapMarker
gameType={mapMarker.matchType}
isSanctioned={mapMarker.isSanctioned}
startDate={mapMarker.startAt}
/>
<Callout style={styles.customCallout}>
<CustomMarkerCallout markerInfo={mapMarker} />
</Callout>
</Marker>
);
}
Fixed the issue by adding onSelect which is iOS specific. The onPress was only working for Android so don't know if this is the right answer but is working for me as of now.
Im using "google-maps-react" and trying to add new markers to my map with clicks.
I currently manage to console log the specific latLng, but cant seem to make a new one. I'm pretty new to React.
My onMapClick works with finding the latitude and longitude. But I think I need to add the position to an array and then use that one to update the map. Might be wrong
onMapClick = (map,maps,e) => {
const { latLng } = e;
const latitude = e.latLng.lat();
const longitude = e.latLng.lng();
console.log(latitude + ", " + longitude);
var marker = new window.google.maps.Marker({
position: e.latLng,
setMap: map,
});
}
The solution Im currently on is that I just hardcoded some Markers in my render() with the location of array in Marker
<Marker
onClick={this.onMarkerClick}
name={storedLocations[0]}
position={{lat:listLatitude[0], lan:listLongitude[0]}}
/>
My InfoWindow is:
<InfoWindow
marker={this.state.activeMarker}
visible={this.state.showingInfoWindow}
onClose={this.onClose}
>
<div>
<h4>{this.state.selectedPlace.name}</h4>
</div>
</InfoWindow>
</Map>
My onMapClick works with finding the latitude and longitude. But I
think I need to add the position to an array and then use that one to
update the map.
That's indeed would the React way but instead of instantiating markers via Google Maps API, consider to keep the data (marker locations) via state and React will do the rest like this:
class MapContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
locations: []
};
this.handleMapClick = this.handleMapClick.bind(this);
}
handleMapClick = (ref, map, ev) => {
const location = ev.latLng;
this.setState(prevState => ({
locations: [...prevState.locations, location]
}));
map.panTo(location);
};
render() {
return (
<div className="map-container">
<Map
google={this.props.google}
className={"map"}
zoom={this.props.zoom}
initialCenter={this.props.center}
onClick={this.handleMapClick}
>
{this.state.locations.map((location, i) => {
return (
<Marker
key={i}
position={{ lat: location.lat(), lng: location.lng() }}
/>
);
})}
</Map>
</div>
);
}
}
Explanation:
locations state is used to track all the locations once the map is clicked
locations state is passed to Marker component to render markers
The next step could be to introduce a separate component for markers list, Thinking in React tells about components the follows:
One such technique is the single responsibility principle, that is, a
component should ideally only do one thing. If it ends up growing, it
should be decomposed into smaller subcomponents.
const MarkersList = props => {
const { locations, ...markerProps } = props;
return (
<span>
{locations.map((location, i) => {
return (
<Marker
key={i}
{...markerProps}
position={{ lat: location.lat(), lng: location.lng() }}
/>
);
})}
</span>
);
};
Here is a demo which demonstrates how to add a makers on map click via google-maps-react library
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