2

When modifying a feature, there is the option to delete a single vertex. According to the docs it says:

removePoint(){boolean}: Removes the vertex currently being pointed.

(https://openlayers.org/en/latest/apidoc/ol.interaction.Modify.html)

Since I work on mobile devices, I would like to present a popup with a delete button next to the a vertex if a user clicks or hovers over it. Therefore I need the coordinates of this vertex. I can see the vertex indicated on the map with a different style, but how can I get it or its coordinates? It must be somewhere in some selection because the automatic "pointing to" style and removePoint method works per se fine.

Chris
  • 4,238
  • 4
  • 28
  • 49

2 Answers2

2

Here is a solution that use a button to delete a vertex. The button is shown or hidden if there is a vertex to delete (it could be a popup).

It uses:

  • condition option to show the button if there is a point near the click
  • insertVertexCondition option to hide the button (there is no vertex here)
  • modifystart and modifyend event to hide the button (we are moving and we don't want the button to be visible)
  • removePoint function when click on the button

The button is not show if you're moving or if there is no point to delete. It doesn't rely on features that are not documented or private.

You can see it in action here.

var btElt = document.getElementById("delete");

// Modify interaction
var mod = new ol.interaction.Modify({
  source: vector.getSource(),
  // Show on select
  condition: function(e){
    // Check if there is a feature to select
    var f = this.getMap().getFeaturesAtPixel(e.pixel,{
      hitTolerance:5
    });
    if (f) {
      var p0 = e.pixel;
      var p1 = f[0].getGeometry().getClosestPoint(e.coordinate);
      p1 = this.getMap().getPixelFromCoordinate(p1);
      var dx = p0[0]-p1[0];
      var dy = p0[1]-p1[1];
      if (Math.sqrt(dx*dx+dy*dy) > 8) {
        f = null;
      }
    }
    if (f) btElt.style.display = "inline-block";
    else btElt.style.display = "none";

    return true;
  },
  // Hide on insert
  insertVertexCondition: function(e) {
    btElt.style.display = "none";
    return true;
  }
});
// Hide on modifying
mod.on(['modifystart','modifyend'], function(){
  btElt.style.display = "none";
});
map.addInteraction (mod);

// Delete vertex when click the button
function deleteVertex() {
  mod.removePoint();
  btElt.style.display = "none";
}
Viglino Jean-Marc
  • 1,371
  • 8
  • 6
  • Ah I was not aware of the getFeaturesAtPixel method. I modified it a bit and it works very nice and smooth with touch devices. Thanks a lot. – Chris Jun 08 '18 at 18:47
  • 1
    I've put a working example with a popup and/or a menu here: http://viglino.github.io/ol-ext/examples/interaction/map.interaction.modifytouch.html – Viglino Jean-Marc Jun 11 '18 at 07:17
0

Alright digging into the source code I came up with a kinda ugly but so far working solution. For the record, this is the code.

this.modify = new Modify({
    features: new Collection([this.selectedFeature]),
    pixelTolerance:30,
    condition: (event)=>{
        if(this.modify["lastPointerEvent_"] && this.modify["vertexFeature_"])
            this.removePointPopup.setPosition(this.modify["lastPointerEvent_"].coordinate);
        else
            this.removePointPopup.setPosition(undefined);
        return true;
    }
});
this.modify.on("modifyend",ev=>{
   this.removePointPopup.setPosition(ev.target["lastPointerEvent_"].coordinate);
})

[...]

removePoint(){
     this.modify.removePoint()
     this.removePointPopup.setPosition(undefined);
}

If someone knows about a nicer solution, feel free to post it.

Chris
  • 4,238
  • 4
  • 28
  • 49