Automatic zoom depending on extreme points - javascript

I use OL 4.6.5.
I put some markers in a vector layer and have used a home-made thing to find the zoom, depending on how far from eachother the markers are placed (points from database). This is clumsy and coarse but it works...
Now I look for a function or other means to set the zoom automatically, depending on max and min lat and long. I couldn't make "fitExtent()" to work so I looked here and I found two solutions but I can only use this one:
var onChangeKey = vectorSource.on('change', function() { if
(vectorSource.getState() == 'ready') {
vectorSource.unByKey(onChangeKey);
map.getView().fitExtent(vectorSource.getExtent(), map.getSize()); } });
It uses the "fitExtent()" in another way than I did but unfortunately it doesn't change the zoom from 2. The other solution is some wierd language??? JS console reports: "Uncaught SyntaxError: Unexpected identifier".
There is an example page here: https://xerxx.se/zoomtest.html
The JScode is at the bottom. Both solutions I tried are there, the one quoted above is "in action".
My own clumsy code is also there - you will see it.
There must be a clever command for this, right?

The syntax you adopted in your code is not necessary here as vectorSource.on('change', function() { is important only when you load asynchronously a source (Ajax calls).
Your code is synchronous e.g
var vectorSource = new ol.source.Vector({
features: [placeOSM[1], placeOSM[2]]
});
...
Replace the block
var onChangeKey = vectorSource.on('change', function() {
if (vectorSource.getState() == 'ready') {
vectorSource.unByKey(onChangeKey);
map.getView().fitExtent(vectorSource.getExtent(), map.getSize());
}
});
with
// fitExtent is now fit and second arg map.getSize() is now optional
// e.g http://openlayers.org/en/latest/apidoc/ol.View.html#fit
map.getView().fit(vectorSource.getExtent());

Related

Unable to remove all layers from a map

I have a big map application, so to be representative I will have to provide just a chunk of code. So, this is how I try to remove all layers from a map:
map.getLayers().forEach(function (layer) {
map.removeLayer(layer);
});
//map.getOverlays().clear(); <-- also tried this, but to no effect
And I have some random behaviour - sometimes all layers are removed, sometimes not. It's a complete randomness, so there is no guarantee, that you will be able to reproduce this issue. So, it may be enough for me to know just conceptually, why it may happen.
SOLUTION
This is obviously an ol3 bug, because if I loop and delete just twice, then it starts working:
map.getLayers().forEach(function (layer) {
map.removeLayer(layer);
});
//for some crazy reason I need to do it twice.
map.getLayers().forEach(function (layer) {
map.removeLayer(layer);
});
Probably, it's not a bug, and there is some secret method, that enables to clear the map. But I do not know about it.
This is not a bug. The reason why your code does not work is because you are modifying the layers collection while looping through it. Doing so changes the index of each layer, and will cause unexpected results.
The proper way to clear all layers of a map is to use ol.Map#setLayerGroup():
map.setLayerGroup(new ol.layer.Group());
You should just clone the array:
const layers = [...map.getLayers().getArray()]
layers.forEach((layer) => map.removeLayer(layer))
You can use a while loop to do this and check the length of the layer array, as they are rearranged each time a layer is deleted, so this is why the forEach doesn't work, try
var layerArray, len, layer;
layerArray = map.getLayers().getArray(),
len = layerArray.length;
while (len > 0){
layer = layerArray[len-1];
map.removeLayer(layer);
len = layerArray.length;
}
I achieve that a while ago this way:
for(i in map._layers){
if(map._layers[i]._path != undefined) {
try{ map.removeLayer(map._layers[i]) }catch(e){ }
}
}
Maybe it helps

Openlayers 3 Replace a failed tile

We are running Open Layers 3.15.
Sometimes we get a dropped or failed tile.
Currently it displays nothing, (which can be confusing for our users) so we'd like to replace this with a tile that says 'no data' or something.
I've tried picking up the event and replacing the source of the tile eg
source.on('tileloaderror', function(){
source.setUrl('./images/map/failureTile.png');
});
but the problem with this is, instead of doing this on 1 tile, it does it for the entire layer, we don't want that.
Anyone know how we can do this for just the tile that failed and not the entire layer?
It's 2018, but for someone who may need this. Tested on v5.3.0
source.on('tileloaderror', function (event) {
var tileLoadFunction = function (imageTile, src) {
imageTile.getImage().src = './images/map/failureTile.png';
};
if (event.tile.tileLoadFunction_ != tileLoadFunction) {
event.tile.tileLoadFunction_ = tileLoadFunction;
event.tile.load();
}
});
This code relys on private function event.tile.tileLoadFunction_ is exposed.
Unfortunately xnakos' answer doesn't work on v5.3.0 because the event.tile.getImage() has been replaced with 1x1 canvas image by internal error handler.
Also noted, changing event.tile.src_ directly, seems to be an option, but it doesn't work either because of cache key or something.
A tile which failed to load should have a distinct class (.olImageLoadError). You can define a CSS rule not show these items.
.olImageLoadError {
display: none !important;
}
You could try this:
source.on('tileloaderror', function(event) {
event.tile.getImage().src = './images/map/failureTile.png';
});
You need the event parameter, that can get you the tile that failed, so that you can change the tile's image.
Warning: I tested the code above using tileloadend instead of tileloaderror, because my tiles never fail on me. :) I used a simulated failure rate using Math.random() and some random tiles were replaced by the image specified. I cannot think of a reason the code above would not work. If you verify it works, I will remove this warning from my answer. I tested it on OpenLayers 3.14.2 and on an OSM source.

Rafael: Mapael: Update trigger doesn't work, and no errors are given

Based on this minimal example of Mapael (part of the relevant code is down here):
$('#refresh').on('click', function() {
// Update some plots and areas attributes ...
var updatedOptions = {'areas' : {}, 'plots' : {}};
// add some new plots ...
var newPlots = {
"Dijon" : {
latitude : 47.323056,
longitude : 5.041944
}
}
$(".mapcontainer").trigger('update', [updatedOptions, newPlots, [], {animDuration : 1000}]);
});
I created this example page with an update trigger that works fine. Now I want to move this to my real application php page, and it doesn't work! Please take a look here.
The annoying part is that the console of my Browser doesn't show any errors! How can I debug this problem when I don't see any errors? Please assist!
If you require any additional information, please ask. Thanks for any efforts.
PS: Please ignore the bad styling that the script and css code is in body. I'll fix this once this issue is resolved. I don't think it's the issue, since the example page that works is exactly the same and doesn't have this problem.
First, take a note that you're using different versions of Maphael:
on the page where it works, version is 1.1.0,
on your page it is 2.0.0-dev.
Second, after setting a breakpoint at the "onUpdateEvent" method of Maphael (line 876), it just seems that event data just doesn't get passed into the handler.
Does the "update" event have the same signature for Maphael/Raphael 1.x and 2.x? This is the place you should look at.
Update: I took a look at the 2.0.0-dev internals, and it seems your update code should be something like this:
var updatedOptions = {'areas': {}, 'plots' : {},
// add some new plots ...
newPlots: {
"Dijon" : {
latitude : 47.323056,
longitude : 5.041944
}
},
animDuration : 1000
};
$(".mapcontainer").trigger('update', updatedOptions);
(last line may be:
$(".mapcontainer").trigger('update', [updatedOptions]);
)
Please check if it helps (though I'd recomment you to switch to a stable 1.1.0 release of Maphael).

leaflet maps - remove marker layer group and add another marker layer group

My objective here is to remove all the markers added to leaflet using layer group for a paginated listing page.When navigated to other page i am able to remove layer group of previous page, but on adding new layer group of markers(markers of next page) i am getting this error in browser and markers are not added to the map
error is - Uncaught TypeError: layer.onAdd is not a function;
code is
var leaflet_factory = {
//initializing map container
initialize: function() {
var map = L.map('mapresults');
var googleLayer = new L.Google('ROADMAP');
map.addLayer(googleLayer);
},
//set view of mao
setview: function(lat, long, zoom) {
map.setView([lat, long], zoom);
},
//add list of markers to maps
addMarkersList: function(marker_array) {
var markerArray = [];
$.each(marker_array, function(key, data) {
var marker_pointer = L.marker([data.lat, data.long]).bindPopup('<strong>' + $(this).attr('data-vendor').capitalize() + '</strong><br>' + $(this).attr('data-location').capitalize());
markerArray.push(marker_pointer);
});
window.page_makers_layer = L.layerGroup(markerArray);
window.page_makers_layer.addTo(map);
},
//remove the current marker layer group
removeMarkerLayer: function() {
map.removeLayer(window.page_makers_layer);
}
}
The problem with the above code is when calling addMarkersList for first time after initializing the map container it works.
But when i call addMarkerList with new list of markers(lat long pair) after calling removeMarkerLayer to remove existing marker layer it gives me following error which i am trying to debug.
Uncaught TypeError: layer.onAdd is not a function
Please point where i am doing wrong.
You're doing a few things wrong. Not catastrophically wrong, just antipattern wrong, e.g.:
map.removeLayer(window.page_makers_layer);
Do NOT use window globals to store references to your data (unless you're really, really, really sure of what you're doing). If you're wrapping map creation in a factory or a module, store your data in that scope.
var leaflet_factory = {
Do not name something a factory if it doesn't follow the factory pattern. It's very confusing. Just name it differently, make it a CJS module instead, or skip it entirely.
Research into common programming patterns. Do you have something that appears only once in the webpage? Consider singletons.
gives me following error which I am trying to debug.
How are you trying to debug it? Learn to use your browser debugging capabilities, and provide a complete stack trace.
You should be able to easily keep track of the value of the problematic variable, and see if it is an instance of L.LayerGroup when the call is made.

Styling a geoJSON Feature Layer in MapBox

I just started playing with MapBox and am running into a confusing issue. I'm creating a map with a geoJSON layer using this code:
var map = L.mapbox.map('map', '<MapBoxID>');
var zipLayer = L.mapbox.featureLayer('data/blah.json');
zipLayer.addTo(map);
zipLayer.setStyle({color: 'red'});
The map appears and shows the geoJSON, but it ignores the styling. When I copy that last line into the JS console in my browser, it works fine, though.
What am I missing here? Also, I've tried at least a dozen different ways of including the style in the options directly in the featureLayer() call, but nothing has worked. How do I specify the style when creating the feature layer?
I'm guessing a bit here, since I don't know the Mapbox JS very well, but it sounds a lot like an async error. Strangely, I don't see anything in the Mapbox or Leaflet APIs about a callback for this function. But, you can pass straight GeoJSON to featureLayer(), so I'd suggest using jQuery (or your XHR library of choice) to grab the data:
var map = L.mapbox.map('map', '<MapBoxID>');
var zipLayer;
$.getJSON('data/blah.json', function(data) {
zipLayer = L.mapbox.featureLayer(data);
zipLayer.addTo(map);
zipLayer.setStyle({color: 'red'});
});
Hopefully that'll do the trick.
I would go the route of using the built-in featureLayer function, then listening for it to be ready. This should help get you pointed in the right direction:
var featureLayer = L.mapbox.featureLayer()
.loadURL('/example-single.geojson')
.on('ready', function(layer) {
this.eachLayer(function(marker) {
// See the following for styling hints:
// https://help.github.com/articles/mapping-geojson-files-on-github#styling-features
marker.setIcon(L.mapbox.marker.icon({
'marker-color': '#CC0000'
}));
});
})
.addTo(map);
Have you tried adding the zipLayer after setting the style?

Categories

Resources