[GIS] OpenLayers 3 draw polygon to select features

openlayerspolygon

Update

I have now got this working and this plunk shows a working example.


I have a set of points on a vector layer and I am allowing the user to draw a polygon on another layer of the map. I want to select all the points inside the polygon.

I have got this to work, but only temporarily. When the user finished the polygon, the points are selected but then immediately unselected again. I cannot figure out why.

I have made the function by referencing an example: DragBox

When I replace my polygon with a dragbox, the selections persist. But when I use interaction.Draw to make a polygon, the selection does not persist.

The javascript code is below, and here is a plunker of the feature.

var map;

//Add map layer
var baseLayer = new ol.layer.Tile({
    source : new ol.source.OSM()
});

//Add view
var view = new ol.View({
    //projection is about how we represent a global thing on a flat thing.
    projection : 'EPSG:900913',
    center : ol.proj.fromLonLat([-2.5,51.1]),
    zoom:4,
});

//Add layer of point features
var pointsLayer = new ol.layer.Vector({
    title: 'random points',
    source : new ol.source.Vector({
        url : './assets/Points.json',
        format : new ol.format.GeoJSON()
    })
});

//initialise map (called at the end)
function init(){
    map = new ol.Map({
        target : 'map',
        //the type of rendered we want to use.
        renderer : 'canvas',
        view : view
    });
    map.addLayer(baseLayer);
    map.addLayer(pointsLayer);
}

init();

//////////// ADD SELECTION

//add ol.collection to hold all selected features
var select = new ol.interaction.Select();
map.addInteraction(select);
var selectedFeatures = select.getFeatures();

//////////// ADD DRAWING

// Add drawing vector source
var drawingSource = new ol.source.Vector();

//Add drawing layer
var drawingLayer = new ol.layer.Vector({
    source: drawingSource
});
map.addLayer(drawingLayer);

//declare interactions globally so we can attach listeners to them later.
var draw;
var modify;



// Drawing interaction
draw = new ol.interaction.Draw({
    source : drawingSource,
    type : 'Polygon',
    //only draw when Ctrl is pressed.
    condition : ol.events.condition.platformModifierKeyOnly
});
map.addInteraction(draw);

draw.on('drawend', function(e) {

    // features that intersect the box are added to the collection of
    // selected features, and their names are displayed in the "info"
    // div
    var extent = e.feature.getGeometry().getExtent();
    pointsLayer.getSource().forEachFeatureIntersectingExtent(extent, function(feature) {
        selectedFeatures.push(feature);
    });
});

//////////// SUPPORTING FUNCTIONS

//turn the cursor into a pointer if it's over an image.
map.on('pointermove',function(evt){
    if(evt.dragging){
        return;
    }
    var pixel = map.getEventPixel(evt.originalEvent);
    //called with pixel, callback. Detects layers that have a colour value
    //at a pixel.
    var hit = map.forEachFeatureAtPixel(pixel,function(feature){
        return true;
    });
    map.getTargetElement().style.cursor = hit? 'pointer' : '';
});

Best Answer

This is happening only when you click on last vertex of your polygon to close the polygon. If you double click to close it no such error occurs. The problem comes because you have select and draw interactions active at the same time. So single click for closing the polygon fires the unselect action of select interaction. To overcome the issue do as follows

  1. create a drawstart event and disable the select interaction

    draw.on ('drawstart',function(e) {
    select.setActive(false);
    })
    
  2. within the drawend event you allready have, re-enable the select interaction with delay 300 ms. (251ms is the time ol needs to distinguish single click from double click)

    draw.on('drawend', function(e) {
    e.preventDefault();
    setTimeout(function(){ 
     select.setActive(true); 
    }, 300);