2
votes

I have three kml layers in a map: polygons, lines, points. The map is modified from the mobile-wms-vienna example. I have changed the layers, and changed the "Labels" button to alter the opacity on the polygon layer. To ensure that all features can be seen I need set z-indexing.

However I would also like to be able to display a pop-up on the polygon layer, which is set as the lowest. I do not want to see popups from lines or points. (Points can have labels, lines do not need labeling). I have read many posts about the problems with select on multiple layers, but could not find a solution to how to make anything selectable when z-indexing is set.

Is there a way to do this? Preferably draw the layers in the order they are added to the map. Or a label layer that moves with the map and zoom changes? Unfortunately, kml polygon labels are fixed to a point and so might disappear when the map is moved or zoomed in.

The entire map code is given below, as I am not sure if there is something else in my map that is affecting this behaviour.

var map;
var linetyle = new OpenLayers.Style({'strokeWidth': 2, 'strokeColor':"red",});

function init() {

    document.documentElement.lang = (navigator.userLanguage || navigator.language).split("-")[0];

    var layerPanel = new OpenLayers.Control.Panel({
        displayClass: "layerPanel",
        autoActivate: true
    });

    var opButton = new OpenLayers.Control({
        type: OpenLayers.Control.TYPE_TOGGLE,
        displayClass: "opButton",
        eventListeners: {
            activate: function() {
                if (polygon) {polygon.setOpacity(0.4);}
            },
            deactivate: function() {
                if (polygon) {polygon.setOpacity(0.9);}
            }
        }
    });
    layerPanel.addControls([opButton]);

    var zoomPanel = new OpenLayers.Control.ZoomPanel();

    // Geolocate control for the Locate button - the locationupdated handler
    // draws a cross at the location and a circle showing the accuracy radius.
    var geolocate = new OpenLayers.Control.Geolocate({
        type: OpenLayers.Control.TYPE_TOGGLE,
        bind: false,
        watch: true,
        geolocationOptions: {
            enableHighAccuracy: false,
            maximumAge: 0,
            timeout: 7000
        },
        eventListeners: {
            activate: function() {
                map.addLayer(vector);
            },
            deactivate: function() {
                map.removeLayer(vector);
                vector.removeAllFeatures();
            },
            locationupdated: function(e) {
                vector.removeAllFeatures();
                vector.addFeatures([
                    new OpenLayers.Feature.Vector(e.point, null, {
                        graphicName: 'cross',
                        strokeColor: '#f00',
                        strokeWidth: 2,
                        fillOpacity: 0,
                        pointRadius: 10
                    }),
                    new OpenLayers.Feature.Vector(
                        OpenLayers.Geometry.Polygon.createRegularPolygon(
                            new OpenLayers.Geometry.Point(e.point.x, e.point.y),
                            e.position.coords.accuracy / 2, 50, 0
                        ), null, {
                            fillOpacity: 0.1,
                            fillColor: '#000',
                            strokeColor: '#f00',
                            strokeOpacity: 0.6
                        }
                    )
                ]);
                map.zoomToExtent(vector.getDataExtent());
            }
        }
    });
    zoomPanel.addControls([geolocate]);

    map = new OpenLayers.Map({
        div: "map",
        theme: null,
        projection: new OpenLayers.Projection("EPSG:3857"),
        displayProjection: new OpenLayers.Projection("EPSG:4326"),
        layers: [new OpenLayers.Layer.Google( "Google Satellite", {type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 22})],
        center: new OpenLayers.LonLat(149.1, -35.3).transform('EPSG:4326', 'EPSG:3857'),
        zoom: 10,
        units: "m",
        maxResolution: 38.21851413574219,
        controls: [
            new OpenLayers.Control.Navigation(),
            new OpenLayers.Control.Attribution(),
            zoomPanel,
            layerPanel
        ],

    });

    layerPanel.activateControl(opButton);

    // Vector layer for the location cross and circle
    var vector = new OpenLayers.Layer.Vector("Vector Layer");

     var point = new OpenLayers.Layer.Vector("points", {
//               rendererOptions: {zIndexing: 'true'}, 
                projection: map.displayProjection,
                strategies: [new OpenLayers.Strategy.BBOX()],
                protocol: new OpenLayers.Protocol.HTTP({
                    url: "kml/point.kml",
                    format: new OpenLayers.Format.KML({
                        extractStyles: true,
                        extractAttributes: true
                    })     })       }); 
     var line = new OpenLayers.Layer.Vector("line", {
//                rendererOptions: {zIndexing: 'true'}, 
                projection: map.displayProjection,
                strategies: [new OpenLayers.Strategy.BBOX({resFactor: 1})],
                styleMap: linetyle,
                protocol: new OpenLayers.Protocol.HTTP({
                    url: "kml/line.kml",
                    format: new OpenLayers.Format.KML({ extractStyles: false,
                        extractAttributes: true
                    })        })     });
     var polygon = new OpenLayers.Layer.Vector("Geology", {
//                rendererOptions: {zIndexing: 'true'}, 
                projection: map.displayProjection,
                strategies: [new OpenLayers.Strategy.BBOX({resFactor: 1})],
                protocol: new OpenLayers.Protocol.HTTP({
                url: "kml/polygon.kml",
                   format: new OpenLayers.Format.KML({extractStyles: true,extractAttributes: true})
                })    });
            map.addLayers([point, line, polygon]);
            polygon.setOpacity(0.5);

//            point.setZIndex(1400);
//            line.setZIndex(1300);
//            polygon.setZIndex(1200);

//  Select Features/Popup
            select = new OpenLayers.Control.SelectFeature (polygon, line, point);

            polygon.events.on({
                "featureselected": onFeatureSelect,
                "featureunselected": onFeatureUnselect
            }),
            line.events.on({
                "featureselected": onFeatureSelect, 
                "featureunselected": onFeatureUnselect
            }),
            point.events.on({ 
                "featureselected": onFeatureSelect, 
                "featureunselected": onFeatureUnselect
            }),

            map.addControl(select);
            select.activate();   

        function onPopupClose(evt) {
            select.unselectAll();
        }
        function onFeatureSelect(event) {
            var feature = event.feature;
            // Since KML is user-generated, do naive protection against
            // Javascript.
            var content = "<h2>"+feature.attributes.name + "</h2>" + feature.attributes.description;
            if (content.search("<script") != -1) {
                content = "Content contained Javascript! Escaped content below.<br>" + content.replace(/</g, "&lt;");
            }
            popup = new OpenLayers.Popup.FramedCloud("chicken", 
                                     feature.geometry.getBounds().getCenterLonLat(),
                                     new OpenLayers.Size(100,100),
                                     content,
                                     null, false, onPopupClose);
            feature.popup = popup;
            map.addPopup(popup);
        }
        function onFeatureUnselect(event) {
            var feature = event.feature;
            if(feature.popup) {
                map.removePopup(feature.popup);
                feature.popup.destroy();
                delete feature.popup;
            }
        };

};

The map can be seen at http://quartzspatial.net/act/map_v2.html

The closest answer that may solve my problem is here, but I could not understand how to use the solutions, and after many attempts at putting code in different places, I gave up.

1

1 Answers

0
votes

I have just been looking at similar problem earlier. You probably figured this out yourself by now but I would like to share my jsFiddle in which I use event listener on the map object instead of a select control.

You cannot use an OpenLayers select control with layers index. The activation event will always put the layers on top and setting the z index on the layers will disable the select control. I also wasn't able to make the solution with disabling the moveontop in the activate event work (in jsFiddle).

Please have a look at the event listener solution:

var map = new OpenLayers.Map({
 div: "map",
 projection: new OpenLayers.Projection("EPSG:3857"),
 displayProjection: new OpenLayers.Projection("EPSG:4326"),
 layers: [
  new OpenLayers.Layer.OSM()],
 controls: [
  new OpenLayers.Control.Navigation(),
  new OpenLayers.Control.ArgParser() ],

 eventListeners: {

  featureover: function(e) { if (e.feature.layer != vectors2) {
   e.feature.renderIntent = "temporary";
   e.feature.layer.drawFeature(e.feature); }
  },

 featureout: function(e) { if (e.feature.layer != vectors2) {
  e.feature.renderIntent = "default";
  e.feature.layer.drawFeature(e.feature); }
 },

 featureclick: function(e) { if (e.feature.layer != vectors2) {
  e.feature.renderIntent = "select";
  e.feature.layer.drawFeature(e.feature); }
 }

}

});