Leaflet - Event on tiles loading - javascript

I am currently developing a map-based application and need a way to get notified when Leaflet is pulling tiles from the TileProvider (which, in my case, is MapBox). I read the Leaflet documentation, especially the part with the TileLayer. Currently, I am using the following code to attach a tileload handler:
map.eachLayer(function (layer) {
layer.on('tileload', function(e) {
console.log(e);
});
});
Is there a better way to get the TileLayer of the current map? One problem with this approach is that I hook the handler to all layers (although only TileLayers will raise events, it is unclean to hook it too all layers). Or can I attach the handler directly to the map instance somehow?
Update
I initialize the map with the following MapBox code snippet:
map = L.mapbox.map( element, '...', mapOptions );
This automatically creates a TileLayer (and several other layers), attaches them to the map object and returns this object for later use.

Why not use tileload event directly on the tile layer, like this:
//create a variable to store the tilelayer
var osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
//add the tileload event directly to that variable
osm.on('tileload', function (e) {
console.log(e);
});

If you've got a lot of L.mapbox.TileLayer instances and you don't want to add the eventhandler manually to each instance like Alexandru Pufan suggests in his answer you could still use a loop and Object's instanceof method:
map.eachLayer(function (layer) {
if (layer instanceof L.mapbox.TileLayer) {
layer.on('tileload', function(e) {
console.log(e);
});
}
});
After reading your comment on Alexandru's answer i'm guessing you only have one layer, then it would be best to add it manually to the instance, which is possible with L.mapbox.TileLayer like this:
var layer = L.mapbox.tileLayer(YOUR MAP ID);
layer.on('tileload', function(e) {
console.log(e);
});
var map = L.mapbox.map('mapbox', null, {
'center': [0, 0],
'zoom': 0,
'layers': [layer]
});

Related

How do I simply get the current geolocation using leaflet without events?

I've read the leaflet documentation fairly in depth and I can't find a simple answer to my question.
First some context:
I've created a new map and centred it at the current location and added a listener for location found.
var map = L.map('map', {zoomControl: false}).fitWorld();
L.tileLayer('https://api.mapbox.com/styles/v1/mapbox/outdoors-v9/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1IjoiZG9ucZhc3o3ODMifQ.3-x6nnTgePEK0ERPllV7oQ', {
maxZoom: 20
}).addTo(map);
map.locate({setView: true, watch: true, maxZoom: 17});
map.on('locationfound', onLocationFound);
I now want to create a marker at the current location e.g.
marker = L.marker(map.getLatLong);
marker.addTo(map);
This is to be done outwith the onLocationFound() function as I want to create it only once and then use the locationfound event to have the marker move using marker.setLatLng().
How am I able to use leaflet to get the current LatLong? Does it have a simple alternative to the HTML5 Geolocation API?
I've tried map.getCenter but it returns (0,0)
This is to be done out with the onLocationFound() function as I want to create it only once
In that case, use map.once() instead of map.on(). As you can read in the documentation, once() is the same as on() but only runs on the first event of that kind.
and then use the locationfound event to have the marker move using marker.setLatLng().
In that case, then check if the marker is created, create if it's not, or move it if it is. Something like...
var marker;
map.on('locationfound', function(ev){
if (!marker) {
marker = L.marker(ev.latlng);
} else {
marker.setLatLng(ev.latlng);
}
})
I'd also appreciate if anyone knows of a tidy way of doing it without events
In that case, do have a look at the HTML5 geolocation API. There are no events, but there are asynchronous callbacks anyway. You can use those callbacks directly, you can wrap them in event handlers (as Leaflet does), you can wrap them in Promises, but one way or the other you'll have to deal with not-totally-trivial asynchronicity issues.

Vuejs and google maps: Cannot create new object of Polyline class

So, I want the user to be able to draw a freehand polygon on click of a button. I have it implemented in plain JS and now want to use it in vue (using vue-cli).
I am using this plugin for vue: https://github.com/xkjyeah/vue-google-maps/blob/vue2/API.md
Here is the code I am using:
var self = this;
// calls another method which disables map controls
self.disableMap();
// below line is fine
console.log(self.$refs.map.$mapObject);
// event handler is being called
self.$refs.map.$mapObject.addListener('mousedown', function() {
// the below line results in undefined
console.log(self.$refs.$polylineObject);
let poly = new(self.$refs.map.$polylineObject)({
map: self.$refs.map,
clickable: false
});
})
Any help greatly appreciated.

Events on openlayers overviewmap

I'm using openlayers 3 on a simple html page, to display a map with an overviewmap.
I would like to know if it is possible to trigger events on openlayers overviewmaps, like we can do on openlayers maps.
Indeed I have features displayed on the overviewmap (not on the map) and I'd like to be able to select them.
I can't see anything in the API related with that.
Thank you by advance
Finally, i was able to do it like this (getOverviewMap() has to be called on the overviewMap element) :
var overviewMapControl = new ol.control.OverviewMap({
// Parameters for my overviewMap
});
var map = new ol.Map({
controls: ol.control.defaults().extend([
overviewMapControl
]),
// ... other parameters
});
and the event triggered :
overviewMapControl.getOverviewMap().on('click', function(evt) {
overviewMapControl.getOverviewMap().forEachFeatureAtPixel(evt.pixel,
function(feature, layer) {
console.log(feature.getProperties());
});
});

How to get modified and original geojson points after editing polygon in leaflet?

I have a geojson feature I've created. After editing, I know there is a draw:edited event. How do I get the original points that the polygon consisted of, and is it possible to get the new polygon points? How? Is it possible to know which vertices were changed or added?
I tried the following, all of which does not work:
map.on('draw:edited', function (e) {
var type = e.layerType;
var layer = e.layer; // this is giving undefined errors
var shape = layer.toGeoJSON() // this is undefined
var shape_for_db = JSON.stringify(shape);
});
The draw:created event fired on L.Map returns a L.LayerGroup as e.layers, which contains all the features that just have been edited. This is because you can edit multiple features at once before pressing the save button. You can iterate the L.LayerGroup and then fetch the GeoJSON:
map.on('draw:edited', function (e) {
e.layers.eachLayer(function (layer) {
console.log(layer.toGeoJSON());
});
});

Need to redraw a map with new data (in conjunction with CartoDB.js)

I seem to be having some trouble with reinitializing a Leaflet map object. I am running an init() function that starts by initializing a map, adding a tilelayer and layer with polygons, and then adding sublayers which color the polygons according to a ST_Intersects query. The issue is that this function is tied to an AJAX call that is caused by a click event but does not update the data according to the new parameters sent to the map. I don't think I am explaining this very well, so here is a bit of my code:
success: function(data) {
init(data);
}
function init(data){
// initiate leaflet map
alert("start");
var map = L.map('cartodb-map').setView([40.750028, -73.926768], 11);
alert("map made");
//create sublayers, etc
}
What happens is that the first time init is run, both 'start' and 'map made' alerts work, and the map is made according to the data. Any further calls to init simply alerts with "start" and "map made" is never alerted so I believe the problem is with reinitializing the leaflet map. What should I do to fix this?
Not sure the problem without seeing more of your code, but you could try calling map.remove(); the second time around. So:
if (map) {
map.remove();
// add in new map initialization here
} else {
var map = ...
}

Categories