9
votes

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.

1
Can you make fiddle of current status?artgb
With a select interaction, you shouldn't need to update feature styles manually. You should be able to update the interaction's selected feature set by grabbing the feature collection with var features = selectInteraction.getFeatures(), clearing the features collection, and then adding the new selected feature to features.user8651755
@artgb: I will try to get a fiddle running as soon as possible. Right now it uses non publicly available data, so I need to do some changes.Tommy
@Wyatt: Perhaps I'm using the selection interaction in a wrong way. But what I want is to get all features at the click, but only show one of them as selected. And in a later step I want to be able to cycle through the other features that was selected, one at a time. Another solution (perhaps correct solution?) is to draw a separate layer and keep track of this myself, but it would be nice if the selection interaction could help.Tommy

1 Answers

4
votes

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.