OpenLayers2 WMS layers and overlay, even official samples are broken? - javascript

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);

Related

Performance limitations with OpenLayers 4.6.5 using several layers

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.

Magnifying Tiles in OpenLayers 2 or Increasing MaxZoom Without Distorting Projection

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!

marker symbols for leaflet_Ajax, looking always for default marker in js/images/marker-icon.png

I am new to leaflet but have developed some interactive maps in the past. I started working on displaying a gps device on a UAV. The UAV sends the location information on a server and has a php code that returns some sensor values upon relevant request (in geojson format, so I dont have to do much... phew). I was looking for some solutions for how to do it seamlessly using Ajax when i came across leaflet_Ajax.. I had a lot of issues which were mostly resolved by some questions on stackoverflow for example this one and a few others.
Now here is how i am writing my code for the markers for the points:
var geojsonLayer = new L.GeoJSON.AJAX("myserver/get_geoj.php?stype=particle&sval[min]=2&sval[max]=26",{pointToLayer: redmarkers, onEachFeature: popUp});
function popUp(feature, layer) {
layer.bindPopup(feature.properties.sensor_v);
},
I have another function redmarkers that returns red colored circle markers. What happens is that finally it is loading the data from the server... phewh.... but it does not bind the popup or the markers to this layer. It looks for the (I guess some) default marker images in the js/images/marker-icon.png as marker symbol. This doesnot exist and so it gives me an error. But if i take any random image and call it marker-icon.png and put it in the desired location it shows that image on the map but still does not bind the popup.
What am i doing wrong. As i am new to stack overflow as well if you need more information or if i am not asking the question right please let me know.
Okay So I resolved it, but thought that somebody else might do similar mistakes later and I should answer this question.
I had accidentally edited my leaflet.js file somehow. I dont remember doing that though. I deleted the dummy image that I had put in the js/images folder for marker-icon.png and it was still showing the same marker. The i realized it had cached it so i disabled chache, only to realize in the console that the error had something to do with leaflet.js. I updated the version of leaflet.js (had a backup copy on my disk, so the same version didnt update or something), and it works fine now. Here is my current code
var geojsonLayer = new L.GeoJSON.AJAX(dataurl,{
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, redRegionStyle);
},
onEachFeature: onfeature
});
function onfeature(feature, layer)
{
layer.on(
{
mouseover: highlightFeature,
mouseout: resetHighlight
});
layer.bindPopup(feature.properties.sensor_v.toString());
}
It works perfectly highlights the features as i like and also has the popup bind to the features.
Sorry to all those who i bothered by asking this question as it was my own sily mistake

LEAFLET: Custom images in the Layer Control Tutorial?

I have followed the leaflet tutorial on how to create Layer Control and the custom markers:
Markers:http://leafletjs.com/examples/custom-icons.html
Control: http://leafletjs.com/examples/layers-control.html
I am using the control code and i would like to add my custom marker to this. When applying the code it the map goes blank and breaks. Im not sure if it's something do to with the positioning with the "add to map" and "bindpopup". Any help would be great.
CODE:
[CLOUDMADE API KEY AND INFO HERE]
var officeIcon = L.icon({
iconUrl: 'images/office1.png'
});
var london = L.marker([51.3512542357518,-0.461769104003906],{icon: officeIcon}).addTo(map).bindPopup('<b>Office Address</b>');
var cities = L.layerGroup([london]);
var minimal = L.tileLayer(cloudmadeUrl, {styleId: 22677}),
midnight = L.tileLayer(cloudmadeUrl, {styleId: 999}),
motorways = L.tileLayer(cloudmadeUrl, {styleId: 46561});
var map = L.map('map', {
center: new L.LatLng(54.980000,-1.5975022315979004),
zoom: 10,
layers: [minimal, motorways, cities]
});
var baseMaps = {
"Minimal": minimal,
"Night View": midnight,
};
var overlayMaps = {
"Motorways": motorways,
"Display Markers": cities
};
map.addControl(new MyControl());
L.control.layers(baseMaps, overlayMaps).addTo(map);
The problem is that you're adding the marker to the map before you have defined the map. I would recommend using firebug for firefox or the equivalent in chrome. That way you could look at the console and you would see the error:
'Uncaught TypeError: Cannot call method 'addLayer' of undefined'
L.Marker.L.Class.extend.addTo leaflet-src.js:2993
addVehicleContentUI obelix.dev:1074
(anonymous function) obelix.dev:718
(anonymous function) obelix.dev:1292
p.event.dispatch jquery-1.8.0.min.js:2
g.handle.h
This pointed me to the L.Marker which made me realise that you hadn't defined the map yet. The problem you have is that you're adding the marker to the map as well as adding it to the group layer. Just don't add it to the map (as per the tutorial you were following). so remove the code:
.addTo(map)
from:
var london = L.marker([51.3512542357518,-0.461769104003906],{icon: officeIcon}).addTo(map).bindPopup('<b>Office Address</b>');
The next problem is that MyControl isn't a control, I commented out the following line:
map.addControl(new MyControl());
From your code snippet, I presume you have a key from cloudmade. If so then it should work fine. I tested it locally and everything was good.
I do highly recommend getting firebug if you're using firefox or the equiv for chrome if you use chrome. Looking at the console will show you these problems and you can even set breakpoints and step through the javascript as it executes. An invaluable tool for javascript programming IMHO.
Cheers.

Controlling Clustered Pushpin's VEShape in VE SDK 6.2

Preface
I'm using the newly released Microsoft Virtual Earth SDK v6.2 which has built-in support for pushpin clustering. I realize there are custom ways of doing clustering where my question is easy to answer, but I'd like to leverage the built-in support as much as possible, so this question is specifically related to using the clustering feature of the VE 6.2 SDK.
The Problem
After enabling the built-in clustering (via VEShapeLayer.SetClusteringConfiguration), the clusters are created as expected, however, they have the default information in them which says something like "X items located here - zoom in to see details". In the app I'm working on, I need to display more information than that - I either need to allow the user to click on the pushpin and VE will automatically zoom in so that the points are now distinct OR display the names of the points in the infobox attached to the cluster pushpin. The catch is that cluster shape that VE creates for me does not appear to be editable until after all of the clustering logic has run...at that point, I don't know what original pushpins belong to that particular cluster. Is there a way to make this happen without resorting to creating a custom clustering implementation?
In case others have this same issue, the answer was just posted over in the MSDN forum for VE:
http://social.msdn.microsoft.com/Forums/en-US/vemapcontroldev/thread/d55090e2-2f5c-459c-9ecd-c3f32f0505b3/
We're doing precicely what I think you are asking for... Try this
// Create your map
var MapCtl = new VEMap('MapContainer');
// Create a layer for your pins
MapPinLayer = new VEShapeLayer();
// Add a callback that gets called every time the cluster config changes
var clusteringOptions = new VEClusteringOptions();
clusteringOptions.Callback = clusterCallback;
MapPinLayer.SetClusteringConfiguration(VEClusteringType.Grid, clusteringOptions);
// your cluster callback method
function clusterCallback(clusters) {
for (var i = 0; i < clusters.length; ++i) {
var cluster = clusters[i];
var clusterShape = cluster.GetClusterShape();
var clusterSize = cluster.Shapes.length;
clusterShape.SetTitle('Some Title');
clusterShape.SetDescription('There's ' + clusterSize + ' shops in this area');
}
}

Categories

Resources