[GIS] OpenLayers adding circle feature with same vectorSource increases opacity of all

feature-layeropenlayersopenstreetmapvectorvector-layer

Background

Specs

  • OpenLayers 4.4.1
  • OSM

I'm fairly new to OpenLayers and have never used vectors before (primarily because I found out that I was using OpenLayers version 1, and had to relearn everything).

My application adds circles to a map relating to a position with a specific radius indicating position accuracy.

In its operation, multiple circles are added to the map at different times.

This is my code for loading the map:

var map = new ol.Map({
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      })
    ],
    target: 'mapdiv',
    controls: ol.control.defaults({
      attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
        collapsible: false
      })
    }),
    view: new ol.View({
      //center: [0, 0],
      zoom: 16
    })
  });

  //this is where all map 'features' (circles) are stored
  var vectorSource = new ol.source.Vector({
   projection: 'EPSG:4326'
  });

As you can see, I load the 'vector source' right after the map as I understood that it holds all 'vectors' which are displayed on the map so long as you specify it as the 'source'.

This is the code I use to generate the circle (source) (I tweaked it at getPointResolution because the OP made a mistake):

  //code from https://stackoverflow.com/a/28299599
  function addCircle(map, vectorSource, radius) {
    var view = map.getView();
    var projection = view.getProjection();
    var resolutionAtEquator = view.getResolution();
    var center = view.getCenter();
    var pointResolution = ol.proj.getPointResolution(projection, resolutionAtEquator, center);
    var resolutionFactor = resolutionAtEquator/pointResolution;
    var radius = (radius / ol.proj.METERS_PER_UNIT.m) * resolutionFactor;


    var circle = new ol.geom.Circle(center, radius);
    var circleFeature = new ol.Feature(circle);

    // vector layer
    vectorSource.addFeature(circleFeature);
    var vectorLayer = new ol.layer.Vector({
     source: vectorSource
    });

    map.addLayer(vectorLayer);
  }

Problem

Loading one circle goes normally, adds a blue stroked, opaque circle at the specified location with specified radius.

Loading a second circle appears more opaque than the last. Moving the map to the previous circle, it is also more opaque.

With each added circle, the apparent opacity increases for all displayed circles.

Running vectorLayer.getOpacity() in every circle generation results in 1, when clearly the circle is translucent, becoming increasingly opaque with every new circle.

Summary

Looking around, it appears that often it is the case that the developer is reloading the same circle over and over until many are stacked on top of one another. It almost seems like this is the case for me too, except I've triple-checked that I'm only running addCircle() once and the circle is in a different position than the last.

Is it possible that OpenLayers is redrawing all previous circles with every new circle?

Maybe this isn't related to getOpacity but has to do with the color as an rgba() combination…

Question

I want every circle to remain the same after drawing new circles. The default opacity and color is fine.

Am I doing something wrong?

UPDATE: Here's a fiddle as an example – https://jsfiddle.net/f5zrLt20/5/

Best Answer

The problem you are having is that with every call you are adding new layer to map and every time you are adding feature to the same source, so more and more features are overlaying each other every time.

First layer has one feature. Second has two etc and so opacity seems to be changing.

Define the layer when defining the vectorSource:

var layer = null;

//this is where all map 'features' (circles) are stored
var vectorSource = new ol.source.Vector({
  projection: 'EPSG:4326'
});

And check if it exists on creating a new circle:

// If layer is not yet set, create new layer and add it to map
if (!layer) {
  vectorSource.addFeature(circleFeature);
  layer = new ol.layer.Vector({
    source: vectorSource
  });
  map.addLayer(layer);
}
//Otherwise, just add feature to the source
else {
  layer.getSource().addFeature(circleFeature);
}

Here's a fiddle of it working once this is done: fiddle.

At first I thought it might be a style issue, that's why I'm changing the style in the fiddle.

Related Question