Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Openlayers 4: Changing the draw order of selected features

I have a single vector layer in OpenLayers 4 (4.4.1). The layer has several features with LineString geometries. Some of the features overlap.

If I click at a point where features overlap, I want only one of the features to be drawn as selected. The others should still be available for selection later (by feature id in a separate UI selection list).

If I click on another feature id (in the separate UI selection List) that feature should be drawn as selected, and the previously selected should not be drawn as selected, but still available in the selection list.

This works, but it is only the first (default) selected feature that seems to be drawn at the top.

Image below shows when feature id 10049 is marked as selected. The first element in the selection is drawn correctly

Image below shows when feature id 10048 is marked as selected. The second element in the selection is drawn below the first

If I click somewhere on the southmost feature where they do not overlap, it is drawn correctly as selected on top.

The southmost feature is drawn correctly if clicked where there is no overlap

To keep track of the feature that needs to be visually selected there is a variable:

var multiselectPrimaryId = 0;

I use the following selectInteraction code:

selectInteraction.on('select', function (e) {
    e.deselected.forEach(function (feature) {
        feature.setStyle(null);
    });
    if (e.selected.length <= 1) {
        $("#multipleHitWindow").hide();
        multiselectPrimaryId = 0;
        if (e.selected.length == 0) {
            return;
        }
    }
    var features = e.selected;
    if (multiselectPrimaryId == 0) {
        multiselectPrimaryId = features[0].getId();
    }
    if (features.length > 1) {
        var text = "Multiple hits: ";
        features.forEach(function (elem, index, array) {
            text += "<a href='javascript:changeSelectedFeature("
                 + elem.getId() + ")'>" + elem.getId() + "</a>  &nbsp;";
            if (elem.getId() == multiselectPrimaryId) {
                elem.setStyle(selectedStyleFunction);
            }
        });
        $('#multipleHit').html(text);
        $("#multipleHitWindow").show();
    }
    else {
        features[0].setStyle(selectedStyleFunction);
    }
});

And I call this function from a dynamically created list of link:

function changeSelectedFeature(id) {
    multiselectPrimaryId = id;
    var featuresArray = selectInteraction.getFeatures().getArray().slice(0);
    var event = new ol.interaction.Select.Event()
    event.deselected = featuresArray;
    event.selected = featuresArray;
    event.type = 'select';
    event.target = selectInteraction;
    event.mapBrowserEvent = map.mapBrowserEventHandler_;
    selectInteraction.dispatchEvent(event);
}

How can I get the one with selectedStyle set to be drawn at the top? I have tried to add a zIndex to the selectedStyle. But it does not seem to have any effect.

Here is a JsFiddle: https://jsfiddle.net/5j6c6mgo/7/ . There are some other minor issues with the selection, but hopefully you will able to see the behaviour that I described above.

like image 876
Tommy Avatar asked Oct 12 '17 12:10

Tommy


1 Answers

I have a single vector layer ... The layer has several features with LineString geometries. Some of the features overlap.

I think you would need the LineString geometries to be in separate Layers for you to be able to use 'zIndex' - you would do this by calling 'setZIndex' on the layer in question. This will easily allow you to set the draw order at runtime.

Other than that the vectors are going to be displayed in their initial draw order and short of redrawing changing their draw order isn't possible.

like image 73
Fraser Avatar answered Nov 09 '22 07:11

Fraser