Search code examples
openlayers

Openlayers 4 - Modify interaction & multiple feature at the same coordinate


I have a modify interaction enabled on a vector layer with multiple features. It work fine to move a feature to a new position. However if there are more features on the same coordinate, then all of then moved at the same time. See example on codepen.

var raster = new ol.layer.Tile({
    source: new ol.source.OSM()
  });

var data = new ol.Collection();

  data.push(new ol.Feature({
    geometry: new ol.geom.Point([0, 0])
  }));

  var f = new ol.Feature({
    geometry: new ol.geom.Point([0, 0])
  });
  f.setStyle(new ol.style.Style({
                image: new ol.style.Circle({
                    radius: 10,
                    fill: new ol.style.Fill({
                        color: [255, 255, 255, 0.5]
                    }),
                    zIndex: Infinity
                }),
            }));

  data.push(f);

  var vector = new ol.layer.Vector({
    source: new ol.source.Vector({
      features: data
    })
  });


  var modify = new ol.interaction.Modify({
    features: data
  });

  var map = new ol.Map({
    interactions: ol.interaction.defaults().extend([modify]),
    layers: [raster, vector],
    target: 'map',
    view: new ol.View({
      center: [0, 0],
      zoom: 12
    })
  });

Are there any way to avoid that? The only solutions I have found are:

  1. I have a select interation to select the feature
  2. Use translate interaction to move one of the features

or

  1. At pointer move event and detect if one or more features are at the coordinate and then select one of then
  2. Add the selected feature to modify feature layer and move it

Any other way?

Regrads RM


Solution

  • There is another way. You can register a 'pointermove' handler on the map, in which you get the topmost feature, and set it as the only feature on the source that the Modify interaction works on. See https://codepen.io/ahocevar/pen/YxjyRd for the full example.

    Other than in your code, you'll connect the Modify interaction to a source instead of a collection, and that source (modifySource) is separate from the vector layer's source and initially empty. In the pointermove handler, you add just a single feature to that source:

    function pointermove(e) {
      if (e.dragging) {
        return;
      }
      var features = map.getFeaturesAtPixel(e.pixel, {
        layerFilter: function(l) {
          return l == vector;
        }
      });
      if (features && features[0] != modifySource.getFeatures()[0]) {
        modifySource.clear();
        modifySource.addFeature(features[0]);
      }
    }
    map.on("pointermove", pointermove);
    

    Also note that this handler must be registered before the Modify interaction is added to the map.