Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing an OpenLayers Markers layer to draw on top, and having selectable layers beneath

I have an OpenLayers map with a raster base layer, a vector layer and a markers layer in that order. They display fine, in the correct order with the markers on top of the vectors, great.

But when I add a SelectFeature Control and point it to the vector layer, it is suddenly drawn above the markers layer, despite all efforts to raise the marker layer or setting the Z index. It seems that the SelectFeature control overrides all drawing order settings. Is this by design, or can I overcome this somehow?

The layer definitions:

var baselayer = new OpenLayers.Layer.WMS('Norden', 
'http://{myarcgisserver}/ArcGIS/services/mylayer/MapServer/WMSServer', {
    layers :'1,2',
    transparent :false,
    width :'auto',
    height :'auto',
    filter :null
}, {
    isBaseLayer: true,
    singleTile :true,
    ratio :1,
    alpha :false,
    transitionEffect :'resize'
});

var vectorLayer = new OpenLayers.Layer.Vector("Work orders", {
    projection: new OpenLayers.Projection("EPSG:2400"),
    strategies: [new OpenLayers.Strategy.Fixed(), refresh],
    protocol: new OpenLayers.Protocol.HTTP({
        url: "/WorkOrder/WorkOrders.ashx?output=geojson",
        format: new OpenLayers.Format.GeoJSON()
    })
});

var markerlayer = new OpenLayers.Layer.Markers("Markers", {
    projection: new OpenLayers.Projection("EPSG:2400"),
    displayInLayerSwitcher: false
}
);

The control definition:

var selectctrl = new OpenLayers.Control.SelectFeature(
    vectorLayer,
    {
        clickout: true,
        toggle: false,
        multiple: false,
        hover: false,
        toggleKey: "ctrlKey", // ctrl key removes from selection
        multipleKey: "shiftKey", // shift key adds to selection
        box: false
    }
);

Activation: (Without this, the layers draw in correct order)

map.addControl(selectctrl);

selectctrl.activate();

Edit: Found this in OpenLayers.Handler.Feature, where the "moveLayerToTop" feels like the culprit... Will try to overcome it, but if someone knows it to be impossible, please let me know!

/**
 * Method: activate 
 * Turn on the handler.  Returns false if the handler was already active.
 *
 * Returns:
 * {Boolean}
 */
activate: function() {
    var activated = false;
    if(OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
        this.moveLayerToTop();
        this.map.events.on({
            "removelayer": this.handleMapEvents,
            "changelayer": this.handleMapEvents,
            scope: this
        });
        activated = true;
    }
    return activated;
},
like image 363
Niklas Wulff Avatar asked Jan 18 '11 20:01

Niklas Wulff


2 Answers

The answer - if it's ok to call it that lies in the activate function that I mention above. I tried to override that and removed the call to moveLayerToTop, and it works like a charm.

EDIT: I ended up adding this code to a js file outside the OL code library, overriding the handlers activate function. This is because I would otherwise lose the change on an update of the OpenLayers code base.

OpenLayers.Handler.Feature.prototype.activate = function() {
    var activated = false;
    if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
        //this.moveLayerToTop();
        this.map.events.on({
            "removelayer": this.handleMapEvents,
            "changelayer": this.handleMapEvents,
            scope: this
        });
        activated = true;
    }
    return activated;
};
like image 68
Niklas Wulff Avatar answered Oct 01 '22 11:10

Niklas Wulff


I found this when I had the same issue, trying to get multiple layers to react to mouse events.

The solution, just in case anyone else finds this thread is much simpler.

The SelectFeature control takes an array of Vector layers and if all the laters you need to react to mouse events (hover and click) are in that array, they ALL work, not just the one that was moved to the top.

The documentation suggests against using markers layers at all. While my solution revolves around PostGIS geometry fields and lends itself to rendering POINT data in a vector layer, anything that uses Markers can be done this way, and according to OpenLayers, should.

So, the approved solution to this thread can be much simplified using Vector Layers for the markers and doing something like this:

this.carSelect = new OpenLayers.Control.SelectFeature(
    [vectorsLayer, markersLayer],
    {
        'hover':true,
        'callbacks': {
            blah blah blah
    }
});

This will register the appropriate events on both layers and make them both live.

I hope this helps anyone else stumbling on this issue.

As said elsewhere, using OpenLayers is not hard, finding the correct way to do things with it is.

like image 21
Martin Fraser Avatar answered Oct 01 '22 11:10

Martin Fraser