Leaflet-Draw: Get polygon latLng in 'draw:editvertex' event - leaflet

When a draw:editvertex event fires, how can I get information about the polygon which triggered it?
this.map.on('draw:editvertex', function (e) { debugger;
var layers = e.layers;
// I want to get current polygon latLng here
}.bind(this));

This approach works for me (but doesn't feel like best practice) –
In my draw:editvertex handler I loop through the target._layers and look for the edited property:
map.on('draw:editvertex', function(e) {
for (thisLayer in e.target._layers) {
if (e.target._layers.hasOwnProperty(thisLayer)) {
if (e.target._layers[thisLayer].hasOwnProperty("edited")) {
console.log("we think we found the polygon?");
console.log(e.target._layers[thisLayer]);
// the updated Polygon array points are here:
newPolyLatLngArray = e.target._layers[thisLayer].editing.latlngs[0];
}
}
};
});
...like I said, this doesn't feel Awesome, but it is working for me so far.

There are not only layers in e, but also the target layer poly can be approached easily.
map.on('draw:editvertex', function (e) {
var poly = e.poly;
var latlngs = poly.getLatLngs(); // here the polygon latlngs
});

Related

Changing instance of Feature on click

Im trying to find a way to change the instance of a Leaflet geoJson Feature after it is added to the map.
This is what I want to achieve:
Importing data with L.GeoJson and I am using pointToLayer to change the marker to L.CircleMarker
Now I want
layer.on('click', function (e) {
e.target //Do something here to change it from L.CircleMarker to L.Marker
});
Any idea how to achieve this?
var group = L.geoJSON(); // Your geojson group on importing
layer.on('click', function (e) {
var circlemarker = e.target //Do something here to change it from L.CircleMarker to L.Marker
var marker = L.marker(circlemarker.getLatLng()).addTo(group);
marker.feature = circlemarker.feature
circlemarker.removeFrom(group)
// Then add the same events to the layer as in pointToLayer
});

Toggle geojson layer interactivity

First of all, since it's my first question, I'm sorry if I make any mistakes.
I'd like to "deactivate" a Geojson Layer, composed by a feature collection with many polygons (or lines). I have seen how to create it with the option interactive = yes or interactive = no, but I can't find out how to toggle this dynamically.
Thanks in advance.
EDIT: last thing I tried was this:
var onEachFeature = function(feature, layer) {
function onmouseover(e) {
var layer = e.target;
var activeLayer = ___get_active_layergroup();
if (activeLayer === null){
layer.setStyle({
cursor: 'move'
});
} else if (activeLayer.hasLayer(layer)){
layer.setStyle({
cursor: 'pointer'
});
} else {
layer.setStyle({
cursor: 'move'
});
}
}
function onmouseout(e) {
}
return {
mouseover: onmouseover,
mouseout: onmouseout
}
}
And I put that function in the layer initialization.
___get_active_layergroup is accesible in the context.
EDIT2:
It works if instead of setStyle I use this:
var element = layer.getElement();
if (element.classList.contains("leaflet-interactive")) {
element.classList.remove("leaflet-interactive")
}
But I don't really like how it works. I can see the pointer while I'm moving the mouse blinking (because it takes a few milliseconds process the mouseover I think).

Getting the bounds of loaded tile of leaflet

Using leaflet is there any way I can get the bounds (NorthEast, SouthWest) of a loaded tile? I want to request the server to load the markers only for a particular tile which is loaded, so that when user is panning/dragging the map he can easily see the new markers on new area.
What you really want to do is a subclass of L.GridLayer. This will allow fine control over loaded/unloaded tiles, and is the best way to use the private L.GridLayer._tileCoordsToBounds() method.
With some basic handling of loaded markers, it should look like:
L.GridLayer.MarkerLoader = L.GridLayer.extend({
onAdd: function(map){
// Add a LayerGroup to the map, to hold the markers
this._markerGroup = L.layerGroup().addTo(map);
L.GridLayer.prototype.onAdd.call(this, map);
// Create a tilekey index of markers
this._markerIndex = {};
},
onRemove: function(map){
this._markergroup.removeFrom(map);
L.GridLayer.prototype.onRemove.call(this, map);
};
createTile: function(coords, done) {
var tileBounds = this._tileCoordsToBounds(coords);
var tileKey = this._tileCoordsToKey(coords);
var url = ...; // Compute right url using tileBounds & coords.z
fetch(url).then(function(res){
if (!key in this._markerIndex) { this._markerIndex[key] = []; }
// unpack marker data from result, instantiate markers
// Loop as appropiate
this._markerGroup.addLayer(marker);
this._markerIndex[key] = marker;
done(); // Signal that the tile has been loaded successfully
});
},
_removeTile: function (key) {
for (var i in this._markerIndex[key]) {
this._markerGroup.remove(this._markerIndex[key][i]);
}
L.GridLayer.prototype._removeTile.call(this, key);
}
});
Please note that zooming might be a source of bugs and graphical glitches (markers being removed because a tile unloads, before the markers at the new zoom level are loaded). Beware of that.

Leaflet: Removing markers from map

I load some lat / lon info, then use it to build a polyline.
I then want to add a marker at each of the polyline vertices that will show when the polyline is clicked.
The vertices should disappear if a different (or the same) polyline is clicked.
The code below creates the polyline and the vertex markers.
But the vertex markers do not ever disappear.
I've tried to do this several ways with the same result. I've tried storing the vertex markers in an array and adding them directly to the map, then map.removeLayer'ing them. That doesn't work either. Nor does it work if I use an L.featureGroup instead of a layerGroup.
Clearly I've missed the point somewhere as to how markers can be removed. Could someone point me at the error in my methodology?
// trackMarkersVisible is a global L.layerGroup
// success is a callback from an ajax that fetches trackData, an array f lat/lon pairs
success: function (trackData) {
// build an array of latLng's
points = buildTrackPointSet(trackData, marker.deviceID);
var newTrack = L.polyline(
points, {
color: colors[colorIndex],
weight: 6,
clickable: true
}
);
$(newTrack).on("click", function () {
trackMarkersVisible.clearLayers();
$.each(points, function(idx, val) {
var tm = new L.Marker(val);
trackMarkersVisible.addLayer(tm);
});
map.addLayer(trackMarkersVisible);
});
}
Without a JSFiddle or Plunker it's hard to say because i'm not sure what behaviour your getting but using the clearLayers() method of L.LayerGroup should remove all layers from that group. I would check in the onclick handler if the group already has layers: group.getLayers().length === 0 If the group is empty, add the markers, if the group has layers use clearLayers. Example in code:
polyline.on('click', function (e) {
if (group.getLayers().length === 0) {
e.target._latlngs.forEach(function (latlng) {
group.addLayer(L.marker(latlng));
});
} else {
group.clearLayers();
}
});
This works for me, see the example on Plunker: http://plnkr.co/edit/7IPHrO?p=preview
FYI: an instance of L.Polyline is always clickable by default so you can leave out the clickable: true

Adding CartoDb layer to Leaflet Layer Control

I'm trying to toggle the display of a CartoDb layer on a Leaflet map. I've been able to load the layer using this code:
var layerUrl = 'http://ronh-aagis.cartodb.com/api/v1/viz/rotaryclubs_geo2/viz.json';
var clubPts = cartodb.createLayer(map, layerUrl, {
// The ST_AsGeoJSON(ST_Simplify(the_geom,.01)) as geometry will store a simplified GeoJSON representation of each polygon as an attribute we can pick up on hover
query: 'select *, ST_AsGeoJSON(the_geom) as geometry from {{table_name}}',
interactivity: 'cartodb_id, geometry'
})
.on('done', function(layer) {
map.addLayer(layer);
layer.on('featureOver', function(e, pos, latlng, data) {
$('.leaflet-container').css('cursor','pointer');
if (data.cartodb_id != point.cartodb_id) {
drawHoverPoint(data);
}
cartodb.log.log(pos, data);
});
layer.on('featureOut', function(e, pos, latlng, data) {
$('.leaflet-container').css('cursor','default')
removePoint();
});
layer.on('error', function(err) {
cartodb.log.log('error: ' + err);
});
}).on('error', function() {
cartodb.log.log("some error occurred");
});
Yet when I try to add this layer to a Layer Control:
var clubs = new L.LayerGroup();
clubs.addLayer(clubPts);
I get an "Uncaught TypeError: Object # has no method 'onAdd'" error.
Any thoughts? Thanks!
A great way to reduce complexity and get up to speed quickly here would be using an already-built Leaflet plugin, like Vector Layers, that has built-in CartoDB support already. Take a look at the demo here. http://jasonsanford.github.io/leaflet-vector-layers/demos/cartodb/