Merci Didier, I'll give it a look! On Tue, Aug 4, 2009 at 10:32 AM, RICHARD Didier<didier.rich...@ign.fr> wrote: > >> On Tue, Aug 4, 2009 at 6:04 AM, Eric Lemoine<eric.lemo...@camptocamp.com> >> wrote: >>> On Monday, August 3, 2009, Ivan Grcic <ivan.gr...@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@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.lemo...@camptocamp.com >>> http://www.camptocamp.com >>> _______________________________________________ >>> Dev mailing list >>> Dev@openlayers.org >>> http://openlayers.org/mailman/listinfo/dev >>> >> >> >> >> -- >> Ivan Grcic >> _______________________________________________ >> Dev mailing list >> Dev@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@openlayers.org > http://openlayers.org/mailman/listinfo/dev >
-- Ivan Grcic _______________________________________________ Dev mailing list Dev@openlayers.org http://openlayers.org/mailman/listinfo/dev