[OpenLayers-Dev] A kind of MultiLayer container
Ivan Grcic
ivan.grcic at geofoto.hr
Tue Aug 4 05:38:27 EDT 2009
Merci Didier, I'll give it a look!
On Tue, Aug 4, 2009 at 10:32 AM, RICHARD Didier<didier.richard at ign.fr> wrote:
>
>> On Tue, Aug 4, 2009 at 6:04 AM, Eric Lemoine<eric.lemoine at camptocamp.com>
>> wrote:
>>> On Monday, August 3, 2009, Ivan Grcic <ivan.grcic at geofoto.hr> wrote:
>>>> Hi devs,
>>>>
>>>> I want to ask if anyone has made something like Vector/RootContainer,
>>>> a layer that would contain several layers, and every layer would
>>>> activate/deactivate on different zoomLevels.
>>>>
>>>> Simple case: 3 (or more) layers combined in one ContainerLayer
>>>> small scale: WMS raster layer
>>>> larger scales: other WMS raster layer
>>>> large scale: WFS vector layer
>>>>
>>>> Usually I always register zoomend event on map, and manually activate
>>>> or deactivate layers...but it got little bit boring to do that on
>>>> application level every time.
>>>>
>>>> I remember Alexandre did something like that but for Vector layer
>>>> or http://openlayers.org/pipermail/users/2009-January/009666.html
>>>>
>>>> Anyone did something like that? (does mapfish maybe has soemthing like
>>>> that)
>>>> If not, can anyone just give few tips, so I could start developing
>>>> it...
>>>
>>>
>>> Hi Ivan
>>>
>>> Can't you just set different resolution ranges in the layers?
>>>
>>> Cheers,
>>>
>>>
>> Tnx for replies guys,
>>
>>
>> Yes yes, im setting ranges for my layers, but I want to have only one
>> layer shown in layerSwitcher for group of layers.
>>
>> I guess I just have to create one dummy layer with inLayerSwitcher:
>> true, and other layers to false. And then just register activate,
>> deactivate events that will turn off/on all group layers. (as alex
>> suggested, tnx)
>>
>> I was just wondering if it would have sense to have it included in
>> API, not to do it manually all the time...
>> Cheers
>>
>
> Hi all,
>
> For our portal API, we have develop something really close :
>
>
> /*
> * Copyright 2008-2009 Institut Geographique National France, released
> under the
> * BSD license.
> */
> /**
> * Class: Geoportal.Layer.Aggregate
> * A container of layers. The idea is to group layers to avoid big list to be
> * displayed in the LayerSwitcher. This aggregation also helps in grouping
> * spread OGC services into a compound one.
> * This feature is experimental.
> *
> * Inherits from:
> * - {<OpenLayers.Layer>}
> */
> Geoportal.Layer.Aggregate=
> OpenLayers.Class( Geoportal.Layer, {
>
> /**
> * APIProperty: layers
> * {Array(<Geoportal.Layer>)} Ordered list of layers in the aggregation.
> */
> layers: null,
>
> /**
> * Constructor: Geoportal.Layer.Aggregate
> * Build an aggregation of layers.
> *
> * Parameters:
> * name - {String} The aggregation name.
> * layers - {Array(<Geoportal.Layer>)} Ordered list of layers to push
> into
> * the aggregation.
> * options - {Object} Hash table of options.
> */
> initialize: function(name, layers, options) {
> Geoportal.Layer.prototype.initialize.apply(this,[name, options]);
> this.layers= [];
> this.addLayers(layers);
> },
>
> /**
> * APIMethod: destroy
> * Clean up the compound layer.
> *
> * Parameters:
> * setNewBaseLayer - {Boolean} Set a new base layer when this layer has
> * been destroyed. Default is true.
> */
> destroy: function(setNewBaseLayer) {
> if (this.map) {
> this.map.events.unregister("removelayer",this,this.remove);
> }
> if (this.layers) {
> for (var i= 0, len= this.layers.length; i<len; i++) {
> this.layers[i].aggregate= null;
> }
> this.layers= null;
> }
> Geoportal.Layer.prototype.destroy.apply(this,arguments);
> },
>
> /**
> * Method: remove
> * Remove the aggregation from the map.
> *
> * Parameters:
> * evt - {Event}
> */
> remove: function(evt) {
> if (evt.layer != this) { return; }
> if (this.layers) {
> var layer;
> for (var i= 0, len= this.layers.length; i<len; i++) {
> layer= this.layers[i];
> layer.map.removeLayer(this.layers[i],false);
> }
> }
> },
>
> /**
> * Method: clone
> *
> * Returns:
> * {<Geoportal.Layer>} An exact clone of this <Geoportal.Layer>
> */
> clone: function() {
> var obj= Geoportal.Layer.prototype.clone.apply(this,arguments);
> // FIXME: a layer may belong to multiple aggregates ?
> obj.addLayers(this.layers);
> },
>
> /**
> * Method: setMap
> * Set the map property for the layer. This is done through an accessor
> * so that subclasses can override this and take special action once
> * they have their map variable set.
> *
> * Here we take care to bring over any of the necessary default
> * properties from the map.
> *
> * Parameters:
> * map - {<OpenLayers.Map>}
> */
> setMap: function(map) {
> if (this.map != null) { return; }
> if (!this.layers) { return; }
> var layer;
> for (var i= 0, len= this.layers.length; i<len; i++) {
> layer= this.layers[i];
> if (layer.map == null) {
> map.addLayer(layer);
> }
> }
> var me= this.maxExtent == null;
> Geoportal.Layer.prototype.setMap.apply(this,arguments);
> if (me) {
> this.maxExtent= null;
> for (var i= 0, len= this.layers.length; i<len; i++) {
> layer= this.layers[i];
> if (i==0) {
> this.maxExtent= layer.maxExtent.clone();
> } else {
> this.maxExtent.extend(layer);
> }
> }
> }
> // update layers' z-index :
> this.setZIndex(this.getZIndex());
> this.map.events.register("removelayer",this,this.remove);
> },
>
> /**
> * APIMethod: removeMap
> * The layer has been removed from the map.
> *
> * Parameters:
> * map - {<OpenLayers.Map>}
> */
> removeMap: function(map) {
> if (this.map == null) { return; }
> if (this.layers) {
> var layer;
> for (var i= 0, len= this.layers.length; i<len; i++) {
> layer= this.layers[i];
> if (layer.map != null) {
> layer.map.removeLayer(layer);
> }
> }
> }
> },
>
> /**
> * APIMethod: setVisibility
> * Set the visibility flag for the layer and hide/show & redraw
> * accordingly. Fire event unless otherwise specified
> *
> * Note that visibility is no longer simply whether or not the layer's
> * style.display is set to "block". Now we store a 'visibility' state
> * property on the layer class, this allows us to remember whether or
> * not we *desire* for a layer to be visible. In the case where the
> * map's resolution is out of the layer's range, this desire may be
> * subverted.
> *
> * Parameters:
> * visible - {Boolean} Whether or not to display the layer (if in range)
> */
> setVisibility: function(visibility) {
> if (visibility != this.visibility) {
> this.visibility= visibility;
> Geoportal.Layer.prototype.display.apply(this,arguments);
> if (this.layers && this.map!=null) {
> var layer, lproj;
> for (var i= 0, len= this.layers.length; i<len; i++) {
> layer= this.layers[i];
> if (layer.isBaseLayer) { continue; }
> if (layer.territory!==undefined &&
> this.map.baseLayer.territory!==undefined) {
> if (layer.territory==this.map.baseLayer.territory) {
> if (visibility) {
> layer.setVisibility(layer.calculateInRange());
> } else {
> layer.setVisibility(false);
> }
> }
> continue;
> }
> lproj= layer.getNativeProjection();
> if (!lproj) { continue; }
> if
> (!(lproj.equals(this.map.baseLayer.nativeProjection)
> ||
> (lproj.proj.projName=='longlat' &&
> lproj.isCompatibleWith(this.map.baseLayer.nativeProjection))))
> { continue; }
> if (!(layer.restrictedExtent || layer.maxExtent) ||
> this.map.baseLayer.maxExtent.containsBounds(
> layer.restrictedExtent ||
> layer.maxExtent,true,true)) {
> if (visibility) {
> layer.setVisibility(layer.calculateInRange());
> } else {
> layer.setVisibility(false);
> }
> }
> }
> }
> if (this.map != null) {
> this.map.events.triggerEvent("changelayer", {
> layer: this,
> property: "visibility"
> });
> }
> this.events.triggerEvent("visibilitychanged");
> }
> },
>
> /**
> * APIMethod: display
> * Hide or show the Layer.
> *
> * Parameters:
> * display - {Boolean}
> */
> display: function(display) {
> var inRange = this.calculateInRange();
> if (display != (this.div.style.display != "none")) {
> this.div.style.display = (display && inRange) ? "block" : "none";
> if (this.layers) {
> var layer;
> for (var i= 0, len= this.layers.length; i<len; i++) {
> layer= this.layers[i];
> layer.display(display);
> }
> }
> }
> },
>
> /**
> * Method: initResolutions
> * This method's responsibility is to set up the 'resolutions' array
> * for the layer -- this array is what the layer will use to
> interface
> * between the zoom levels of the map and the resolution display
> * of the layer.
> *
> * The user has several options that determine how the array is set up.
> *
> * For a detailed explanation, see the following wiki from the
> * openlayers.org homepage:
> * http://trac.openlayers.org/wiki/SettingZoomLevels
> */
> initResolutions: function() {
> if (this.layers) {
> var layer;
> var mnz= typeof(this.options.minZoomLevel) == 'number';
> var mxz= typeof(this.options.maxZoomLevel) == 'number';
> for (var i= 0, len= this.layers.length; i<len; i++) {
> layer= this.layers[i];
> if (i==0) {
> if (!mnz && typeof(layer.minZoomLevel) == 'number') {
> this.options.minZoomLevel= layer.minZoomLevel;
> }
> if (!mxz && typeof(layer.maxZoomLevel) == 'number') {
> this.options.maxZoomLevel= layer.maxZoomLevel;
> }
> } else {
> if (!mnz && typeof(layer.minZoomLevel) == 'number') {
> this.options.minZoomLevel=
> Math.min(this.options.minZoomLevel,
> layer.minZoomLevel);
> }
> if (!mxz && typeof(layer.maxZoomLevel) == 'number') {
> this.options.maxZoomLevel=
> Math.max(this.options.maxZoomLevel,
> layer.maxZoomLevel);
> }
> }
> }
> }
> Geoportal.Layer.prototype.initResolutions.apply(this,arguments);
> },
>
> /**
> * Method: getDataExtent
> * Calculates the max extent which includes all of the data for the
> layer.
> * This function is to be implemented by subclasses.
> *
> * Returns:
> * {<OpenLayers.Bounds>}
> */
> getDataExtent: function () {
> var de= null;
> if (this.layers) {
> var layer;
> for (var i= 0, len= this.layers.length; i<len; i++) {
> layer= this.layers[i];
> if (i==0) {
> de= layer.getDataExtent();
> } else {
> de.extend(layer.getDataExtent());
> }
> }
> }
> return de;
> },
>
> /**
> * APIMethod: setOpacity
> * Sets the opacity for the entire layer (all images)
> *
> * Parameter:
> * opacity - {Float}
> */
> setOpacity: function(opacity) {
> if (opacity != this.opacity) {
> Geoportal.Layer.prototype.setOpacity.apply(this,arguments);
> if (this.layers) {
> var layer;
> for (var i= 0, len= this.layers.length; i<len; i++) {
> layer= this.layers[i];
> layer.setOpacity(opacity);
> }
> }
> }
> },
>
> /**
> * Method: setZIndex
> * Assign the aggregation z-index.
> * Aggregated layers have their z-index numbered from the
> aggregation's
> * z-index by decrementing their rank to the base z-index.
> *
> * Parameters:
> * zIndex - {Integer}
> */
> setZIndex: function (zIndex) {
> this.div.style.zIndex = zIndex;
> if (this.layers) {
> var layer;
> for (var i= 0, len= this.layers.length; i<len; i++) {
> layer= this.layers[i];
> // sub-layers are added before the aggregation to the map
> // the first sub-layer has z-index Z_INDEX_BASE['Overlay']
> + rank * 5
> // the last sub-layer's z-index is augmented by
> layers.length * 5
> // the aggregation's z-index is augmentented by
> (layers.length + 1) * 5
> if (layer.div) {
> // on destroying the map, the sub-layer are destroyed
> // before the aggregation ... if which case layer's
> div is
> // null !
> layer.setZIndex(zIndex-i-1);
> }
> }
> }
> },
>
> /**
> * APIMethod: addLayer
> * Add a layer to an aggregation.
> *
> * Parameters:
> * layer - {<OpenLayers.Layer>}
> */
> addLayer: function(layer) {
> var lyr;
> for (var i= 0, len= this.layers.length; i<len; i++) {
> lyr= this.layers[i];
> if (lyr == layer) {
> var msg= OpenLayers.i18n('layerAlreadyAdded',
> {'layerName':layer.name});
> OpenLayers.Console.warn(msg);
> return;
> }
> }
> layer.displayInLayerSwitcher= false;
> layer.visibility= this.visibility;
> // FIXME: a layer may belong to multiple aggregates ?
> layer.aggregate= this;
> this.layers.push(layer);
> if (this.map) {
> if (layer.map == null) {
> this.map.addLayer(layer);
> }
> this.initResolutions();
> this.setZIndex(this.getZIndex());
> }
> },
>
> /**
> * APIMethod: addLayers
> * Add layers to an aggregation.
> *
> * Parameters:
> * layers - {Array(<OpenLayers.Layer>)}
> */
> addLayers: function(layers) {
> if (!layers) { return; }
> if (!(layers instanceof Array)) {
> this.addLayer(layers);
> return;
> }
> for (var i= 0, len= layers.length; i<len; i++) {
> this.addLayer(layers[i]);
> }
> },
>
> /**
> * Constant: CLASS_NAME
> * {String} *"Geoportal.Layer.Aggregate"*
> */
> CLASS_NAME:"Geoportal.Layer.Aggregate"
> });
>
>
> Note that Geoportal.Layer is just a synonym of OpenLayers.Layer
>
> Regards,
>
> didier
>>
>>>>
>>>> Tnx&Cheers,
>>>>
>>>>
>>>> --
>>>> Ivan Grcic
>>>> _______________________________________________
>>>> Dev mailing list
>>>> Dev at openlayers.org
>>>> http://openlayers.org/mailman/listinfo/dev
>>>>
>>>
>>> --
>>> Eric Lemoine
>>>
>>> Camptocamp France SAS
>>> Savoie Technolac, BP 352
>>> 73377 Le Bourget du Lac, Cedex
>>>
>>> Tel : 00 33 4 79 44 44 96
>>> Mail : eric.lemoine at camptocamp.com
>>> http://www.camptocamp.com
>>> _______________________________________________
>>> Dev mailing list
>>> Dev at openlayers.org
>>> http://openlayers.org/mailman/listinfo/dev
>>>
>>
>>
>>
>> --
>> Ivan Grcic
>> _______________________________________________
>> Dev mailing list
>> Dev at openlayers.org
>> http://openlayers.org/mailman/listinfo/dev
>>
>
>
> --
> RICHARD Didier - Chef du pôle technique du Géoportail
> 2/4, avenue Pasteur - 94165 Saint Mandé Cedex
> Tél : +33 (0) 1 43 98 83 23
> _______________________________________________
> Dev mailing list
> Dev at openlayers.org
> http://openlayers.org/mailman/listinfo/dev
>
--
Ivan Grcic
More information about the Dev
mailing list