Leaflet Overlay Layers Control Menu with JQuery ajax Call (GeoServer WFS) - javascript

I can setup a LeafletJS map having multiple (overlay) layers and to manage their visibility with a control menu when using basic GeoJSON files, exactly like the doc example : http://leafletjs.com/examples/layers-control/.
This works fine :
var geojson_layer1 = L.geoJson.ajax("layer1.geojson", {style: style, onEachFeature:onEachFeature});
var geojson_layer2 = L.geoJson.ajax("layer2.geojson", {style: style, onEachFeature:onEachFeature});
...
geojson_layer1.addTo(map);
geojson_layer2.addTo(map);
...
var baseMaps = {
"MyMap": map
};
var overlayMaps = {
"Layer1": Layer1,
"Layer2": Layer2
};
...
L.control.layers(baseMaps, overlayMaps).addTo(map);
Now I try to do the same (still basemap + overlay layers with control) but with data coming from a GeoServer (WMS/WFS). For this I use JQuery ajax call, eg :
var xyz_Parameters = {
service: 'WFS',
version: '1.0.0',
request: 'GetFeature',
typeName: 'myworkspace:xyz',
maxFeatures: '50',
outputFormat: 'application/json',
};
var parameters_xyz = L.Util.extend(xyz_Parameters);
var URL = owsrootUrl + L.Util.getParamString(parameters_xyz);
console.log(URL);
$.ajax({ url: URL, success: function (data) {
var geojson_layer_1 = new L.geoJson(data, {style: style, onEachFeature:doNothing});
geojson_layer_1.addTo(map);
}
});
This works fine too BUT I'm unable to manage the layers visibility through menu as variable (geojson_layer_1 here) is not seen globally.
Actually my problem comes with the async/callback (normal) behavior. I'd like to know how to manager a layer object with callback.
I've seen lot of things on the web (eg : Handling ajax-request in leaflet map) but either it is not exactly what I want or I wasn't able to make them work.
Does anyone would have a (more) complete example ?
Thanks.
Tom

Related

Use GIF as a source of ImageWMS on OpenLayers Map

OpenLayers version 2 seemed to display gifs without any problem.
OpenLayers: 4.6.4 (the version that I am using now) only displays the first frame of the gif: https://prnt.sc/i5xrun
Andreas Hocevar suggested a solution to this problem (https://github.com/openlayers/openlayers/issues/4133):
Use a "custom imageLoadFunction for the image source. Instead of
returning the image itself, return a canvas with a frame of the gif,
which you can get using third party libraries (e.g.
http://themadcreator.github.io/gifler/docs.html#animator::createBufferCanvas())."
I tried to use his approach but didn't manage to display the canvas on the map. Could someone either advise how to show gif on the map or how to display canvas holding that gif?
Here's the code that I used:
<script src="/js/gifler.min.js"></script>
...
var ImageSource = new ol.source.ImageWMS({
url: 'http://weather-services.telventdtn.com/basic/wms_v1/wms.wsgi?',
params: {
'REQUEST' : 'GetAnimationFile',
'VERSION' : '1.3.0',
'SERVICE' : 'WMS',
'STYLES' : '',
'LAYERS' : 'RADAR_US_CURRENT',
'CRS' : 'EPSG:900913',
'BBOX' : '-16730536.751059378,2397065.207023127,-3629841.5992064495,8198941.401981145',
'FORMAT' : 'image/gif',
'WIDTH' : '2678',
'HEIGHT' : '1186',
'FRAMEDELAY' : '20',
'TRANSPARENT': 'TRUE'
},
imageLoadFunction: function (image, src) {
var client = new XMLHttpRequest();
client.open('GET', src, true);
client.setRequestHeader('Authorization', "Basic " + btoa("login:password"));
client.responseType = "arraybuffer";
client.onload = function () {
var byteArray = new Uint8Array(this.response);
var blob = new Blob([byteArray], {type: "image/png"});
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL(blob);
gifler(imageUrl)
.get()
.then(function(animator) {
var BufferCanvas = animator.constructor.createBufferCanvas(animator._frames[0], animator.width, animator.height);
animator.animateInCanvas(BufferCanvas);
image.setImage(BufferCanvas);
});
};
client.send();
}
});
var Image = new ol.layer.Image({
name: 'precip_layer',
opacity: 0.8,
zIndex: 1,
source: ImageSource
});
The solution is in the new release of OpenLayers v4.6.5. Below is the example from their official website of how the animated WMS layer can be achieved:
https://openlayers.org/en/latest/examples/wms-time.html
I had some success animating gif downloaded through imageWMS (used ncWMS for this).
create an ImageWMS source image layer to get the animated gif from ncWMS or other WMS service that provides animated gifs.
Then I would use the gifuct-js.js library to unpack the gif in the ImageWMS "imageLoadFunction".
I then have another ImageLayer which uses an ImageCanvasSource, in which I have the canvasFunction create the canvas, which I give to the gif library functions to render on top of.
The net result is one layer to downloade the imageWMS and another layer to display it as an ImageCanvasSource. You may have to do some projection alignment, but now you can have controls to animate the gif in another layer.

Refresh openlayers map after updating chart element

I need to refresh an openlayers map after updating the size of pie charts in a mapfile displayed on the map (on button click). I cannot refresh the whole page or I lose the data. It works when I change the zoom level. I have tried map.updateSize() (no effect), map.render() (TypeError "a" is not defined), layer.redraw(). I am not sure if I am missing something openlayers-related, or if it is an issue with my javascript. I have looked through a number of posts, but can't seem to get any of the answers working in my case.
$(document).ready(function() {
map = new OpenLayers.Map( 'map' ,
{ maxExtent: new OpenLayers.Bounds({{bounds.0}}, {{bounds.1}}, {{bounds.2}}, {{bounds.3}}),
controls:[new OpenLayers.Control.Navigation(),
new OpenLayers.Control.LayerSwitcher(),
new OpenLayers.Control.PanZoomBar()],
numZoomLevels:20
}
);
var mpLayer = new OpenLayers.Layer.MapServer('Zones Layer', '{{ mapserverpath }}', {
map:'{{mapFile}}',
layers:'all',
isBaseLayer: 'true'
},{
singleTile: 'true'
// ratio: 2.0
}
);
map.addLayers([mpLayer]);
//map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
map.zoomToMaxExtent();
map.events.register("click", map, qryDB );
$(document).on('click', '#bttnMinus', function(){
pieFact*=0.5;
updatePieFact();
mpLayer.redraw();
});
$(document).on('click', '#bttnPlus', function(){
pieFact*=1.5;
updatePieFact();
mpLayer.redraw();
});
$(document).on('click', '#bttnReset', function(){
pieFact=1.0;
updatePieFact();
mpLayer.redraw();
});
});
You can try to call "clearGrid()" function before redrawing.
"clearGrid()" is a function of Layer.Grid (Layer.MapServer inherits from Layer.Grid). It will destroy each tile of the layers.
Just remark that "clearGrid ()" is not a APIMethod, so it is not supposed to be called in this way.
There are also a similar question/answer here.
try this. It worked for me.
$(window).trigger('resize');
This code sets the screen again.

How to set default layer visible in openlayers 2

I have two layers and switcher in openlayers. After init immediately I would like to set second layer to be visible, but still showed first added layer.
I tried: setVisibility, setBaseLayer, but without successful.
Here is part of code:
var gmapLayer = new OpenLayers.Layer.Google("Google sattelite", { type: google.maps.MapTypeId.SATELLITE, visibility: false });
var gmapStreetLayer = new OpenLayers.Layer.Google("Google streets", { visibility: false });
map.addLayer(gmapLayer);
map.addLayer(gmapStreetLayer);
map.addControl(new OpenLayers.Control.LayerSwitcher());
After init I tried:
map.setBaseLayer(selLayer);
//or
selLayer.setVisibility(true);
Ok I found problem. I used setBaseLayer wrong because called to array see:
var selLayer = map.getLayersByName(selectedLayer);
if (selLayer !== null) {
map.setBaseLayer(selLayer); //<---Wrong
}
Right solutions is:
var selLayer = map.getLayersByName(selectedLayer);
if (selLayer !== null) {
map.setBaseLayer(selLayer[0]); //<--Good
}

OpenLayers: Can't select feature after clickout

I'm trying a simple test where I have a base image with draggable features on top. These point features have associated external graphics (I'd prefer to use polygons with associated graphics but that's a whole other question).
I have a hover control that works perfectly. I also have a select control that almost works. However I cannot reselect a feature once I have clicked out once. Similarly, I cannot select features if I click anywhere outside of the features before trying to select one.
I hope that's clear - but if not then this example should be (and you can also see the whole code) http://sigfrid.co.uk/oltest/simple.html
I'll put what I think are the key bits of code below....
Create a map
var map = new OpenLayers.Map({
div:'map',
});
Add a base layer
var base = new OpenLayers.Layer.Image(
'Base level',
'img/base.png',
new OpenLayers.Bounds(-1000, -1000, 1000, 1000),
new OpenLayers.Size(864,864),
options
);
map.addLayer(base);
Add styles
var markerStyleMap = new OpenLayers.StyleMap
({
"default": new OpenLayers.Style(template, {context: context}),
"hover": new OpenLayers.Style ({graphicOpacity:0.5}),
"select": new OpenLayers.Style ({graphicOpacity:0.1})});
Add points
pt1 = new OpenLayers.Geometry.Point(0,0);
pt1Feature = new OpenLayers.Feature.Vector(pt1);
...
markerLayer.addFeatures([pt1Feature,pt2Feature,pt3Feature]);
Add unique lookup for the different marker images
var lookup = {
"f1": {externalGraphic:"img/f1.png"},
"f2": {externalGraphic:"img/f2.png"},
"f3": {externalGraphic:"img/f3.png"},
}
markerStyleMap.addUniqueValueRules("default", "type", lookup);
markerLayer.styleMap = markerStyleMap;
markerLayer.features[0].attributes.type = "f1";
...
Add controls
var dragControl = new OpenLayers.Control.DragFeature(markerLayer)
map.addControl(dragControl);
dragControl.activate();
var highlightCtrl = new OpenLayers.Control.SelectFeature(markerLayer, {
hover: true,
highlightOnly: true,
renderIntent: "hover",
});
map.addControl(highlightCtrl);
highlightCtrl.activate();
var selectCtrl = new OpenLayers.Control.SelectFeature(markerLayer, {
clickout: true,
renderIntent: "select",
});
map.addControl(selectCtrl);
selectCtrl.activate();
Thanks for any help,
Nick
Turns out drag and select are not compatible. However, there are some work arounds such as
http://fastr.wordpress.com/2012/04/17/openlayers-selectfeature-where-did-i-clicked-2/
although this does add some event problems...

Google Maps API infoWindowAnchor not working?

I am trying to get the infoWindow to display in just the right place on a Google Maps integration I'm working on (just above the top right/top left corner of an image). Whenever I try to adjust the "infoWindowAnchor" it doesn't seem to be working? However, the "iconAnchor" seems to be working as expected. I am wondering if anyone has ever run into a similar scenario before? I am making use of a custom icon, but even when I revert back to the standard icons provided by Google, the infoWindow seems to be displaying incorrectly (The tail is centered on the icon as opposed to being placed in it's top right position).
Below is the code I'm using to get this all working. The Important bits are here, but I've removed some of the other functions that may get in your way when diagnosing.
$(document).ready(function() {
var centerLatitude = 37.782112;
var centerLongitude = -122.419281;
var sanFran = new GLatLng(centerLatitude, centerLongitude);
var startZoom = 12;
var map;
var icon;
// Creates a default icon using our tuberent image
var myIcon = new GIcon();
myIcon.image = baseurl + 'my/imageFolder/markerFolder/image.png';
myIcon.shadow = baseurl + 'my/imageFolder/markerFolder/shadow.png';
myIcon.iconSize = new GSize(25,25);
myIcon.shadowSize = new GSize(38,25);
myIcon.iconAnchor = new GPoint(13,25);
myIcon.infoWindowAnchor = new GPoint(13,0);
myIcon.printImage = baseurl + 'my/imageFolder/markerFolder/printImage.gif';
myIcon.mozPrintImage = baseurl + 'my/imageFolder/markerFolder/mozPrintImage.gif';
myIcon.printShadow = baseurl + 'my/imageFolder/markerFolder/printShadow.gif';
myIcon.transparent = baseurl + 'my/imageFolder/markerFolder/transparent.png';
myIcon.imageMap = [22,0,22,1,22,2,21,3,21,4,21,5,21,6,21,7,23,8,24,9,24,10,22,11,22,12,22,13,22,14,22,15,22,16,22,17,22,18,22,19,22,20,22,21,22,22,22,23,22,24,2,24,1,23,1,22,1,21,1,20,1,19,1,18,1,17,1,16,1,15,1,14,1,13,1,12,1,11,0,10,0,9,1,8,3,7,4,6,5,5,7,4,8,3,9,2,10,1,11,0];
map = new GMap2(document.getElementById('map'));
map.addControl(new GMapTypeControl());
map.addControl(new GLargeMapControl3D());
map.setCenter(sanFran, startZoom);
/* Some Random Code and Functions here .... */
var point = new GLatLng(location.lat, location.lng);
var marker = new GMarker(point, myIcon);
map.addOverlay(marker);
/* Some Random Code and Functions here .... */
GEvent.addListener(marker, "click", function(){
var randomText = "Just some random test text";
var myHtml = "<b>#" + location.id + "</b><br/>" + location.neighborhood + "<br/>" + randomText;
map.openInfoWindowHtml(point, myHtml);
});
});
$(document.body).unload(function() {
if (GBrowserIsCompatible()) {
GUnload();
}
});
You could also try setting the pixel offset in the GInfoWindowOptions of openInfoWindowHTML().
Can you move the info window at all? By setting very large values just to test?
Otherwise, I doubt this is the answer, but I'd try it just in case.
From Google Maps API:
"Once we've created a map via the GMap2 constructor, we need to initialize it. This initialization is accomplished with use of the map's setCenter() method. The setCenter() method requires a GLatLng coordinate and a zoom level and this method must be sent before any other operations are performed on the map, including setting any other attributes of the map itself."
You're adding a couple of controls before calling setCenter().

Categories

Resources