Find leaflet id of the latest layer created in Leaflet - javascript

I am adding layers to a layergroup "drawnitems" using the leaflet draw library
drawnItems.addLayer(L.polygon(polygon));
I need to find the leaflet ID of the layer created using the above code immediately upon it's creation. This happens in a loop. I am adding multiple layers.
My goal is to save shapes that have been edited by the user into the DB. These shapes are previously created and then stored in the DB and then rendered on the map. For this I am planning to use leaflet id assigned to each shape and then find the corresponding db entry using some logic in the "draw:edited" event.

Okey to simply get the ID of the latest layer added you can do the following:
for(layer of polyLayers) {
drawnItems.addLayer(layer);
var leafletId = layer._leaflet_id
};
But I think for your approach that would not be the best solution, because leaflet ID are not stable. It would be better to create layer variables dynamically and assign an ID from you database, where the layers are stored. Then you are able to get every layer by it's database ID (e.g. myPolyLayers[idFromDataBase]). Just do:
var myPolyLayers = {};
for(layer of polyLayers) {
var id = Math.floor((Math.random() * 500) + 1); // The ID from the database
myPolyLayers[id] = layer
drawnItems.addLayer(layer);
//var leafletId = layer._leaflet_id
};
console.log(myPolyLayers[id]) // Get the layer with the ID given before
In this snippet, the ID where I choosed a random number should be the ID from you database.

I solved this. I created a "hashmap" between the database id and the leaflet shapes id (leaflet_id) while loading shapes on the map. Then in the "draw:edited" I found the database id of the object edited by the user with the help of the "key" = leaflet_id. Thus, I was able to save changes made by the user in the same database record.

var polygon = new L.Polygon([
[51.51, -0.1],
[51.5, -0.06],
[51.52, -0.03]
]);
polygon.options.id = 1;
drawnItems.addLayer(polygon);

As simple as get _leaflet_id of your latest layer created, for example as you if I am drawing polygons, for example:
let polygon = L.polygon([<my coords>], {color: 'red'});
// Added this way
let layer = polygon.addTo(this.drawElementsLayer);
// or this way (is the same)
this.drawElementsLayer.addLayer(polygon);
console.log(panelPolygon._leaflet_id) // n
>> 47 (in my eample case).

Related

Highlight an existing business on Google Maps API

I have a list of store addresses, and I'm trying to create a map out of it.
Using the Places API I am able to retrieve most of the informations and manually create and place the markers on the map:
const service = new google.maps.places.PlacesService(map);
service.findPlaceFromQuery({
query: '212 Enterprise Dr, Rockaway, Frank Pizza',
fields: ['all']
}, onPlaceFound);
However I'd like to select the original marker instead of overlapping a new one.
That is because I want the user to be able to open the default info window with store phone number, directions and stuff.
I know that I can re-create it, but it feels kinda lame since all the info is already there.
This SO post ask about the same, yet no solution has been found.
Based on the documentation found here, which shows findPlaceFromQuery(), the second parameter of findPlaceFromQuery should be a function where the first argument of that function is an Array of placeResults.
Therefore, after reviewing a link here and here your onPlaceFound function should be looking something like:
function onPlaceFound(placeResultsArray){
const firstResult = placeResultsArray[0], firstIconURL = firstResult.icon;
const latLng = firstResult.geometry.location, lat = latLng.lat(), lng = latLng.lng();
// do stuff with those variables here
}
Of course, that does not select Google's result as a Marker, but now you have the actual icon, and latitude and longitude.

Adding onclick call for mapbox icons

I'm struggling with adding a click event to points on my mapbox map. I'm having to add the source from a backend sql query into a hbs template. I've tried just adding business1 as the source without the for loop but i get an invalid geojson object warning. If i add just 'locations' as the id obviously it gives me a warning that the id already exists on the map.
So how i can add an onclick call for dynamics id's?
How i load the points
business1 = {{{businesses}}}
for(i=0;i<business1.length;i++){
// Add the data to your map as a lyer
map.addLayer({
id: 'locations'+[i],
type: 'symbol',
minzoom: zoomThreshold,
// Add a GeoJSON source containing place coordinates and information.
source: {
type: 'geojson',
data: business1[i]
},
layout: {
'icon-image': 'circle-stroked-15',
'icon-allow-overlap': true,
}
});
}
How the map click is called-with the added [i] just to show what i'm thinking
map.on('click', function(e) {
var features = map.queryRenderedFeatures(e.point, {
layers: ['locations'+[i]] // replace this with the name of the layer
});
if (!features.length) {
return;
}
What else i've tried-but always returns the same location regardless of what is clicked
for(i=0; i<business1.length;i++){
var features = []
var feature = [i]
feature.dataPosition = i;
var clickedNameClicked = names[this.dataPosition]
console.log(clickedNameClicked)
features.push(business1[i]);
}
I definitely don't recommend adding a new source / layer for each business. That will not be performant if you have a bunch of layers, and I think it's adding too much complexity to your on click logic.
I've tried just adding business1 as the source without the for loop but i get an invalid geojson object warning.
This is a strong indication that there's something awry with your business data that you should address before adding it to your map and worrying about click events. I would recommend using a tool like http://geojsonlint.com/ to see what is going on there.
Once you have valid geojson, it will be much easier to add click events to your icons. https://docs.mapbox.com/mapbox-gl-js/example/queryrenderedfeatures-around-point/
⚠️ Disclaimer: I currently work at Mapbox ⚠️

Json to Map Unsing Amcharts

I need to creat a Tunisia map using Amcharts with my json data
Code in my json / id in tunisiaLow
nbre in my json / value in tunisialow
i change in tunisiaLow like my json data but not work
i need samthink like this
pic
pleas help me
this is my code in plunker plnkr.co/edit/6aDJREhcFYSfM5JW99mX?p=preview
The biggest issue with your code is that you modified the AmCharts map JS file in such a way that it completely breaks with the library. The JS files should not be modified unless you know what you're doing and follow the directions on creating your own map files tutorial. Your modified file removes the required id attribute that makes the map function.
Ideally you should modify your data to match the map format, not the other way around. Going by your last ticket, you seem to be unable to change your data, so the solution is the same as the last - remap your data to conform with AmCharts' format.
The original JS/SVG map has a list of IDs for each province. Since your dataset's titles don't exactly match the titles within the original map, you'll want to create a lookup object that uses your titles to link up to the internal map IDs, for example, using your French titles:
var areaDataMapping = {
"TUNIS": "TN-11",
"ARIANA": "TN-12",
"BEN AROUS": "TN-13",
"MANOUBA": "TN-14",
"NABEUL": "TN-21",
"ZAGHOUAN": "TN-22",
"BIZERTE": "TN-23",
"BEJA": "TN-31",
"JENDOUBA": "TN-32",
"KEF": "TN-33",
"SILIANA": "TN-34",
"KAIROUAN": "TN-41",
"KASSERINE": "TN-42",
"SIDI BOUZID": "TN-43",
"SOUSSE": "TN-51",
"MONASTIR": "TN-52",
"MAHDIA": "TN-53",
"SFAX": "TN-61",
"GAFSA": "TN-71",
"TOZEUR": "TN-72",
"KEBILI": "TN-73",
"GABES": "TN-81",
"MEDENINE": "TN-82",
"TATAOUINE": "TN-83"
};
From there, you can remap your parsed JSON file to create the correct area object array with the required properties such as id, title and value and then assign the result to your code:
var remappedAreas = AmCharts.parseJSON( areas ).map(function(area) {
return {
id: areaDataMapping[area.libelleFr],
title: area.libelleAr,
code: area.code,
value: area.nbre
}
});
var map = AmCharts.makeChart("...", {
// ...
"dataProvider": {
// ...
"areas": remappedAreas,
// ...
},
// ...
});
Here's an updated plunkr, which uses the official AmCharts JS for Tunisia instead of your version.

redraw markers and clusters after location was inserted into collection

I have a map where my markers and clusters are rendered with leaflet. I have a collection where I have stored information like latitude/longtitude.
I iterate over the collection like this to insert the markers in
in Template.map.rendered
Locations.find({}).forEach(function(obj){
console.log("Adding: lat " + obj.latitude + " - long " + obj.longtitude);
var m = L.marker([obj.latitude,obj.longtitude]);
markers.addLayer(m);
});
How can I also draw new inserted locations after the template was finished rendering that the map will be live updated?
Exactly the same as you do in your template. If you have a reference to the MarkerCluster layer (i'm assuming markers), just use the addLayer method of the layer:
markers.addLayer(L.Marker([0,0]);
If you want to bulk add markers you can use the method addLayers:
markers.addLayers([
L.Marker([0,0]),
L.Marker([1,1])
]);
MarkerCluster will take care of the rest, you can also animated the new inserts by using animateAddingMarkers in the options when instanciating the MarkerCluster:
new L.MarkerClusterGroup({
'animateAddingMarkers': true
});
animateAddingMarkers: If set to true then adding individual markers to the MarkerClusterGroup after it has been added to the map will add the marker and animate it in to the cluster. Defaults to false as this gives better performance when bulk adding markers. addLayers does not support this, only addLayer with individual Markers.
Check the README.MD on their Github: https://github.com/Leaflet/Leaflet.markercluster

Reload points on a Map in using the Google Maps API v3

I'm trying to reload points on a map based on when someone clicks a button.
I have a couple json objects saved in memory, "data" and "data2". The following code takes the "data2" JSON file and sets it equal to the "data" JSON file and then triggers a map reload event.
dataholder = data
function myFunction() {
data = dataholder
window.data = data2;
google.maps.event.trigger(map, 'resize');
}
Currently, the map won't reload with the new set of data. However, I am not getting any error messages.
There's no map reload event. The resize event, when it comes from a window resize, will at most recalculate the map bounds and reproject the existing features (markers, polylines, polygons). For this case in particular, I don't think that manually triggering the resize event will have any effect.
In second place, you say you have two json files, but your code suggest you instead have two json objects already in memory (meaning you don't need to perform aditional requests to retrieve the value of data2). The rest of the answer will assume that.
If your original collection of markers came from "data", which is a collection of LatLng pairs, and you want to replace the markers for the contents of "data2" the process would be:
1.- Push the markers into an object where you can find them later on
var markers=[];
for(onemarker in data) {
var newmarker=new google.maps.Marker({map: map, position: new google.maps.LatLng({onemarker.lat, onemarker.lng}) });
markers.push(newmarker);
}
2.- When you want to replace the markers, first purge the markers array
while(markers.length) {
var oldmarker=markers.pop();
oldmarker.setMap(null);
};
3.- Fill the markers array with the data from the data2 object
for(onemarker in data2) {
var newmarker=new google.maps.Marker({map: map, position: new google.maps.LatLng({onemarker.lat, onemarker.lng}) });
markers.push(newmarker);
}
For this kind of markers, as for the regular features, there's no instantaneous binding between the object and the underlying data. This is slightly different for the new google.maps.Data() layer for which you can skip the iteration and just feed it a geoJSON array. You still need to have an object to store the current markers, or else you won't have a way to access them when you want to remove them.

Categories

Resources