Leaflet - Creating LayerGroups Dynamically - javascript

Is it possible to create LayerGroups Dynamically? I'm developing an web map that shows the tree species that exists in the parks, an i'm trying to create a LayerGroup for each species so that with a LayerControl i can hide and show certain species, for the sake of testing, i have been creating LayerGroups like this:
l1 = new L.LayerGroup();
//...
l100 = new L.LayerGroup();
And i'm sure that there is a way to do it depending on the number of species that exists, i have tried:
for (var i = 0; i < numberOfSpecies ; i++) {
l[i] = new L.LayerGroup();
}
But this way, i cant do this:
l[0].addLayer(marker);
What is the best way to do something like this?

Yes, you can.
For example:
var layerGroups = {}
for (var i = 0; i < 3; ++i) {
layerGroups[i] = L.layerGroup().addTo(map);
}
for (var i = 0; i < 3; ++i) {
layerGroups[i].addLayer(L.marker([i,i]))
}
You can try it here : https://jsfiddle.net/mckbda9y/6/

Related

adjusting linked indexes for reorganized arrays

I have a table that can be dynamically styled with various colors and a palette of colors that serves as a reference to those colors. When the user has finished coloring, I want to compile the file to JSON. I can fetch the necessary values likewise:
// note _colors is a global variable declared elsewhere
var $rowSelect = $("#rowSelect");
var $colSelect = $("#colSelect");
var $colorBoard = $("#colorBoard");
var $upload = $("#upload");
$upload.on("click", function() {
var numRows = Number($rowSelect.val());
var numCols = Number($colSelect.val());
var pixels = [];
var colors = [];
var comp_colors = [];
var $rows = $colorBoard.children();
for(var i = 0; i < numRows; i++) {
var $cols = $rows.eq(i).children();
for(var ii = 0; ii < numCols; ii++) {
$cell = $cols.eq(ii);
pixels.push(Number($cell.attr("data-colorid")));
}
}
var usedColors = pixels.filter((v, i, a) => a.indexOf(v) === i);
for(var i = 0; i < _colors.length; i++) {
colors.push(_colors[i] ? _colors[i].color.getColor() : null);
if(_colors[i] && usedColors.includes(i) && !comp_colors.includes(colors[i])) comp_colors.push(_colors[i].color.getColor());
}
}
Since colors can be deleted, duplicated, or unused in my UI, I cleaned up my raw color array colors into the comp_colors array. For example, an array of unprocessed colors may look like: [null, "#EF1A1A", null, "#40E255", "#0B1DE3", "#FFFFFF", "#FFFFFF"]. If "#0B1DE3" was not actually present in our pixel array, the cleaned up version would look like: ["#EF1A1A", "#40E255", "#FFFFFF"].
The problem is that cleaning up the color array has offset the indexes that the values of the pixels array were using to reference the colors. For example, using the color situation above, a fetched array of pixels may look like this: [1,3,3,1,5,6,5,1,3,6], but the revised version for the cleaned up color set would be: [0,1,1,0,2,2,2,0,1,0].
What is the most efficient way to correct these values to the appropriate indexes?
I found a concise method, but I don't feel like it is very efficient. I have to iterate through every pixel to achieve this, which can be costly at with large creations. The new list of pixels will be loaded into comp_pixels:
for(var i = 0; i < cells.length; i++) comp_pixels.push(comp_colors.indexOf(colors[pixels[i]]));

How get coordinates from polygons inside a Layer

I have a LayerGroup
var mapLayer = new L.layerGroup();
This is how I add several polygons to this LayerGroup:
var buffered = turf.buffer(polyline, path_alarmweight, 'meters');
bufferedPolygon = L.geoJson(buffered, bufferedOptions).addTo(mapLayer);`
How can I get the coordinates from a single or several polygons which I added to the mapLayer?
First of all you need to get all layers from LayerGroup, use getLayers() function, in documentation. You will get layers in LayerGroup:
var arrayOfLayers = mapLayer.getLayers();
Then you can iterate over arrayOfLayers and for every layer you can get coordinates of polygon with getLatLngs() function. See the reference:
for(var i=0; i < arrayOfLayers.length; i++) {
// first get array of coordinates
var arrayOfPoints = arrayOfLayers[i].getLatLngs();
//then iterate over coordinates
for(var j=0; j < arrayOfPoints.length; j++) {
console.log(arrayOfPoints[j]);
}
}

populate select element based on json

How could I populate a second select element? I've figured out how to do the first one. But how could I do the same for the second depending on which "Make" is selected? I've tried to talk myself through it while taking small steps but I'm thinking this may be too advanced for me.
var cars = '{"USED":[{"name":"Acura","value":"20001","models":[{"name":"CL","value":"20773"},{"name":"ILX","value":"47843"},{"name":"ILX Hybrid","value":"48964"},{"name":"Integra","value":"21266"},{"name":"Legend","value":"21380"},{"name":"MDX","value":"21422"},{"name":"NSX","value":"21685"},{"name":"RDX","value":"21831"},{"name":"RL","value":"21782"},{"name":"RSX","value":"21784"},{"name":"SLX","value":"21879"},{"name":"TL","value":"22237"},{"name":"TSX","value":"22248"},{"name":"Vigor","value":"22362"},{"name":"ZDX","value":"32888"}]},{"name":"Alfa Romeo","value":"20047","models":[{"name":"164","value":"20325"},{"name":"8c Competizione","value":"34963"},{"name":"Spider","value":"22172"}]}';
var carobj = eval ("(" + cars + ")");
var select = document.getElementsByTagName('select')[0];
//print array elements out
for (var i = 0; i < carobj.USED.length; i++) {
var d = carobj.USED[i];
select.options.add(new Option(d.name, i))
};
If I read your question right, you want to populate a second select with the models for the make in the first select. See below for a purely JS approach (with jsfiddle). If possible, I would recommend looking into jQuery, since I would prefer a jQuery solution.
http://jsfiddle.net/m5U8r/1/
var carobj;
window.onload = function () {
var cars = '{"USED":[{"name":"Acura","value":"20001","models":[{"name":"CL","value":"20773"},{"name":"ILX","value":"47843"},{"name":"ILX Hybrid","value":"48964"},{"name":"Integra","value":"21266"},{"name":"Legend","value":"21380"},{"name":"MDX","value":"21422"},{"name":"NSX","value":"21685"},{"name":"RDX","value":"21831"},{"name":"RL","value":"21782"},{"name":"RSX","value":"21784"},{"name":"SLX","value":"21879"},{"name":"TL","value":"22237"},{"name":"TSX","value":"22248"},{"name":"Vigor","value":"22362"},{"name":"ZDX","value":"32888"}]},{"name":"Alfa Romeo","value":"20047","models":[{"name":"164","value":"20325"},{"name":"8c Competizione","value":"34963"}, {"name":"Spider","value":"22172"}]}]}';
carobj = eval ("(" + cars + ")");
var makes = document.getElementById('make');
for (var i = 0; i < carobj.USED.length; i++) {
var d = carobj.USED[i];
makes.options.add(new Option(d.name, i));
}
makes.onchange = getModels;
getModels();
}
// add models based on make
function getModels () {
var makes = document.getElementById('make');
var make = makes.options[makes.selectedIndex].text;
for (var i = 0; i < carobj.USED.length; i++) {
if (carobj.USED[i].name == make) {
var models = document.getElementById('model');
models.options.length = 0;
for (var j= 0; j < carobj.USED[i].models.length; j++) {
var model = carobj.USED[i].models[j];
models.options.add(new Option(model.name, j));
}
break;
}
}
}
I would also recommend looking into safer JSON parsing. There is a security risk in using eval if it runs on any user input. You could look into JSON.org and their json2.js. Or if you want to use jQuery: parseJSON. Below is the jQuery version:
jQuery.parseJSON(jsonString);
JSON parsing tips from: Safely turning a JSON string into an object.

Google Maps MarkerClusterer v3 Return Cluster of Marker

I am currently using the Google Maps MarkerClusterer v3 (http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/docs/reference.html) and have been very impressed with the functionality so far.
However, I now wish to add in an additional function to my map. When a user hovers over a list of the markers, the marker image is changed. This works great when the markers aren't clustered, but since I am also using the Clusterer, I need to be able to return the Cluster to which a specific marker belongs.
Does anyone know if this is possible? I checked the API documents, but couldn't find a method to return an array of the Clusters.
Essentially, here is a pseudo-code of what I need to do:
function changeClusterIcon(the_marker)
{
var clusters = _CLUSTERER.getClusters();
var clusters_length = clusters.length;
var marker_pos = the_marker.getPosition().toString();
for(var i = 0; i < clusters_length; i++)
{
var this_cluster = clusters[i];
var the_markers = this_cluster.markers.length;
for(var j = 0; j < the_markers; j++)
{
var this_marker = this_cluster.markers[i];
if(this_marker.getPosition().toString() == marker_pos)
{
return this_cluster;
}
}
}
return false;
}
The MarkerClusterer library does not provide a way to retrieve the clusters. But there is an enhanced version of the library, MarkerClustererPlus, which provides more capabilities. Using MarkerClustererPlusapi-doc, you may use the MarkerClusterer.getClusters() function to retrieve an Array of the Cluster class instances. Then, you may use the Cluster.getMarkers() function to retrieve an Array of the markers that are within that Cluster. And with that, you should have what you need to move forward.
Your function is almost correct, here the proper version:
function changeClusterIcon(the_marker)
{
var clusters = _CLUSTERER.getClusters();
var clusters_length = clusters.length;
var marker_pos = the_marker.getPosition().toString();
for(var i = 0; i < clusters_length; i++)
{
var this_cluster = clusters[i];
var the_markers = this_cluster.markers_.length;
for(var j = 0; j < the_markers; j++)
{
var this_marker = this_cluster.markers_[j];
if(this_marker.getPosition().toString() == marker_pos)
{
return this_cluster;
}
}
}
return false;
}
So the markers property should be called as markers_ and the second foreach uses j instead of i.

Sort computed areas

I have a google maps and I get all markers that are close a locaton (lat, lng).
This point is OK.
Now i want to sort theses markers, like in SQL we can do a "order by distance ASC" for example.
I saw in javascript have a method call sort() which can sort some numbers asc or desc for example.
markers have some informations: name, title, gender, city, postcode ...
my code:
var nbMeters = 50000;
for (var i = 0; i < markers.length; i++) {
var myMarker = markers[i];
coord2 = new google.maps.LatLng(myMarker.lat, myMarker.lng);
var distance = google.maps.geometry.spherical.computeDistanceBetween(coords, coords2);
if(distance <= nbMeters) {
alert(myMarker.name);
//OK my marker is close the variable coords, good !
//But how to know which marker is the closer, which is the second, the third ... and the less closer ??
}
}
Have you an idea?
Maybe try sth like this:
for (var i = 0; i < markers.length; i++) {
var myMarker = markers[i];
coord2 = new google.maps.LatLng(myMarker.lat, myMarker.lng);
var distance = google.maps.geometry.spherical.computeDistanceBetween(coords, coords2);
markers[i].distance = distance;
}
function sortMarkers(marker1, marker2) {
return marker1.distance - marker2.distance;
}
markers.sort(sortMarkers);
It's untested and based on http://www.w3schools.com/jsref/jsref_sort.asp

Categories