Sunday 25 December 2016

Style GeoJSON layers depending on attributes in Openlayers 3


I'm trying to mimic most of the great google-vector-layers and leaflet-vector-layers from Jason Sanford (https://github.com/JasonSanford) to easily display, style and add customized popups for data from Postgis-databases. This works in combination with a modified version of the PHP-Database-GeoJSON from Bryan McBride.


Until now I got a lot of things to work (load Postgis-layers, by passing field-nemes and a WHERE-cause, creating layer-individual popups, ...) but I'm actually having problems to implement a styling function.


In the examples mentioned above they pass a symbology-object to a constructor that cares about the styling of the layer. I've tried to use and adapt this code so that it could work in Openlayers 3 as well, but I need help from experienced developers. Could someone have a look at the code and point me in the right direction?


The layer definitions, that are used to create new ol3Vectors look like this:


n2k_dh_l = new ol3Vector({
map: map,
title: "Natura 2000 Habitats Directive",
attribution: "
RĂ©seau Natura 2000 Habitats Directive",

geotable: "n2k_dh",
fields: "gid as id,surfha,sitecode,sitename",
where: "sitename ilike '%moselle%'",
minResolution: 0.01,
maxResolution: 50,
content: "

BH {sitecode}


{sitename}
{surfha} ha

",
symbology: {
type: "single",
styleOptions: {
fill: "rgba(100,250,0,0.1)",

color: "green",
width: 2
}
}
});

communes = new ol3Vector({
map: map,
title: "Communes",
attribution: "
Communes ACT",

geotable: "communes",
fields: "gid as id,surfha,commune,stat",
where: "",
minResolution: 0.01,
maxResolution: 50,
content: "

{commune}


{stat}
{surfha} ha

",
symbology:{
type: "unique",
property: "stat",
values: [

{
value: "XYZ",
styleOptions: {
fill: "rgba(100,250,0,0.1)",
color: "green",
width: 2
}},
{
value: "UVZ",
styleOptions: {

fill: "rgba(100,250,0,0.1)",
color: "red",
width: 2
}},
{
value: "",
styleOptions: {
fill: "rgba(100,250,0,0.1)",
color: "grey",
width: 2

}}
]
}
});

Inside the ol3Vector-constructor I try to implement a function to style features based on the symbology defined in the layer options.


When I pass the style options for a layer with a single style directly like this:


style: new ol.style.Style({
fill: new ol.style.Fill({color: options.symbology.styleOptions.fill}),
stroke: new ol.style.Stroke({

color: options.symbology.styleOptions.color,
width: options.symbology.styleOptions.width
})
}),

everything works fine, but the following styling function _getStyledFeatures inside the ol3Vector-function I would like to use, causes me headache.


Maybe someone has an idea how to get that work.


function ol3Vector(options){

var options = options || {};


newLayer = new ol.layer.Vector({
title: options.title,
visible: false,
minResolution: options.minResolution,
maxResolution: options.maxResolution,
content: options.content,
symbology: options.symbology,
style: _getStyledFeatures,
source: new ol.source.Vector({

projection: 'EPSG:4326',
attributions: [new ol.Attribution ({html: options.attribution })],
strategy: ol.loadingstrategy.bbox,
loader: function(extent, resolution, projection) {
var extent = ol.proj.transformExtent(extent, projection.getCode(), ol.proj.get('EPSG:4326').getCode());
$.ajax({
type: 'GET',
url: "./mapdata/get_geojson.php?"+
"geotable=" + options.geotable +
"&fields=" + options.fields +

"&where=" + options.where +
"&bbox=" + extent.join(','),
context: this
}).done (function (data) {
var format = new ol.format.GeoJSON();
this.addFeatures (format.readFeatures(data,{
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
}));
});

}
})

})


return newLayer;
};

ol.inherits(ol3Vector, ol.layer.Vector);




function _getStyledFeatures(feature) {
//
// Create empty styleOptions and feartureStyles objects to add to, or leave as is if no symbology can be found
//
var styleOptions = {};
var featureStyles = {};


//
// get properties.
//
var atts = feature.getProperties();

//
// Is there a symbology set for this layer?
// if not, style with default style
var defaultStyle = new ol.style.Style({
fill: new ol.style.Fill({color: 'rgba(255,255,255,0.4)'}),

stroke: new ol.style.Stroke({
color: '#3399CC',
width: 1.25
})
});
if (!options.symbology) {
return defaultStyle;
}
else (options.symbology) {
switch (options.symbology.type) {

case "single":
//
// Its a single symbology for all features so just set the key/value pairs in styleOptions
//
for (var key in options.symbology.styleOptions) {
styleOptions[key] = options.symbology.styleOptions[key];
if (styleOptions.title) {
for (var prop in atts) {
var re = new RegExp("{" + prop + "}", "g");
styleOptions.title = styleOptions.title.replace(re, atts[prop]);

featureStyles = new ol.style.Style(styleOptions){
fill: new ol.style.Fill({color: styleOptions.fill}),
stroke: new ol.style.Stroke({
color: styleOptions.color,
width: styleOptions.width
})
};
}
}
}

break;
case "unique":
//
// Its a unique symbology. Check if the features property value matches that in the symbology and style accordingly
//
var att = options.symbology.property;
for (var i = 0, len = options.symbology.values.length; i < len; i++) {
if (atts[att] == options.symbology.values[i].value) {
for (var key in options.symbology.values[i].styleOptions) {
styleOptions[key] = options.symbology.values[i].styleOptions[key];

if (styleOptions.title) {
for (var prop in atts) {
var re = new RegExp("{" + prop + "}", "g");
styleOptions.title = styleOptions.title.replace(re, atts[prop]);
featureStyles = new ol.style.Style(styleOptions){
fill: new ol.style.Fill({color: styleOptions.fill}),
stroke: new ol.style.Stroke({
color: styleOptions.color,
width: styleOptions.width
})

};
}
}
}
}
}
break;
case "range":
//
// Its a range symbology. Check if the features property value is in the range set in the symbology and style accordingly

//
var att = options.symbology.property;
for (var i = 0, len = options.symbology.ranges.length; i < len; i++) {
if (atts[att] >= options.symbology.ranges[i].range[0] && atts[att] <= options.symbology.ranges[i].range[1]) {
for (var key in options.symbology.ranges[i].styleOptions) {
styleOptions[key] = options.symbology.ranges[i].styleOptions[key];
if (styleOptions.title) {
for (var prop in atts) {
var re = new RegExp("{" + prop + "}", "g");
styleOptions.title = styleOptions.title.replace(re, atts[prop]);

featureStyles = new ol.style.Style(styleOptions){
fill: new ol.style.Fill({color: styleOptions.fill}),
stroke: new ol.style.Stroke({
color: styleOptions.color,
width: styleOptions.width
})
};
}
}
}

}
}
break;
}
}
return featureStyles;
}


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...