2

I want to implement a styling/labeling function, which takes layer-options and uses them while creating new ol.layer.Vector objects in a function called ol3Vectors.

The features that should be used for labeling are passed with the label: "" - option.

First I define my layers with their options:

n2k_do_l = new ol3Vector({
            title: "Natura 2000 Birds Directive",
            attribution: "<br />Réseau Natura 2000 Birds Directive",
            geotable: "n2k_do",
            fields: "gid as id,sitecode,sitename,surfha",
            where: "",
            symbology: {
            type: "single",
            styleOptions: {
            fill: "rgba(100,250,0,0.1)",
            color: "magenta",
            width: 2
        }
        },    
            minResolution: 0.01,
            maxResolution: 50,
            content: "<p><strong> BD {sitecode}</strong><hr>{sitename}<br />{surfha} ha </p>",
            showLabels: true,
            label: "sitecode" //feature to be used for labeling 
});

n2k_dh_l = new ol3Vector({
            map: map,
            title: "Natura 2000 Habitats Directive",
            attribution: "<br />Réseau Natura 2000 Habitats Directive",
            geotable: "n2k_dh",
            fields: "gid as id,surfha,sitecode,sitename",
            where: "sitename ilike '%moselle%'",
            symbology: {
            type: "single",
            styleOptions: {
            fill: "rgba(100,250,0,0.1)",
            color: "green",
            width: 2
        }
        },  
            minResolution: 0.01,
            maxResolution: 50,
            content: "<p><strong> BH {sitecode}</strong><hr>{sitename}<br />{surfha} ha </p>",
            showLabels: true,
            label: "sitename" //feature to be used for labeling 
});


communes = new ol3Vector({
            map: map,
            title: "Communes",
            attribution: "<br />Communes ACT",
            geotable: "communes",
            fields: "gid as id,surfha,commune,stat",
            where: "",
            symbology:{
            type: "single",
        styleOptions: {
                    fill: "rgba(100,250,0,0.1)",
                    color: "green",
                    width: 2                
        }},
            minResolution: 0.01,
            maxResolution: 50,
            content: "<p><strong>{commune}</strong><hr>{stat}<br />{surfha} ha </p>",
            showLabels: true,
            label: "commune" //feature to be used for labeling  
});

When passing this layer-definitions to my ol3Vector-function, the layers are created, but only the last layer shows labels. The other layers show up, but without labels. I supposed that my labeling-function could create a layer-specific labels.

Here the code I use:

function ol3Vector(options){

newLayer = new ol.layer.Vector({
              title: options.title,
              visible: false,
              minResolution: options.minResolution,
              maxResolution: options.maxResolution,
              content: options.content,
              symbology: options.symbology,
              showLabels: options.showLabels,
              label: options.label,
              style: labelStyle, // labelled polygons with default styling
          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;
};

var styleCache ={};
function labelStyle(feature, resolution) {

    var text = "";

    text = feature.get(newLayer.get('label'));  // 'label' is only evaluated for the last layer 

    if (!styleCache[text]) {
         styleCache[text] = new ol.style.Style({
                stroke: new ol.style.Stroke({ color: [0, 153, 255, 1], width: 1.5 }),
                fill: new ol.style.Fill({ color: [0, 255, 0, 0.1] }),
                text: new ol.style.Text({
                    font: '15px Calibri,sans-serif',
                    text: text,
                    fill: new ol.style.Fill({
                        color: [255, 255, 255, 1]
                    }),
                    stroke: new ol.style.Stroke({
                        color: [0, 0, 0, 1],
                        width: 2
                    })
                })
            });
    }

    return styleCache[text];
}

EDIT: After trying a lot around I found out, that the layers are created one after the other while calling the page (layer-source is defined, without adding the layers to the map).

I thought, that each layer would create immediatly the corresponding styles for the layer. But this doesn't seem to be the case. The function for styling the layers is called only when the layers are added to the map (via layerswitcher). Only at this moment they refer to the newLayer-object, which is clearly the last one, that has been crated. Clear that the call of the

text = feature.get(newLayer.get('label'));   

only reflects the 'label'-value of the last layer.

Even if it is nice to undestand, I have already read and tryed a lot, but actually no idea how to change my code so that it would work.

So for me it seems that it would be necessary to create each layer including the labeling and keep it in the background (not assigning it to a map) until it gets called by the layerswitcher.

0

After a lot of reading, consulting poeple I finally found an answer from ahocevar to a related question How to set an ol.style.text using a source in OpenLayer, which finally helped me to solve my problem.

The important step was to wrap the style-function in an anonymous function like this, so that I could access all my option.parameters:

style: (function() {
here the code of the styling-function
...
}()

Using the following code, I can define both options

  • showLabel: (true/false) and
  • label: "field of Postgis-table used for labeling".

May this help someone who's dealing with similar probs.

    ol3Vector = function(options) {

    var options = {
        title: options.title,
        visible: false,
        geotable: options.geotable,
        fields: options.fields,
        where: options.where,
        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",
                    dataType: "json",
                    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"
                    }));

                });

            }
        }),
        minResolution: options.minResolution,
        maxResolution: options.maxResolution,
        content: options.content,
        symbology: options.symbology,
        showLabels: options.showLabels,
        label: options.label,
        style: (function() {          // style function needed to be wrapped in an anonymous function to get it work
            var layerLabel = "";
            if (!options.showLabels) {
                layerLabel = "";
            } else if (options.showLabels) {
                layerLabel = options.label;
            }
            var style = new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: [0, 153, 255, 1],
                    width: 1.5
                }),
                fill: new ol.style.Fill({
                    color: [0, 255, 0, 0.1]
                }),
                text: new ol.style.Text({
                    text: "",
                    font: "16px Calibri,sans-serif",
                    fill: new ol.style.Fill({
                        color: [255, 255, 255, 1]
                    }),
                    stroke: new ol.style.Stroke({
                        color: [0, 0, 0, 1],
                        width: 2.5
                    })
                })
            });
            var styles = [style];
            return function(feature, resolution) {
                style.getText().setText(feature.get(layerLabel));
                return styles;
            };
        })()
      };

      ol.layer.Vector.call(this, options);

    };

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.