1

I have a feature with multiple elements, every element has its own geometry and an ID.

Is possible to change the style of the feature and display the elements of the feature on the map like it's own ID? For example, I have three elements, a (id = 1), b (id = 1) and c (id = 2), I want to display them on the map with 1 (for a and b) and 2 (for c). Is possible to do it?

This is my code and the JSON explains what I mean with multiple id:

var bikeStyle = new ol.style.Style({
        image: new ol.style.Circle({
            radius: 15,
            fill: new ol.style.Fill({color: 'rgba(0, 200, 0, 1)'}),
            stroke: new ol.style.Stroke({color: 'green', width: 1})
        })
    });

var map = new ol.Map({
    target: 'map',
    layers: [

       ...

    ],
    
    view: new ol.View({
        center: ol.proj.fromLonLat([11.341868,44.494949]),
        zoom: 14
    })
});


source = new ol.source.Vector();

bike = new ol.layer.Vector({
    title: 'bikes',
    source: source,
    style: bikeStyle,
})

source.addFeatures(
  new ol.format.GeoJSON().readFeatures(bikes, {
    dataProjection: 'EPSG:4326',
    featureProjection: map.getView().getProjection()
  })
);

Where bike in source a json file like:

{
  "type": "FeatureCollection", 
      "features": [{"id": 1, "type": "Feature", "geometry": {"type": "Point", "coordinates": [x,y]}, "properties": {"id": 1, "resnumb": A}}],
      "features": [{"id": 13, "type": "Feature", "geometry": {"type": "Point", "coordinates": [x,y]}, "properties": {"id": 1, "resnumb": B}}],
      "features": [{"id": 2, "type": "Feature", "geometry": {"type": "Point", "coordinates": [x,y]}, "properties": {"id": 2, "resnumb": C}}]
}

As you can see each element has its own id.

6
  • 1
    openlayers.org/en/latest/examples/street-labels.html
    – JGH
    Commented Mar 1, 2022 at 14:00
  • What you call "feature" in your GeoJSON and what is "feature element", which are supposed to be several for each "feature"?
    – TomazicM
    Commented Mar 1, 2022 at 16:50
  • For a feature element I identify everything written after the word feature (id, geometry, ...)
    – Uderr
    Commented Mar 1, 2022 at 21:31
  • 1
    Please edit your question and add an example of GeoJSON for "I have three element, a (id = 1), b (id = 1) and c (id = 2)".
    – TomazicM
    Commented Mar 2, 2022 at 7:57
  • One more question: you want to change style according to id or just display id? Or both?
    – TomazicM
    Commented Mar 2, 2022 at 15:33

1 Answer 1

1

To have dynamic feature style where style changes depending on feature properties, you have to use style function. This function receives feature as the first parameter and should return style, which can be created depending on feature properties.

To avoid creating new styles again and again in the function, so called style cache is usually created, where already created styles are stored for use when needed.

In the code below, new style with random circle colors is created for each different id feature property:

function randomColor() {
  var r = Math.floor(Math.random() * 256);
  var g = Math.floor(Math.random() * 256);
  var b = Math.floor(Math.random() * 256);
  var color = [r, g, b];
  
  return(color);
}

var bikeStyleCache = {};
function createBikeStyle(id) {
  var strokeColor = randomColor();
  var fillColor = strokeColor.slice();
  fillColor[3] = 0.2;
  var bikeStyle = new ol.style.Style({
    image: new ol.style.Circle({
      radius: 15,
      stroke: new ol.style.Stroke({
        color: strokeColor,
        width: 2,
      }),
      fill: new ol.style.Fill({
        color: fillColor
      })
    }),
    text: new ol.style.Text({
      text: id.toString(),
      fill: new ol.style.Fill({
        color: 'black',
      })
    })
  });
  bikeStyleCache[id] = bikeStyle;
}

function getBikeStyle(id) {
  if (!bikeStyleCache[id]) {
    createBikeStyle(id);
  }
  return(bikeStyleCache[id]);
}

function styleFunction(feature, resolution) {
  return(getBikeStyle(feature.get('id')));
}

var source = new ol.source.Vector();
var bike = new ol.layer.Vector({
  title: 'bikes',
  source: source,
  style: styleFunction,
});

And by the way, GeoJSON sample from your question would not work correctly, since you define features attribute again and again, so only last assignment would stay. You have to do it once and features have to be in array:

{
  "type": "FeatureCollection",
  "features": [
    {"id": 1, "type": "Feature", "geometry": {"type": "Point", "coordinates": [10.224194550042373, 41.358221559689788]}, "properties": {"id": 1, "resnumb": 'A'}},
    {"id": 13, "type": "Feature", "geometry": {"type": "Point", "coordinates": [11.960078048414047, 40.779593726899229]}, "properties": {"id": 1, "resnumb": 'B'}},
    {"id": 2, "type": "Feature", "geometry": {"type": "Point", "coordinates": [11.519471533536832, 42.425232517404488]}, "properties": {"id": 2, "resnumb": 'C'}}
  ]
};
1
  • This is exactly what I was looking for, thank you so much!
    – Uderr
    Commented Mar 3, 2022 at 14:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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