I am currently working on a GIS holding a large amount of layers (up to 20 / 30).
The map is rendering tiles in a really slow way.
It was previously written with OpenLayers 2.x, and we didn't face this performance bottleneck.
Our layers are using WMS sources & tiles, which are declared as follow
function createTileLayer(options){
let source = new ol.source.TileWMS({
url: serverURL, // Our GeoServer instance
params: {
'LAYERS': options.id
'BGCOLOR': options.backgroundColor,
'TRANSPARENT': options.transparent,
'VERSION': options.version,
'FORMAT': 'image/png'
},
serverType: 'geoserver',
projection: 'EPSG:2100', // Managed by Proj4J
transition: 0
});
let layerTile = new ol.layer.Tile({
source: source,
visible: options.visible,
});
return layerTile;
}
The map declaration in itself is quite simple:
let map = new ol.Map({
target: document.getElementById('app'),
layers: Layers, // All the layers we created before
view: new ol.View({
center: ol.proj.fromLonLat([5.497853028599662, 34.82203273834541]),
zoom: 18,
projection: 'EPSG:2100'
}),
loadTilesWhileAnimating: true,
loadTilesWhileInteracting: true,
renderer: 'canvas'
});
}
Problem with this approach is that the browser seems to spend far too much time in drawing every layer. Here is the profile of some tests on Chrome:
Results are an almost unusable map.
I am aware that the amount of layers is high, but the issue was not in OpenLayers 2.x (or at least, performances were better).
One possible workaround is using only one TileWMS source and pass it the list of all our layers in its 'LAYERS' param. This dramatically improve the speed because GeoServer does all the rendering work, but we lose some possibilities such as managing each layer transparency.
I might be doing something wrong in querying / rendering tiles this way, that I am not aware of. Thanks for any help.
The most likely issue is that you are not hitting the tile boundaries that GeoWebCache (which is what GeoServer) uses to render the tiles. See this page in the manual which lists the criteria that must be met for this to work.
A better way to do this is to use a WMTS request (where the tile grids etc are agreed on between the client and server rather than guessed at). You can even get OpenLayers to do the negotiation for you by asking for the getCapabilities document.
Related
I am creating a web page with Leaflet to access a WMS server.
The issue I have is that I access a paying WMS server that is "counting" the number of requests I make.
In the first attempt I made, since the default tileSize was 256px each of my requests generated 16 tiles requests and so I was "deducted" 16 requests on my account.
I then tried to modify my code as follow :
var wmsserver = L.tileLayer.wms('http://wmsserver/wms?', {
layers: 'mix:precip_24h:mm' ,
format: 'image/png',
tileSize: window.screen.width,
version: '1.3.0',
transparent: true,
});
Now I still have 2 requests logged, and the result on the screen is a little bit shifted.
There must be a cleaner way to do this.
I am trying to add to my leaflet map a layer with current weather. For that I am using this leaflet plugin https://github.com/buche/leaflet-openweathermap that is using this call:
https://tile.openweathermap.org/map/{layer}/{z}/{x}/{y}.png?appid={API key}
The free version of OWM is offering 60 calls per minute, the problem is that every time that I zoom or drag the map 12 petitions to the API are being requested. I thought the free version with the 60c/m should be more than enough for my app, but as soon I zoom few times the API key gets blocked. Is there a better way to work around this?
The more tiles your map requests, the sooner you reach the limit. In order to reduce the amount of tiles requested (with a cost to user experience), consider limiting zoom/drag options.
// change options according to your needs
let mapOptions = {
zoomControl: false,
scrollWheelZoom: false,
boxZoom: false,
dragging: false
}
let map = L.map('map', mapOptions);
I am using OpenLayers2 with Bing. My customer requires a deeper zoom level to interact with the maps. Currently, the max zoom level I can achieve is 19 which I tested with the getZoom() function. I have tried to set the "numZoomLevels" in the map constructor to a higher number, but Bing/OL just seems to ignore it. I was wondering if there is a way to force the tiles to a lower zoom level or if I could simply magnify the existing tiles so that I can see larger images even if the details are a bit blurry. It is crucial, however, that I don't modify the projection because having correct lat/lon values is paramount to the customer's function.
map = new OpenLayers.Map('map', {
allOverlays: false,
numZoomLevels: 20,
controls: [
new OpenLayers.Control.Navigation({
dragPanOptions: {
enableKinetic: true
}
}),
new OpenLayers.Control.LayerSwitcher(),
new OpenLayers.Control.Zoom({
zoomInId: "customZoomIn",
zoomOutId: "customZoomOut"
})
]});
var aerial = new OpenLayers.Layer.Bing({
name: "Aerial",
key: apiKey,
type: "Aerial"
});
I did stumble across an OL3 magnify example, but it is written for OL3 and a bit beyond what I can convert since I need the magnify option to be embedded as a zoom level, not just a context overlay. Also, I don't have a ton of experience with canvas. Any help is appreciated!
I figured it out, and it's actually quite simple. First, the numZoomLevels should have been on the layer level, not the map level. If you want to be able to zoom in beyond what Bing provides you, you must set fractionalZoom to true as shown below:
map = new OpenLayers.Map('map', {
allOverlays: false,
fractionalZoom: true,
controls: [
new OpenLayers.Control.Navigation({
dragPanOptions: {
enableKinetic: true
}
}),
new OpenLayers.Control.LayerSwitcher(),
new OpenLayers.Control.Zoom({
zoomInId: "customZoomIn",
zoomOutId: "customZoomOut"
})
]});
Then, on each layer, you need to set an array of resolutions. You will need to create a value for each zoom level you list under your numZoomLevels. I needed 22 zoom levels.
var aerial = new OpenLayers.Layer.Bing({
name: "Aerial",
key: apiKey,
type: "Aerial",
numZoomLevels: 22,
resolutions: bingResolutions,
serverResolutions: bingServerResolutions,
transitionEffect: 'resize'
});
In the source code for OpenLayers.Layer.Bing already had a resolution block defined which maps to their values at: https://msdn.microsoft.com/en-us/library/aa940990.aspx
var bingResolutions = [156543.03390625, 78271.516953125, 39135.7584765625,
19567.87923828125, 9783.939619140625, 4891.9698095703125,
2445.9849047851562, 1222.9924523925781, 611.4962261962891,
305.74811309814453, 152.87405654907226, 76.43702827453613,
38.218514137268066, 19.109257068634033, 9.554628534317017,
4.777314267158508, 2.388657133579254, 1.194328566789627,
0.5971642833948135, 0.29858214169740677, 0.14929107084870338,
0.07464553542435169];
var bingServerResolutions = [156543.03390625, 78271.516953125, 39135.7584765625,
19567.87923828125, 9783.939619140625, 4891.9698095703125,
2445.9849047851562, 1222.9924523925781, 611.4962261962891,
305.74811309814453, 152.87405654907226, 76.43702827453613,
38.218514137268066, 19.109257068634033, 9.554628534317017,
4.777314267158508, 2.388657133579254, 1.194328566789627,
0.5971642833948135];
The server resolutions are the tile resolutions from Bing itself. The additional resolutions (0.29858214169740677, 0.14929107084870338, 0.07464553542435169) are my fractional zoom levels that just zoom in on the layer 19 tile.
Here is the working example from OpenLayers for an OSM layer.
Hope this helps someone else!
I'm trying to fetch weather radar data for the UK, from a WMST server.
The client can get the Capabilities fine. After that, the browser (Chrome and Firefox) crashes after a while, with an out-of-memory error.
The only thing obviously different in my case, in comparison with simple examples, is that an API key is needed for all interactions with the server.
var parser = new ol.format.WMTSCapabilities();
var map;
//I pass the API key here
fetch('http://datapoint.metoffice.gov.uk/public/data/inspire/view/wmts?REQUEST=GetCapabilities&key=my_key_goes_here').then(function(response) {
return response.text();
}).then(function(text) {
console.log('Capabilities found.'); //ok
var result = parser.read(text);
var options = ol.source.WMTS.optionsFromCapabilities(result, {
layer: 'RADAR_UK_Composite_Highres',
matrixSet: 'EPSG:4326'
});
map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
opacity: 0.7
}),
new ol.layer.Tile({ //fails when this Tile is included
opacity: 1,
source: new ol.source.WMTS(options),
//I set this, figuring that the API key is still needed
url: 'http://datapoint.metoffice.gov.uk/public/data/inspire/view/wmts?my_key_goes_here'
})
],
target: 'mymap',
view: new ol.View({
center: ol.proj.fromLonLat([0, 52.0]), //near London, UK
zoom: 7
})
});
});
The crash happens without the client trying to fetch the tiles (because I can't see any HTTP requests in the debugger; the last one is the get-capabilities request).
Any hints as to what might be causing this?
First of all, note that ol.layer.Tile does not have an url option. Ideally, the GetCapabilities response would advertise a service url that has the key already. Since the server you are trying to access does not have that, you'll have to tweak the result you get from the GetCapabilities response:
result.OperationsMetadata.GetTile.DCP.HTTP.Get[0].href += 'key=my_key_goes_here&'
The second and more severe problem is that the GetCapabilities response advertises incorrect scale denominators and origins. To fix those, you have to tweak the result again:
result.Contents.TileMatrixSet[0].TileMatrix.forEach(function(m) {
m.ScaleDenominator *= 111319.49079327358;
m.TopLeftCorner = m.TopLeftCorner.reverse();
});
After applying these tweaks, you can pass the result to ol.source.WMTS.optionsFromCapabilities, and you will get a correct map.
I'd strongly recommend you contact the service provider (contact information can also be found in the GetCapabilities response) and let them know about the problems with their GetCapabilities response.
I'm using a library that requires OL2 (sadly, i wish i could go OL3 but that's not an option).
What i need is to display different WMS base layers with some other WMS overlays.
Point is, i don't understand what i'm doing wrong. This library is supposed to give me an ol.wms layer, but it doesn't work. I'm trying to understand how this thing works, but even the documentation and samples on the official website are broken.
Some examples:
http://dev.openlayers.org/examples/wrapDateLine.html
http://dev.openlayers.org/examples/getfeature-wfs.html
http://dev.openlayers.org/examples/tilecache.html
http://dev.openlayers.org/examples/wms-long-url.html
It seems to me that these examples are outdated (i tried on firefox 40, chrome 45, even IE11...) which is understandable since it's a 2 years old library, but i sadly need them.
Can anybody point me to updated samples, if available?
Yep, most samples are broken because they link to WMS unavailable resources (at least at the time of writing).
Using other resources the samples will work.
map = new OpenLayers.Map('map');
var ol_wms = new OpenLayers.Layer.WMS("OpenLayers WMS",
"http://vmap0.tiles.osgeo.org/wms/vmap0", {
layers: "basic"
});
var bmTiles = new OpenLayers.Layer.XYZ(
"Geodab Map",
["http://tiles.geodab.eu/geodab-tiles/tile/bluemarble/${z}/${x}/${y}.png"],
{
numZoomLevels: 10
});
map.addLayers([ol_wms, bmTiles]);
var extent = new OpenLayers.Bounds(4, 32, 22, 55);
map.zoomToExtent(extent, true);