[OpenLayers-Users] legend support?

John Cole john.cole at uai.com
Tue Mar 20 15:13:17 EDT 2007


Thanks to Lance Dyas, I've been able to start a LayerSwitcher with a
multilayer legend.  It's not finished, but I have tried to write it in an
OpenLayers'ish style.  Several things remain to be done, namely checking the
scale levels to make sure a legend request should be made or not.  Very much
a work in progress.

here it is based off the OL WMS server:
------------------------------
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Legend Demonstration</title>
    <style type="text/css">
        #map {
            width: 100%;
            height: 550px;
        }
		
		div.olControlMapScale {
			top: 535px;
			left: 3px;
			display: block;
			position: absolute;
			font-family: Arial;
			font-size: smaller;
		}
    </style>
    <script src="http://www.openlayers.org/api/OpenLayers.js"></script>
    <!-- <script src="lib/OpenLayers.js"></script> -->
    <script type="text/javascript">
        <!--
        function init(){
			var map = new OpenLayers.Map.Legend('map', {
controls: [], maxScale:3000 });

			var layer_legend = new
Legend("http://labs.metacarta.com/wms/vmap0?");
			//layer_legend.addLayer("landmarks", null, 250000);
			layer_legend.addLayer("ocean");
			layer_legend.addLayer("ground_01");
			layer_legend.addLayer("ground_02");
			layer_legend.addLayer("population");
			layer_legend.addLayer("river");
			layer_legend.addLayer("stateboundary");
			layer_legend.addLayer("country_01");
			layer_legend.addLayer("country_02");
			layer_legend.addLayer("disp");
			layer_legend.addLayer("inwater");
			layer_legend.addLayer("coastline_01");
			layer_legend.addLayer("coastline_02");
			layer_legend.addLayer("depthcontour");
			layer_legend.addLayer("priroad");
			layer_legend.addLayer("secroad");
			layer_legend.addLayer("rail");
			layer_legend.addLayer("ferry");
			layer_legend.addLayer("tunnel");
			layer_legend.addLayer("bridge");
			layer_legend.addLayer("trail");
			
			layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
				"http://labs.metacarta.com/wms/vmap0",
{layers: 'basic'}, {legend: layer_legend} );
			map.addLayer(layer);
			
			map.addControl(new OpenLayers.Control.PanZoomBar());
			map.addControl(new
OpenLayers.Control.MouseDefaults());

			var layerswitcher = new
OpenLayers.Control.LayerSwitcher.Legend({'ascending':false});
           map.addControl(layerswitcher);
			layerswitcher.maximizeControl();
			
           map.addControl(new OpenLayers.Control.MousePosition());
			

			// center of us "POINT(-95.8413581848145
36.9642248153687)"
			//map.setCenter(new
OpenLayers.LonLat(-95.8413581848145, 36.9642248153687), 1);
			
			// hsv
			//map.setCenter(new OpenLayers.LonLat(-86.5, 34.75),
11);
			
			// chicago
			map.setCenter(new OpenLayers.LonLat(-87.67408,
41.7844), 9);

        }
		
		var dbgstring = "";
		
		// debugging function
		function DumpResult(source, result)
		{
		var s = "<plaintext>";
		s = s + source + " " + "\n";
		for (var x in result) {
			s = s + x + "=" + result[x] + "\n";
		}

		if (result.get_stackTrace) s = s + result.get_stackTrace() +
"\n";
		s = s + "</pre>";

		document.getElementById("DebugDiv").innerHTML = s;
		}

		// legend object
		Legend = OpenLayers.Class.create();
		Legend.prototype = {
			baseUrl: null,
			wmsQuery:
"LAYER=@layer@&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetLegen
dGraphic&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SCALE=@scale@",
			initialize: function(baseurl, layername, minscale,
maxscale) {
				this.baseUrl = baseurl;
				if (layername) {
					this.addLayer(layername, minscale,
maxscale);
				}
			},
			// this should check the scale to determin if it
should emit a
			// legend at this scale or not.  Right now, it
creats the legend
			// for each level, even if it returns an empty
bitmap.
			getLegend: function(scale) {
				if (this.layers.length > 0) {
					var legDiv =
document.createElement("div");
					for (var i in this.layers) {
						var layer = this.layers[i];
						var legImg =
document.createElement("img");
						legImg.src = this.baseUrl +
this.wmsQuery.replace("@layer@", layer.layername).replace("@scale@", scale);
						legDiv.appendChild(legImg);
	
legDiv.appendChild(document.createElement("br"));
					}
					return legDiv;
				} else {
					return null;
				}
			},
			layers: [],
			addLayer: function(layername, minscale, maxscale) {
				var leglayer = new LegendLayer(layername,
minscale, maxscale);
				this.layers.push(leglayer);
			}
			
		};
		

		// class to store layer information
		LegendLayer = OpenLayers.Class.create();
		LegendLayer.prototype = {
			layername: null,
			minscale: null,
			maxscale: null,
			initialize: function(layername, minscale, maxscale)
{
				this.layername = layername;
				this.minscale = minscale;
				this.maxscale = maxscale;
			}
		};
		
			
		OpenLayers.Map.Legend = OpenLayers.Class.create();
			OpenLayers.Map.Legend.prototype = 
			  OpenLayers.Class.inherit( OpenLayers.Map, {
				/**
				* @param {OpenLayers.LonLat} lonlat
				* @param {int} zoom
				* @param {Boolean} dragging Specifies
whether or not to 
				*                           trigger
movestart/end events
				*/
				setCenter: function (lonlat, zoom, dragging)
{
					
					if (!this.center &&
!this.isValidLonLat(lonlat)) {
						lonlat =
this.maxExtent.getCenterLonLat();
					}
					
					var zoomChanged =
(this.isValidZoomLevel(zoom)) && 
	
(zoom != this.getZoom());

					var centerChanged =
(this.isValidLonLat(lonlat)) && 
	
(!lonlat.equals(this.center));


					// if neither center nor zoom will
change, no need to do anything
					if (zoomChanged || centerChanged ||
!dragging) {

						if (!dragging) {
this.events.triggerEvent("movestart"); }

						if (centerChanged) {
							if ((!zoomChanged)
&& (this.center)) { 
								// if zoom
hasnt changed, just slide layerContainer
								//  (must be
done before setting this.center to new value)
	
this.centerLayerContainer(lonlat);
							}
							this.center =
lonlat.clone();
						}

						// (re)set the
layerContainerDiv's location
						if ((zoomChanged) ||
(this.layerContainerOrigin == null)) {
	
this.layerContainerOrigin = this.center.clone();
	
this.layerContainerDiv.style.left = "0px";
	
this.layerContainerDiv.style.top  = "0px";
						}

						if (zoomChanged) {
							this.zoom = zoom;
								
							//redraw popups
							for (var i = 0; i <
this.popups.length; i++) {
	
this.popups[i].updatePosition();
							}

							// zoom level has
changed, increment viewRequestID.
	
this.viewRequestID++;
						}    
						
						var bounds =
this.getExtent();
						
						//dbgstring = dbgstring +
"Map.setCenter> " + zoomChanged + "<br>\n";
	
//document.getElementById("DebugDiv").innerHTML = dbgstring;
						
						//send the move call to the
baselayer and all the overlays    
	
this.baseLayer.moveTo(bounds, zoomChanged, dragging);
						for (var i = 0; i <
this.layers.length; i++) {
							var layer =
this.layers[i];
							//dbgstring =
dbgstring + "Map.setCenter> " + layer.name + " scale:" + this.getScale() +
"<br>\n";
	
//document.getElementById("DebugDiv").innerHTML = dbgstring;
							if (zoomChanged) {
								// if the
zoom level changed, redraw the legend, in case any graphics changed because
								// of scale
level
	
this.events.triggerEvent("changelayer");
							}
							if
(!layer.isBaseLayer) {

								var
moveLayer;
								var inRange
= layer.calculateInRange();
								if
(layer.inRange != inRange) {
									//
Layer property has changed. We are going 
									//
to call moveLayer so that the layer can be turned
									//
off or on.   
	
layer.inRange = inRange;
	
moveLayer = true;
									if
(!zoomChanged) this.events.triggerEvent("changelayer"); 
								} else {
									//
If nothing has changed, then we only move the layer
									//
if it is visible and inrange.
	
moveLayer = (layer.visibility && layer.inRange);
								}

								if
(moveLayer) {
	
layer.moveTo(bounds, zoomChanged, dragging);
								}
							}

						}
						
	
this.events.triggerEvent("move");
				
						if (zoomChanged) {
this.events.triggerEvent("zoomend"); }
					}

					// even if nothing was done, we want
to notify of this
					if (!dragging) {
this.events.triggerEvent("moveend"); }
				},
				
			/** @final @type String */
			CLASS_NAME: "OpenLayers.Map.Legend"
		});
		
		/** 
		 * @class
		 * 
		 * @requires OpenLayers/Control.js
		 * @requires OpenLayers/Control.js
		 */
		OpenLayers.Control.LayerSwitcher.Legend =
OpenLayers.Class.create();
		OpenLayers.Control.LayerSwitcher.Legend.prototype = 
		  OpenLayers.Class.inherit(
OpenLayers.Control.LayerSwitcher, {
		
			/** Goes through and takes the current state of the
Map and rebuilds the
			 *   control to display that state. Groups base
layers into a radio-button
			 *   group and lists each data layer with a
checkbox.
			 * 
			 * @returns A reference to the DIV DOMElement
containing the control
			 * @type DOMElement
			 */  
			redraw: function() {

				//clear out previous layers 
				this.baseLayersDiv.innerHTML = "";
				this.baseLayerInputs = new Array();
				
				this.dataLayersDiv.innerHTML = "";
				this.dataLayerInputs = new Array();
				
				var containsOverlays = false;
				
				var layers = this.map.layers.slice();
				if (!this.ascending) { layers.reverse(); }
				for( var i = 0; i < layers.length; i++) {
					var layer = layers[i];
					var baseLayer = layer.isBaseLayer;

					if (baseLayer ||
layer.displayInLayerSwitcher) {

						if (!baseLayer) {
							containsOverlays =
true;
						}

						// only check a baselayer if
it is *the* baselayer, check data
						//  layers if they are
visible
						var checked = (baseLayer) ?
(layer == this.map.baseLayer)
	
: layer.getVisibility();
			
						// create input element
						var inputElem =
document.createElement("input");
						inputElem.id = "input_" +
layer.name;
						inputElem.name = (baseLayer)
? "baseLayers" : layer.name;
						inputElem.type = (baseLayer)
? "radio" : "checkbox";
						inputElem.value =
layer.name;
						inputElem.checked = checked;
						inputElem.defaultChecked =
checked;
						inputElem.layer = layer;
						inputElem.control = this;

						if (!baseLayer &&
!layer.inRange) {
							inputElem.disabled =
true;
							}
	
OpenLayers.Event.observe(inputElem, "mouseup", 
	
this.onInputClick.bindAsEventListener(inputElem));
						
						// create span
						var labelSpan =
document.createElement("span");
						if(layer.title)
labelSpan.title = layer.title;
						if (!baseLayer &&
!layer.inRange) {
	
labelSpan.style.color = "gray";
							}
						labelSpan.innerHTML =
"<nobr>"+layer.name+"</nobr>";
	
labelSpan.style.verticalAlign = (baseLayer) ? "bottom" : "baseline";
	
OpenLayers.Event.observe(labelSpan, "click", 
	
this.onInputClick.bindAsEventListener(inputElem));
						// create line break
						var br =
document.createElement("br");
					
						
						var groupArray = (baseLayer)
? this.baseLayerInputs
	
: this.dataLayerInputs;
						groupArray.push(inputElem);
	

			
						var groupDiv = (baseLayer) ?
this.baseLayersDiv
	
: this.dataLayersDiv;
	
groupDiv.appendChild(inputElem);
	
groupDiv.appendChild(labelSpan);
						groupDiv.appendChild(br);

						if(layer.legend){
							var layerlegend =
layer.legend.getLegend(this.map.getScale());
							
							if (layerlegend) {
	
groupDiv.appendChild(layerlegend);
	
groupDiv.appendChild(br);
							}

						}
					}
				}

				// if no overlays, dont display the overlay
label
				this.dataLbl.style.display =
(containsOverlays) ? "" : "none";        

				return this.div;
			},
		
			/** @final @type String */
			CLASS_NAME:
"OpenLayers.Control.LayerSwitcher.Legend"
		});
        // -->
    </script>
  </head>
  <body style="margin:0px;" onload="init()">
    <div id="map">
	<div class="olControlMapScale" style="position: absolute; z-index:
1004;" id="MapScale">
	</div>
</div>
<div id="DebugDiv">

</div>
  </body>
</html>
------------------------------

-----Original Message-----
From: users-bounces at openlayers.org [mailto:users-bounces at openlayers.org] On
Behalf Of Schuyler Erle
Sent: Tuesday, March 20, 2007 11:39 AM
To: gpio Oxxce
Cc: openlayers
Subject: Re: [OpenLayers-Users] legend support?

On Tue, 2007-03-20 at 17:05 +0000, gpio Oxxce wrote:
> 
> Is possible to have on the map somehow the legends generated from the
> geoserver/mapserver etc ...

I was just saying to Christopher last night that it wouldn't be hard to
build a control that knows how to look at a WMS/WFS layer, request the
legend image, and display it on a div somewhere on the page. I recommend
looking at, for example, the permalink control to get a sense of how
this might be done.

SDE

_______________________________________________
Users mailing list
Users at openlayers.org
http://openlayers.org/mailman/listinfo/users

-- 
No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.5.446 / Virus Database: 268.18.15/728 - Release Date: 3/20/2007
8:07 AM
 

-- 
No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.5.446 / Virus Database: 268.18.15/728 - Release Date: 3/20/2007
8:07 AM
 
This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the sender. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail.



More information about the Users mailing list