cannot add features to WFS layer - openlayers-3

I try to load some features from Geoserver to a vector layer in Openlayers 3.9.0.
var url = 'http://localhost:5550/geoserver/mymap/wfs?service=WFS&'+'version=1.0.0&request=GetFeature&typeName=mymap:layer&'+'outputFormat=application/json&maxFeatures=50';
var projection = ol.proj.get('EPSG:3857');
var extent = [2297128.5, 4618333, 2459120.25, 4763120];
var amir = new ol.source.Vector({
format: new ol.format.GeoJSON(),
loader: function (extent) {
$.ajax(url, {type: 'GET'})
.done(loadFeatures)
.fail(function () {alert("error");});
},
strategy: ol.loadingstrategy.bbox
});
function loadFeatures(response) {
formatWFS = new ol.format.WFS();
var features = formatWFS.readFeatures(response);
amir.addFeatures(features);
//-----------OR---------------------
var features = amir.readFeatures(response);
amir.addFeatures(features);
}
var fill = new ol.style.Fill({
color: 'rgba(0,0,0,0.2)'
});
var stroke = new ol.style.Stroke({
color: 'rgba(0,0,0,0.4)'
});
var circle = new ol.style.Circle({
radius: 6,
fill: fill,
stroke: stroke
});
jake = new ol.layer.Vector({
source: amir,
style: new ol.style.Style({
fill: fill,
stroke: stroke,
image: circle
})
});
In loadFeatures function if I use
formatWFS = new ol.format.WFS();
var features = formatWFS.readFeatures(response);
amir.addFeatures(features);
I get Uncaught AssertionError: Failure: Unknown source type pointing to a openlayers line that throws errors and to this line of my codevar features = formatWFS.readFeatures(response);.
If I use
var features = amir.readFeatures(response);
amir.addFeatures(features);
I get Uncaught TypeError: sourceVector.readFeatures is not a function pointing to var features = amir.readFeatures(response); .
The request to the WFS looks ok, with OK 200 status. If I grab the request's URL sended to Geoserver and open it in a new tab I get raw GeoJSON like {"type":"FeatureCollection","totalFeatures":422,"features":[{"type":"Feature","id":"layer.709","geometry":{"type":"Point","coordinates":[2391735.8907621,4695330.8039257005]},"geometry_name":"l_geom","properties":{"l_name":"Leeron"}},....//next feature
So its a FeatureCollection not just an array. Not that I know how to handle this
I dont get why to set a ol.format.WFS and not just read/add features. I dont know how to debug and add the features to my layer

You are instructing GeoServer to use GeoJSON as output format, so you'll need to use the GeoJSON format in OpenLayers to parse the features. You should be able to simplify your source configuration to something like
var url = 'http://localhost:5550/geoserver/mymap/wfs?service=WFS&' +
'version=1.0.0&request=GetFeature&typeName=mymap:layer&' +
'outputFormat=application/json&maxFeatures=50';
var amir = new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent, projection) {
return url + '&bbox=' + extent.join(',') +
'&srsName=' + projection.getCode();
},
strategy: ol.loadingstrategy.bbox
});

Related

URL parameters for Openlayers 3 to zoom to location?

I have an OL3 web application and I am wondering if it is possible to include URL parameters (such as coordinate values) for which the application can parse and open up at a specific location?
For example http://mywebsiteaddress?x=longitudevalue&y=latitudevalue
Is this something that can be done using OL3?
Sure, see: http://openlayers.org/en/latest/examples/permalink.html for an example (uses an anchor instead of url parameters but the idea is the same).
I did not like the openlayers permalink example because it uses map units and not well-known latitudes and longitudes. Sp I wrote my own code to hand over latlon coordinates, zoom and set a marker to it:
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
}
var mzoom=12;
var mlat = Number(getURLParameter('mlat'));
var mlon = Number(getURLParameter('mlon'));
var mzoom = Number(getURLParameter('zoom'));
var marker = 1
if (mlat == 0 || mlon == 0) {
mlat = 51.5; mlon = 7.0; mzoom=12; marker=0 //Default location
}
if (mzoom == 0 ) { mzoom=12 //Default zoom
}
var container = document.getElementById('popup');
var content = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');
closer.onclick = function() {
container.style.display = 'none';
closer.blur();
return false;
};
var overlayPopup = new ol.Overlay({
element: container
});
var expandedAttribution = new ol.control.Attribution({
collapsible: false
});
var map = new ol.Map({
controls: ol.control.defaults({attribution:false}).extend([
expandedAttribution
]),
target: document.getElementById('map'),
renderer: 'canvas',
overlays: [overlayPopup],
layers: layersList,
view: new ol.View({
center: ol.proj.fromLonLat([mlon, mlat]),
zoom: mzoom,
maxZoom: 18, minZoom: 8
})
});
if (marker == 1) {
var vectorLayer = new ol.layer.Vector({
source:new ol.source.Vector({
features: [new ol.Feature({
geometry: new ol.geom.Point(ol.proj.transform([parseFloat(mlon), parseFloat(mlat)], 'EPSG:4326', 'EPSG:3857')),
})]
}),
style: new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 0.5],
anchorXUnits: "fraction",
anchorYUnits: "fraction",
src: "marker.svg"
})
})
});
map.addLayer(vectorLayer);
}
I used the output of the qgis2web plugin and modified the file qgis2web.js as above.

update position of geolocation marker in Openlayers 3

I wan't to have a marker on the map, which position is dynamically updated.
When I create the layer inside the function of the geolocation.on('change'-event it works, but the layer is added each time the geolocation changes. Therefore I wanted to create the layer outside that function and update only the position of the marker.
With the folowing code I get an 'TypeError: a is null'
var geolocation = new ol.Geolocation({
projection: map.getView().getProjection(),
tracking: true,
trackingOptions: {
enableHighAccuracy: true,
maximumAge: 2000
}
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
opacity: 0.75,
src: './_img/marker_.png'
})
});
var pos1 = geolocation.getPosition();
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point(pos1)
});
var iconSource = new ol.source.Vector({
features: [iconFeature]
});
var iconLayer = new ol.layer.Vector({
source: iconSource,
style : iconStyle
});
map.addLayer(iconLayer);
geolocation.on('change', function() {
var pos_upd = geolocation.getPosition();
iconFeature.getGeometry().setCoordinates(pos_upd);
view.setCenter(pos_upd);
view.setZoom(18);
});
The browser Geolocation API, which is wrapped by ol.Geolocation, is asynchronous. After initiation, geolocation.getPosition() will always return undefined until the first change event.
The proper thing to do is to add the feature once you get a coordinate, in the change event handler.
You will need to use a conditional to determine if you should add ore update a feature.
I changed the code a bit, so that I created first an iconFeature, that wasn't already bound to a ol.geom.Point()-position. By this way there was no need to use geolocation.getPosition().
Later in the geolocation.on('change')-event I assigned the actual position to the geometry of the iconFeature.
Works like espected
// add an empty iconFeature to the source of the layer
var iconFeature = new ol.Feature();
var iconSource = new ol.source.Vector({
features: [iconFeature]
});
var iconLayer = new ol.layer.Vector({
source: iconSource,
style : iconStyle
});
map.addLayer(iconLayer);
// Update the position of the marker dynamically and zoom to position
geolocation.on('change', function() {
var pos = geolocation.getPosition();
iconFeature.setGeometry(new ol.geom.Point(pos));
view.setCenter(pos);
view.setZoom(18);
});

How to transform MapTile image to to view

I've created a tile set of an image using MapTiler. MapTiler generates a OL 2 script that centers the tiled image in the viewing window with the following code:
var map, layer;
var mapBounds = new OpenLayers.Bounds(0.000000, -9350.000000, 14450.000000, 0.000000);
var mapMinZoom = 0;
var mapMaxZoom = 6;
var mapMaxResolution = 1.000000;
var gridBounds = new OpenLayers.Bounds(0.000000, -9350.000000, 14450.000000, 0.000000);
function init() {
var options = {
controls: [],
maxExtent : gridBounds,
minResolution: mapMaxResolution,
numZoomLevels: mapMaxZoom+1
};
map = new OpenLayers.Map('map', options);
layer = new OpenLayers.Layer.XYZ( "MapTiler layer", "${z}/${x}/${y}.png", {
transitionEffect: 'resize',
tileSize: new OpenLayers.Size(256, 256),
tileOrigin: new OpenLayers.LonLat(gridBounds.left, gridBounds.top)
});
map.addLayer(layer);
map.zoomToExtent(mapBounds);
I want to use OL3 to display the tiled map but do not know how to implement equivalent OL3 methods to achieve this. Using the following script I can display the tiled image but I cannot figure out how to center the tiles to in the view.
map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM({
url: map_path + '{z}/{x}/{y}.png'
})
})
],
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
I've inspected the map extent which turns out to be:
-20037508.342789244,-20037508.342789244,20037508.342789244,20037508.342789244
My tiled image extent is given in the OL2 code, but I don't known how to use this information in OL3. I think it might have something to do with a transformation or fitExtent but without further direction, it seems I'm just guessing at what to do.
You will have to create a pixel projection for this to work properly. Then you can use fit (replacement for the former fitExtent), as you already suspected, to zoom to the full extent of the image.
The whole OpenLayers 2 code translated to OpenLayers 3 would look like this:
var mapBounds = [0.000000, -9350.000000, 14450.000000, 0.000000];
var mapMaxZoom = 6;
var gridBounds = [0.000000, -9350.000000, 14450.000000, 0.000000];
var projection = new ol.proj.Projection({
code: 'pixels',
units: 'pixels',
extent: gridBounds
});
var map = new ol.Map({
target: 'map',
view: new ol.View({
extent: mapBounds,
projection: projection
})
});
var layer = new ol.layer.Tile({
source: new ol.source.XYZ({
url: '{z}/{x}/{y}.png',
projection: projection,
maxZoom: mapMaxZoom
})
});
map.addLayer(layer);
map.getView().fit(mapBounds, map.getSize());

How do I dynamically load GeoJSON data, based on the map extent, into my OpenLayers 3.5.0 map layer?

I am migrating from OpenLayers 3.2.0 to 3.5.0 and am having trouble loading my GeoJSON data into my vector layer. I have it working, but I'm transforming the geometry of the features from my GeoJSON data source before I add them to my vector source.
Is there a way to make OpenLayers 3.5.0 apply the transformation automatically?
The data from my GeoJSON data source uses the EPSG:4326, I believe that I need to re-project the geometries to EPSG:3857 in order to display them on my map. The GeoJSON data source has the projection information in it's crs attribute and my vector source also has it's projection set. Still, the feature geometries are not transformed on their own.
I need to pass the bounds of the viewable map area via the URL to my GeoJSON data source, I do not want to load all of the data at once. I have a loader function on my vector source that gets the current map extent and builds the URL for the request.
Sample Data from my GeoJSON source is available, it validates through a linter and I believe it to be reasonable.
Below is the current code that I am using.
var vectorFormat = new ol.format.GeoJSON();
var featureStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill(
{color: 'rgba(255, 69, 0, 0.75)'}),
stroke: new ol.style.Stroke(
{color: 'rgba(255, 0, 0, 0.95)', width: 1})
})
});
var vectorSource = new ol.source.Vector({
projection: new ol.proj.Projection({'code':'EPSG:3857'}),
strategy: ol.loadingstrategy.bbox,
loader: function(extent, resolution, projection) {
var coordinate1 = ol.proj.transform([extent[0], extent[1]],
'ESPG:3857', 'EPSG:4326')
var coordinate2 = ol.proj.transform([extent[2], extent[3]],
'ESPG:3857', 'EPSG:4326')
var url = 'api/sites/geo/bounds/4326/' + coordinate1[1]
+ ',' + coordinate1[0] + '/' + coordinate2[1] + ','
+ coordinate2[0] + "/";
$.ajax({
url: url,
dataType: 'json'
}).then(function(response) {
var features = vectorFormat.readFeatures(response);
var transformFn = ol.proj.getTransform(
response.crs.properties.name, projection);
for(index in features) {
var feature = features[index];
feature.getGeometry().applyTransform(transformFn);
}
vectorSource.addFeatures(features);
});
}
});
this.state.map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Vector({
source: vectorSource,
style: featureStyle
})
],
view: new ol.View({
center: this.transformToOl(this.state.center),
zoom: this.state.zoom
})
});
Any help or pointers in the right direction would be greatly appreciated. :-D
Yes, OpenLayers can do the reprojection for you. You don't even have to set the projection on the source. The geometries will be automatically reprojected to the view projection.
var vectorSource = new ol.source.Vector({
url: 'file.json',
format: new ol.format.GeoJSON()
});
http://jsfiddle.net/h9zwjf88/
Update
In case you want to you use a custom loader, you can specify the target projection when parsing the features (see also ol.format.GeoJSON.html#readFeatures):
var vectorSource = new ol.source.Vector({
strategy: ol.loadingstrategy.bbox,
loader: function(extent, resolution, projection) {
$.ajax(url).then(function(response) {
var features = format.readFeatures(response,
{featureProjection: 'EPSG:3857'});
vectorSource.addFeatures(features);
});
}
});
http://jsfiddle.net/h9zwjf88/1/

Problems reading GML file (not reprojected)

I am trying to read a GML in openlayers 3.4.0 file with this code
var from = ol.proj.get("EPSG:4326");
var to = ol.proj.get("EPSG:3857");
var gml = new ol.source.StaticVector({
format: new ol.format.GML2({dataProjection: from,
featureProjection: to}),
projection: 'EPSG:3857',
url: 'test_4326.gml'
});
var vectorLayer = new ol.layer.Vector({
source: gml
});
var map;
function init(){
map = new ol.Map({
layers: [vectorLayer],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
}
that works fine with KML or GeoJSON (changing ol.format and removing relative parameters) but not with GML file (also without parameters in ol.format.GML2), I did some try with different gml files but nothing is working. It seems that the coordinates are nor reprojected during the reading phase.
Which is the correct way to read a GMl file?
The test is at http://kili.aspix.it/ol/testGML.html
The way to do this currently is to use a normal ol.source.Vector, fetch the data using XHR manually and do the parsing directly on the format so you can specify all the options to the readFeatures function. After that you'll add the features to the source. For example:
var vector = new ol.layer.Vector({
source: new ol.source.Vector()
});
var format = new ol.format.GML2();
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "gml.xml", true);
xmlhttp.onload = function() {
var xmlDoc = xmlhttp.responseXML;
var features = format.readFeatures(xmlDoc, {
featureProjection: 'EPSG:3857',
dataProjection: 'EPSG:4326'
});
vector.getSource().addFeatures(features);
};
xmlhttp.send();

Resources