I created a function that displays a marker on the map once geolocated, and the display does not center automatically.
What's the parameters for auto center my marker ?
I think this proble in on the getCenter.
import { useState} from 'react';
import { useMap } from "react-leaflet";
import L from "leaflet";
import icon from "./iconPosition";
export default function LocationMarker() {
const map = useMap();
let [currentPosition, setCurrentPosition] = useState([0, 0]);
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
setCurrentPosition([position.coords.latitude, position.coords.longitude]);
});
let latlng = currentPosition;
L.marker(latlng, { icon })
.addTo(map)
.bindPopup("Vous êtes ici")
.openPopup();
map.getCenter();
map.getZoom();
}
return (null)
};
You need to set the center and not to get the current center.
Replace
map.getCenter();
map.getZoom();
with
map.panTo(latlng)
Related
I have a collection of latlng objects which also have elevation data. I'm mapping over this array and trying to pass that latlng object as a prop to this component i.e. <LeafletReverseGeocoding /> I created. What I want is to take that latlng I passed in and have the .reverse return the closet street near that latlng object. As some of those coordinates originally fall on buildings or non streets.
My hope is the elevation should be about the same to the original latlng.
In Marker component:
{topographyData.map((topoObject, index) => {
console.log("topoObject ", topoObject);
return (
<LeafletReverseGeocoding latlng={topoObject.latlng} key={index} />
);
})}
I'm following the docs here
Code for LeafletReverseGeocoding component:
import L from "leaflet";
import { useEffect } from "react";
import { useMap } from "react-leaflet";
import "leaflet-control-geocoder/dist/Control.Geocoder.js";
export function LeafletReverseGeocoding({ latlng }) {
const map = useMap();
console.log("latlng ", latlng);
useEffect(() => {
var geocoder = L.Control.Geocoder.nominatim();
let marker;
console.log("geocoder ", geocoder);
map.on("load", () => {
geocoder.reverse(
latlng,
map.options.crs.scale(map.getZoom()),
(results) => {
var r = results[0];
if (r) {
if (marker) {
marker
.setLatLng(r.center)
.setPopupContent(r.html || r.name)
.openPopup();
} else {
marker = L.marker(r.center)
.bindPopup(r.name)
.addTo(map)
.openPopup();
}
}
}
);
});
}, []);
return null;
}
Following this yields no markers. What am I missing.
I am trying to draw about 50K points with the leaflet Marker method and it's impossible du the time rendering and ram needed.
The new method I saw is to use Leaflet-canvas to draw point on-screen ' not in the DOM.
How can I perform this in React leaflet 3.X.
I tried
https://www.npmjs.com/package/react-leaflet-canvas-markers
But it doesn't support the V3 of the leaflet.
Any suggestion?
install and import the library npm i leaflet-canvas-marker
Create a custom component and use a useEffect that will mimic the behavior of vanilla leaflet example
import { useEffect } from "react";
import { useMap } from "react-leaflet";
import "leaflet-canvas-marker";
import L from "leaflet";
export default function LeafletCanvasMarker() {
const map = useMap();
useEffect(() => {
if (!map) return;
var ciLayer = L.canvasIconLayer({}).addTo(map);
ciLayer.addOnClickListener(function (e, data) {
console.log(data);
});
ciLayer.addOnHoverListener(function (e, data) {
console.log(data[0].data._leaflet_id);
});
var icon = L.icon({
iconUrl: "https://unpkg.com/leaflet#1.7.1/dist/images/marker-icon.png",
iconSize: [20, 18],
iconAnchor: [10, 9],
});
var markers = [];
for (var i = 0; i < 50000; i++) {
var marker = L.marker(
[58.5578 + Math.random() * 1.8, 29.0087 + Math.random() * 3.6],
{ icon: icon }
).bindPopup("I Am " + i);
markers.push(marker);
}
ciLayer.addLayers(markers);
}, [map]);
return null;
}
Include your custom component as a MapContainer child
<MapContainer center={position} zoom={10} style={{ height: "100vh" }}>
<TileLayer
attribution='© OpenStreetMap contributors'
url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
/>
<LeafletCanvasMarker />
</MapContainer>
You should get a result similar to the following picture:
I have this code that changes the opacity of the marker when clicked.
var z3_ore_a2 = L.marker(map.unproject([424, 3386], map.getMaxZoom()), {icon: lapis_icon}).bindTooltip("
<b>x4</b>", {className: 'map_tooltip2', permanent: true, direction: 'center', offset:
L.point(15,2)}).openTooltip().on('click', oreOnClick);
function oreOnClick(e)
{
var oremarker = e.target;
if(oremarker.options.opacity === 1){
oremarker.setOpacity(0.3);
} else {
oremarker.setOpacity(1);
}
}
I wanted to do the same thing on my tooltip, but this code only changes the marker and not the tooltip, how can I achieve this?
You need to set the opacity for the tooltip too. You can access the tooltip object over the marker marker.getTooltip()
function oreOnClick(e){
var oremarker = e.target;
if(oremarker.options.opacity === 1){
oremarker.setOpacity(0.3);
oremarker.getTooltip().setOpacity(0.3);
} else {
oremarker.setOpacity(1);
oremarker.getTooltip().setOpacity(1);
}
}
I am creating a map to track user position, i am using #geolocation plugin and showing map using:
<script src="https://maps.googleapis.com/maps/api/js?key=API_KEYscript>
Currently marker is being displayed and on watchposition marker is placing multiple times and isn’t removing last placed marker.
import { Component, ViewChild, ElementRef } from '#angular/core';
import { Geolocation, GeolocationOptions, Geoposition, PositionError } from '#ionic-native/geolocation';
declare var google;
#Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
geolocation = Geolocation;
options: GeolocationOptions;
currentPos: Geoposition;
#ViewChild('map', { static: false }) mapElement: ElementRef;
map: any;
constructor() { }
ionViewDidEnter() {
this.getUserPosition();
}
getUserPosition() {
this.options = {
enableHighAccuracy: false
};
//get location
this.geolocation.getCurrentPosition(this.options).then((pos: Geoposition) => {
this.currentPos = pos;
console.log(pos);
//add map
let latLng = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);
let mapOptions = {
center: latLng,
zoom: 18,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
this.addMarker(latLng);
}, (err: PositionError) => {
console.log("error : " + err.message);
})
let subscription = this.geolocation.watchPosition().subscribe(position =>{
let userPosition = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
this.addMarker(userPosition);
})
}
addMarker(position) {
let marker = new google.maps.Marker({
map: this.map,
animation: google.maps.Animation.DROP,
position: position
});
let content = "<p>This is your current position !</p>";
let infoWindow = new google.maps.InfoWindow({
content: content
});
google.maps.event.addListener(marker, 'click', () => {
infoWindow.open(this.map, marker);
});
}
}
I want to remove last marker before placing another one.
Thank you.
I can't seem to figure out how to properly update the coords of individual markers after storing them in the state. How it works currently is that when you click somewhere on the map, it adds a marker and stores its initial position in the state (in markerData) which is then displayed on the map through a map function. You can move the individual markers around but I'm having difficulty figuring out a possible solution to updating the specific markers position so that eventually I can send and store the marker information in the back end.
Here is my current code.
import React, { Component } from 'react';
import { ImageOverlay, Map, Marker, Popup } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import 'leaflet/dist/leaflet.js';
import L from 'leaflet';
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});
export default class CustomMapExample extends Component {
constructor(props) {
super(props);
this.state = {
center: {
lat: 512,
lng: 1024,
},
zoom: 1,
draggable: true,
dimensions: [1024, 2048],
markerData: [],
};
}
toggleDraggable = () => {
this.setState({ draggable: !this.state.draggable })
}
addMarker = (event) => {
const {markerData} = this.state
const coords = event.latlng
markerData.push(coords)
this.setState({markerData})
}
updateMarker = (event) => {
console.log(event)
}
render () {
const boundOrigin = [0, 0];
const bounds = [boundOrigin, this.state.dimensions];
const position = [this.state.center.lat, this.state.center.lng]
return (
<div>
<Map
id="map"
crs={L.CRS.Simple}
minZoom={-1}
bounds={bounds}
center={position}
zoom={this.state.zoom}
onClick={this.addMarker}
>
<ImageOverlay
url='http://www.online-tabletop.com/wp-content/uploads/2017/01/tutoriala.jpg'
bounds={bounds}
/>
{this.state.markerData.map((element, index) =>
<Marker
key={index}
position={element}
draggable={this.state.draggable}
onDragend={this.updateMarker}
>
<Popup>
<span onClick={this.toggleDraggable}>
{this.state.draggable ? `Hello` : 'MARKER FIXED'}
</span>
</Popup>
</Marker>
)}
</Map>
</div>
);
}
}
Since Marker accepts options object as a second parameter, marker index could be introduced to reference which marker is getting updated:
<Marker
key={index}
marker_index={index}
position={element}
draggable={this.state.draggable}
onDragend={this.updateMarker}
/>
And then markerData state could be updated like this once the marker is dragged:
updateMarker = event => {
const latLng = event.target.getLatLng(); //get updated marker LatLng
const markerIndex = event.target.options.marker_index; //get marker index
//update
this.setState(prevState => {
const markerData = [...prevState.markerData];
markerData[markerIndex] = latLng;
return { markerData: markerData };
});
};
Demo