I use an Array to create a couple of markers in my leaflet map for Photos with Geolocations which works fine:
for (var p of ArrayofData) {
var lat = p.lat;
var lon = p.lon;
var markerLocation = new L.LatLng(lat, lon);
var marker = new L.Marker(markerLocation,{
draggable: 'true',
id: p.Filename
});
mymap.addLayer(marker);
}
to enable users to change their photo location I need them to drag those markers around and then I can read the new location:
marker.on('dragend', function (e) {
// Get position of dropped marker
var latLng = e.target.getLatLng();
console.log ("id:"+e.target.options.id);
console.log ("NewLocation:"+latLng);
});
As all of my markers have the same constructor it seems as if this script only works with the last marker. All others are draggable but do not give back any feedback when released.
Does anybody know, how I can access all of them?
You can do that by adding those drag event handlers inside your for loop.
for (var p of data) {
var lat = p.lat;
var lon = p.lon;
var markerLocation = new L.LatLng(lat, lon);
var marker = new L.Marker(markerLocation,{
draggable: 'true',
id: p.Filename
});
map.addLayer(marker);
marker.on('dragend', function (e) {
// Get position of dropped marker
var latLng = e.target.getLatLng();
console.log ("id:"+e.target.options.id);
console.log ("NewLocation:"+latLng);
});
}
Also I highly recommend that you keep track of your markers by adding them to an array.
var markers = [];
for (var p of data) {
var lat = p.lat;
var lon = p.lon;
var markerLocation = new L.LatLng(lat, lon);
var marker = new L.Marker(markerLocation,{
draggable: 'true',
id: p.Filename
});
map.addLayer(marker);
marker.on('dragend', function (e) {
// Get position of dropped marker
var latLng = e.target.getLatLng();
console.log ("id:"+e.target.options.id);
console.log ("NewLocation:"+latLng);
});
markers.push(marker);
}
Demo
Related
How do I get the value at a specific coordinate of raster using leaflet L.canvasLayer.scalarField, i only can obtain the value when the user "click" on map like in this code:
d3.text("https://ihcantabria.github.io/Leaflet.CanvasLayer.Field/data/Bay_Speed.asc", function (asc) {
var s = L.ScalarField.fromASCIIGrid(asc);
var layer = L.canvasLayer.scalarField(s).addTo(map);
layer.on('click', function(e) {
if (e.value !== null) {
let vector = e.value;
console.log(vector)
}
});
});
I am using Leaflet Map with geocoder (ESRI) and Routing Machine.
I have added two markers, let's say my home and my work
var marker_work = L.marker([50.27, 19.03], { title: 'MyWork'}).addTo(map)
.bindPopup("work").openPopup();
var marker_home = L.marker([50.10, 18.4], { title: 'MyHome'}).addTo(map)
.bindPopup("home").openPopup();
Here is an example fiddle:
https://jsfiddle.net/21nmk8so/1/
How can I add this markers/point as a predefined places for ControlGeocoder?
I want to use them in search and use as a start point / end point for route calculation.
Another example for the same question: how to add custom-fake city with lat/lon and be able to search (find route) to/from that city.
I don't know if this is the best solution but it is working:
Create a custom Geocoder Class which overwrites the geocode function. There you can overwrite the result function and apply suggestions to the result.
L.CustomGeocoder = L.Control.Geocoder.Nominatim.extend({
suggestions: [],
setSuggestions(arr){
this.suggestions = arr;
},
createSuggestionFromMarker(marker){
this.suggestions.push({name: marker.options.title, center: marker.getLatLng()});
},
getResultsOfSuggestions(query){
var results = [];
this.suggestions.forEach((point)=>{
if(point.name.indexOf(query) > -1){
point.center = L.latLng(point.center);
point.bbox = point.center.toBounds(100);
results.push(point);
}
});
return results;
},
geocode(query, resultFnc, context) {
var that = this;
var callback = function(results){
var sugg = that.getResultsOfSuggestions(query);
resultFnc.call(this,sugg.concat(results));
}
L.Control.Geocoder.Nominatim.prototype.geocode.call(that,query, callback, context);
}
})
Then you have to use the new Geocoder Class:
var geocoder = new L.CustomGeocoder({});
var control = L.Routing.control({
waypoints: [],
router: new L.Routing.osrmv1({
language: 'en',
profile: 'car'
}),
geocoder: geocoder
}).addTo(map);
And finally you can add suggestions over markers and theier title option over createSuggestionFromMarker(marker) or setSuggestions(arr):
var suggestions = [
{
name: 'Test Car 1',
center: [50.27, 19.03]
},
{
name: 'Test Car 2',
center: [50.10, 18.4]
}
];
geocoder.setSuggestions(suggestions);
var marker_work = L.marker([50.27, 19.03], { title: 'MyWork'}).addTo(map);
var marker_home = L.marker([50.10, 18.4], { title: 'MyHome'}).addTo(map);
geocoder.createSuggestionFromMarker(marker_work);
geocoder.createSuggestionFromMarker(marker_home);
Update, use marker Ref instead of fix latlng
Change this two function, then the marker is referenced and it always searches from the current position of the marker:
createSuggestionFromMarker(marker){
this.suggestions.push({name: marker.options.title, marker: marker});
},
getResultsOfSuggestions(query){
var results = [];
this.suggestions.forEach((point)=>{
if(point.name.indexOf(query) > -1){
if(point.marker){
point.center = point.marker.getLatLng();
}
point.center = L.latLng(point.center);
point.bbox = point.center.toBounds(100);
results.push(point);
}
});
return results;
},
You can test this in the demo, when you drag the marker
https://jsfiddle.net/falkedesign/hu25jfd1/
How can I get the X and Y of GeolocateControl after it geolocated on the map?
I tried to this like
setTimeout(function(){
var userlocation = geolocate.Position;
var lat = userlocation.latitude;
var lng = userlocation.longitude;
console.log(lat);
}, 3000);
but it is not returning anything. and I am getting this error
Uncaught TypeError: Cannot read property 'coords' of undefined
Code:
let geolocate = new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true,
watchPosition: true
}
});
map.addControl(geolocate);
map.on('load', function(){
geolocate.trigger();
});
setTimeout(function(){
var userlocation = geolocate.Position;
var lat = userlocation.coords.latitude;
var lng = userlocation.coords.longitude;
console.log(lat);
}, 3000);
The Geolocate Control has a geolocate event which fires each time the Geolocation API position update returns successfully. Assuming that geolocate is the variable containing your control instance, your code would look like this:
geolocate.on('geolocate', function (position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
console.log('lat, lng', latitude, longitude);
});
In my Ionic 2 application, I'm able to see my current location on the map, but how can I add the location (longtitude and latitude) to Firebase?
initMap(): Promise<any> {
this.mapInitialised = true;
return new Promise((resolve) => {
Geolocation.getCurrentPosition().then((position) => {
let latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
//let latLng = new google.maps.LatLng(40.713744, -74.009056);
let mapOptions = {
center: latLng,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(this.mapElement, mapOptions);
resolve(true);
google.maps.event.addListener(this.map, 'click', (event) => {
this.clearMarkers();
let geocoder = new google.maps.Geocoder;
let infowindow = new google.maps.InfoWindow;
let distanceToYou = this.getDistanceBetweenPoints(
event.latLng,
position,
'miles'
).toFixed(2);
this.geocodeLatLng(event.latLng,geocoder,infowindow,distanceToYou);
});
});
});
}
I'm able to get the current position of me and if I double click the map I can see the distance between me and the marker.
Yes it's possible. But since double clicking a map zooms it, i'll use press. But it would be better if you set a button on a info window with a "save location" text or something like this to call the saving function.
YOUR HTML
<div #mapID (press)="saveLocation()">
YOUR .TS
import * as firebase from 'firebase';
public lat;
public long;
initMap(): Promise<any> {
this.mapInitialised = true;
return new Promise((resolve) => {
Geolocation.getCurrentPosition().then((position) => {
this.lat = position.coords.latitude;
this.long = position.coords.longitude;
// YOUR CODE CONTINUES HERE...
});
});
});
saveLocation(){
firebase.database().ref('PATH/YOU/WANT/TO/SAVE').update({
lat: this.lat,
long: this.long
}).then(res =>{
// THE LOCATION IS SAVED, DO YOUR STUFF
})
}
Like this you can save you location, use update() instead of set() so you don't subscribe other data.
If you want to retrieve that data just use firebase.database().ref('PATH/YOU'VE/SAVED').once('value', snapshot =>{ // CODE });
Hope it helps
I have list of markers that want to render in the map, but I want it one by one. In first click I want to make new marker. Then when I click to another location, I want my marker to just move to the new latLng not to create another marker. Here is my code:
function (licon, coord, data) {
var self = jQuery(this);
var map = self.data("map");
var latlng = new L.LatLng(coord[0], coord[1]);
//Create Marker
if (licon) {
var leafIcon = L.icon(licon);
console.log(typeof (marker));
if (typeof (marker) === 'undefined') {
var marker = L.marker(latlng, {
icon: leafIcon,
"markerData": data,
draggable: true
});
} else {
console.log('not undefined');
map.removeLayer(marker);
marker = L.marker(latlng, {
icon: leafIcon,
"markerData": data,
draggable: true
});
}
} else {
var marker = L.marker(latlng, {
"markerData": data,
draggable: true
});
}
marker.addTo(map);
return marker;
}
A quick example of the result: http://jsfiddle.net/ve2huzxw/43/
var currentMarker;
map.on("click", function (event) {
if (currentMarker) {
currentMarker.setLatLng(event.latlng);
return;
}
currentMarker = L.marker(event.latlng, {
draggable: true
}).addTo(map).on("click", function () {
event.originalEvent.stopPropagation();
});
});
document.getElementById("done").addEventListener("click", function () {
currentMarker = null;
});
You can also add a smooth transition to show the marker moving to the new position:
if (currentMarker) {
currentMarker._icon.style.transition = "transform 0.3s ease-out";
currentMarker._shadow.style.transition = "transform 0.3s ease-out";
currentMarker.setLatLng(event.latlng);
setTimeout(function () {
currentMarker._icon.style.transition = null;
currentMarker._shadow.style.transition = null;
}, 300);
return;
}
a slightly more consolidated solution some years later.
var currentMarker;
map2.on('click', function(e) {
if (currentMarker){
currentMarker.setLatLng(e.latlng)
} else {
currentMarker = new L.marker(e.latlng).addTo(map2);
};
//console.log('lat, lon: ', e.latlng.lat, e.latlng.lng);
});
leaflet now defaults to smoothly dragging the point over to the new coords.