2

firstly I'm new to Openlayers/JS as a whole and fairly inexperienced with programming in general so there might be other problems with my code that I'm not aware of.

I am using the latest version of Openlayers (5.3.0).

My program currently passes GeoJson formatted data via Ajax to be displayed on an Openlayers map. It creates the map, view and a layer for the features to be displayed on. When I press a "Go" button on the page, the features are loaded onto the map successfully. In my case the features are just simple points with latitude/longitude using a png marker to visualise. The GeoJson looks like this in C# before being serialised and sent to JS on my page for deserialisation:

{{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -1.549077,
          53.800755
        ]
      },
      "properties": {
        "GPSKey": 1,
        "Latitude": 53.800755,
        "Longitude": -1.549077,
        "TimeAdded": "2019-01-15T12:10:16",
        "IconPath": "pinred.png"
      },
      "ID": 1,
      "IconPath": null
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -1.545077,
          53.800755
        ]
      },
      "properties": {
        "GPSKey": 2,
        "Latitude": 53.800755,
        "Longitude": -1.545077,
        "TimeAdded": "2019-01-15T12:10:16",
        "IconPath": "pinred.png"
      },
      "ID": 2,
      "IconPath": null
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -1.524043,
          53.773222
        ]
      },
      "properties": {
        "GPSKey": 3,
        "Latitude": 53.773222,
        "Longitude": -1.524043,
        "TimeAdded": "2019-01-15T12:10:16",
        "IconPath": ""
      },
      "ID": 3,
      "IconPath": null
    }
  ]
}}

The JS receives the above serialised and uses this code to add it to the layer for viewing:

var geojsonFormat = new ol.format.GeoJSON({
        dataProjection: "EPSG:4326",
        featureProjection: "EPSG:3857"
    });//creates a format definition

    jsonDecoded = JSON.parse(result); /

    if (jsonDecoded.features.length > 0) {
        for (var i = 0; i < jsonDecoded.features.length; i++) {
            vectorSource.addFeature(geojsonFormat.readFeature(jsonDecoded.features[i], { featureProjection: "EPSG:3857" }));

        }

    }/

The vector layer it gets added to looks like this:

var vectorLayer = new ol.layer.Vector({
    source: vectorSource,
    style: iconStyleFunc()
});

And the iconStyleFunc() looks like this:

function iconStyleFunc() {

    var zIndex = 1;

    var iconName = null;

    if (iconName == null) {
        iconName = "pinother.png"
    };


    iconStyle = [new ol.style.Style({
        image: new ol.style.Icon(({
            anchor: [0.5, 36], 
            anchorXUnits: "fraction",
            anchorYUnits: "pixels",
            opacity: 1,
            src: "images/" + iconName,  
            zIndex: zIndex
        })),
        zIndex: zIndex
    })];
return iconStyle;

This works fine for styling all the features with the icon "pinother.png". I have no problem displaying the points on the map when I press the button.

What I'd like to do is apply styling based on the icon path in the properties of each feature's GeoJson "iconpath", so that any feature having a "pinred.png" would use that instead of the default "pinother.png", and so on with various icons I might need to add in the future.

I'm not sure how to read this property of each feature and how I would best implement it in the styling function. The way I envisaged it was iterating through features using the iconStyleFunc(), reading the IconPath property for each feature, appending that value to the "src/images/" path in the iconStyleFunc() and styling the feature appropriately.

1 Answers1

3

Using the feature argument of the style function you can get properties of the feature

function iconStyleFunc(feature) {

    var zIndex = 1;

    var iconName = feature.get("IconPath") || "pinother.png";

    iconStyle = [new ol.style.Style({
        image: new ol.style.Icon(({
            anchor: [0.5, 36], 
            anchorXUnits: "fraction",
            anchorYUnits: "pixels",
            opacity: 1,
            src: "images/" + iconName,  
            zIndex: zIndex
        })),
        zIndex: zIndex
    })];
return iconStyle;
Mike
  • 16,042
  • 2
  • 14
  • 30
  • Thank you Mike! I think I was overcomplicating things and trying to write huge functions for iterating over each feature and applying a style when Openlayers already has that built in. I thought I'd have to pass the feature explicitly to the iconStyleFunc in the Vectorlayer "Style" property but simply calling iconStyleFunc will be enough to get it to work. – Hiram Hackenbacker Jan 24 '19 at 13:23
  • 1
    I can't understand ho you're passing the feature variable. Could you provide more information? Because what I see here, will make every icons looks the same, isn't it? – Raphaël Balet May 20 '21 at 12:27
  • It is using the `IconPath` property of the feature to produce icons specific to each feature, – Mike May 20 '21 at 12:45
  • I'm with @RaphaëlBalet - how is the `feature` passed to `iconStyleFunc` please? Otherwise it looks great. – valoukh Nov 02 '21 at 17:13
  • OpenLayers calls the style function for each feature whenever the layer is rendered. The style should be defined using only the function name `style: iconStyleFunc` - the function should not be called by adding `()` in the layer setup – Mike Nov 02 '21 at 17:22