openlayers2地图控件扩展:图例控件LegendControl

因项目需要在地图中增加图例,以便专题地图查看或输出。

实现思路,折线和多边形图例直接由样式属性创建,多边形直接设置div的样式;折线通过创建svg,设置polyline的样式;点要素的图例比较复杂,目前实现方式是:

1、根据StyleMap里的Filter,找到不同Filter的要素id,这里的查找要过滤掉没有被渲染的要素;

2、根据要素id从图层的渲染层找到对应的html元素,也就是svg标签;

3、处理找到的svg标签即可,主要是移位;

代码如下:

  1 OpenLayers.Control.LegendControl = OpenLayers.Class(OpenLayers.Control, {
  2     legendDiv: null,
  3     layers: [],
  4     colorDiv_w: 30,
  5     colorDiv_h: 20,
  6     /*
  7      * layers --Array
  8      * */
  9     initialize: function (layers, options) {
 10         OpenLayers.Control.prototype.initialize.apply(this, options);
 11 
 12         this.setLayers(layers);    
 13     },
 14     setMap: function(map) {
 15         var me = this;
 16         OpenLayers.Control.prototype.setMap.apply(this, arguments);
 17         if(me.map){
 18             me.map.events.register("moveend", me, me.redraw);
 19             me.map.events.register("changelayer", me, function(evt){
 20                 if(evt.property == "visibility")
 21                     this.redraw();
 22             });
 23         }
 24     },
 25     //{Array or Object}
 26     setLayers: function(layers){
 27         var me = this;
 28         if(OpenLayers.Util.isArray(layers)){
 29             me.layers = layers;
 30         }
 31     },
 32     addLayer: function(layer){
 33         this.layers.push(layer);
 34 
 35         this.redraw();
 36     },
 37     redraw: function(){
 38         if(this.div.style.display == "none"){
 39             return;
 40         }
 41         if(this.legendDiv){
 42             this.div.removeChild(this.legendDiv);
 43             this.legendDiv = null;
 44         }
 45         this.draw();
 46     },
 47     display: function(display) {
 48         this.div.style.display = (display) ? "" : "none"; 
 49     },
 50     draw: function() {
 51         OpenLayers.Control.prototype.draw.apply(this);
 52 
 53         // create layout divs
 54         this.loadContents();
 55 
 56         return this.div;
 57     },
 58     loadContents: function(){
 59         if(!this.legendDiv){
 60             this.legendDiv = document.createElement("div");
 61             this.legendDiv.id = this.id + "_legendDiv";
 62             OpenLayers.Element.addClass(this.legendDiv, "legendDiv"); 
 63             this.div.appendChild(this.legendDiv);
 64 
 65             // create span
 66             var labelSpan = document.createElement("label");
 67             labelSpan.innerHTML = "Legend";
 68             OpenLayers.Element.addClass(labelSpan, "title");
 69             this.legendDiv.appendChild(labelSpan); 
 70             var brSpan = document.createElement("br");
 71             this.legendDiv.appendChild(brSpan); 
 72 
 73             for(var i = 0; i < this.layers.length;i ++){
 74                 var layer = this.layers[i];
 75                 if(!layer.getVisibility()){
 76                     continue;
 77                 }
 78                 var geom = getLayerDefaultGeometry(layer);  //获取图层中的几何要素
 79                 if(!geom)
 80                     continue;
 81                 
 82                 //one table corresponds to a layer
 83                 var labelLyr = document.createElement("label");
 84                 labelLyr.innerHTML = layer.name;
 85                 this.legendDiv.appendChild(labelLyr);
 86                 var tableDiv = document.createElement("table");
 87                 this.legendDiv.appendChild(tableDiv);
 88                 
 89                 var featArray = layer.features;
 90                 var unrenderFeatures = layer.unrenderedFeatures;
 91                 var arr = Object.keys(unrenderFeatures);
 92                 if(arr.length == featArray.length)
 93                     continue;
 94                 
 95                 var styleRules = layer.styleMap.styles["default"].rules;
 96                 var geomType = "point";
 97                 //decide symbolizer panel from geometry type
 98                 if(geom instanceof OpenLayers.Geometry.Point ||
 99                         geom instanceof OpenLayers.Geometry.MultiPoint) {
100                     var allFilters = [];
101                     var bElseFilter = 2;
102                     for(var key in styleRules) {
103                         var filter = styleRules[key].filter;
104                         if(filter){
105                             allFilters.push(filter);
106                         }
107                         else{ //no filter
108                             bElseFilter = styleRules[key].elseFilter;
109                         }
110                     }
111                     //
112                     if(!bElseFilter){    //no else filter --deafault
113                         var trDiv = this.createPointLegend(geom.id, "default");
114                         tableDiv.appendChild(trDiv);
115                     }
116                     else{    //find filter's geometry id
117                         var filterIDs = [];
118 
119                         var findResults = {};
120                         var findCount = 0;
121                         for(var dex = 0; dex < featArray.length; dex ++){
122                             if(findCount == allFilters.length + 1)
123                                 break;
124                             
125                             var feat = featArray[dex];
126                             if(arr.indexOf(feat.id) >= 0)
127                                 continue;
128 
129                             var beInfilter = false;
130                             for(var fk = 0; fk < allFilters.length; fk ++){
131                                 var bFilter = allFilters[fk].evaluate(feat);
132                                 if(bFilter){
133                                     beInfilter = true;
134                                     if(!findResults[allFilters[fk].toString()]){
135                                         var svgId = feat.geometry.id;
136                                         filterIDs.push({
137                                             id:svgId,
138                                             label: allFilters[fk].toString()
139                                         });
140                                         findResults[allFilters[fk].toString()] = true;
141                                         findCount ++;                                        
142                                     }
143                                     break;
144                                 }
145 
146                             }
147                             if(!beInfilter && (!findResults["default"])){    //false
148                                 var svgId = feat.geometry.id;
149                                 filterIDs.push({
150                                     id:svgId,
151                                     label: "default"
152                                 });
153                                 findResults["default"] = true;
154                                 findCount ++;
155                             }
156                         }
157                         for(var fDex = 0; fDex < filterIDs.length; fDex ++){
158                             var trDiv = this.createPointLegend(filterIDs[fDex].id, filterIDs[fDex].label);
159                             tableDiv.appendChild(trDiv);                        
160                         }
161                     }
162 
163                     continue;    //skip next code
164                 } else if(geom instanceof OpenLayers.Geometry.LineString ||
165                         geom instanceof OpenLayers.Geometry.MultiLineString) {
166                     geomType = "line";
167 
168                 } else if(geom instanceof OpenLayers.Geometry.LinearRing ||
169                         geom instanceof OpenLayers.Geometry.Polygon ||
170                         geom instanceof OpenLayers.Geometry.MultiPolygon) {
171                     geomType = "polygon";
172                 }
173 
174                 for(var key in styleRules) {
175                     var filter = styleRules[key].filter;
176                     var sybol = styleRules[key].symbolizer;
177                     var labelTxt = "";
178                     if(filter) {
179                         labelTxt = filter.toString();
180                     }
181                     else{
182                         labelTxt = "default";
183                     }
184 
185                     var trDiv = document.createElement("tr");
186                     tableDiv.appendChild(trDiv);
187                     var colorTd = document.createElement("td");
188                     trDiv.appendChild(colorTd);
189 
190                     var labelTd = document.createElement("td");
191                     trDiv.appendChild(labelTd);
192 
193                     var itemLabel = document.createElement("label");
194                     itemLabel.style = "margin-left:5px;position:relative;top:3px;";
195                     itemLabel.innerHTML = labelTxt;
196                     labelTd.appendChild(itemLabel);
197 
198                     if(geomType == "line"){
199                         if(sybol.Line){
200                             var colorDiv = this.createLineLegend(sybol.Line);
201                             colorTd.appendChild(colorDiv);
202                         }
203                     }
204                     else if(geomType == "polygon"){
205                         if(sybol.Polygon){
206                             var colorDiv = this.createPolygonLegend(sybol.Polygon);
207                             colorTd.appendChild(colorDiv);                        
208                         }
209                     }
210                 }
211             }
212 
213         }
214     },
215     createPolygonLegend: function(polygonSybol){
216         var colorDiv = document.createElement("div");
217         if(polygonSybol.fill){
218             var color = this.parseColor(polygonSybol.fillColor, polygonSybol.fillOpacity);
219             colorDiv.style.background = color;
220         }
221         if(polygonSybol.stroke){
222             var dashStyle = polygonSybol.strokeDashstyle;
223             var color = this.parseColor(polygonSybol.strokeColor, polygonSybol.strokeOpacity);
224             var width = polygonSybol.strokeWidth + "px";
225             colorDiv.style.border = width + " " + dashStyle + " " + color;
226         }
227         colorDiv.style.height = this.colorDiv_h + "px";
228         colorDiv.style.width = this.colorDiv_w + "px";
230         return colorDiv;
231     },
232     /*
233      * <svg><polyline points="20,27,34,21" fill="none" stroke="#550000" stroke-opacity="1" stroke-width="3"
234      * stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none"></polyline></svg>
235      * */
236     createLineLegend: function(lineSybol){
237         var colorDiv = document.createElement("div");
238         colorDiv.style.height = this.colorDiv_h + "px";
239         colorDiv.style.width = this.colorDiv_w + "px";
240 
241         var lineHtml = '<svg width="100%" height="100%">';
242         lineHtml += '<polyline points="2,2,28,18" fill="none" stroke="' + lineSybol.strokeColor 
243         + '" stroke-opacity="'+ lineSybol.strokeOpacity +'" stroke-width="'+ lineSybol.strokeWidth + '"';
244         lineHtml += ' stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none"></polyline></svg>';
245         colorDiv.innerHTML = lineHtml;
246 
247         return colorDiv;
248     },
249     createPointLegend: function(svgId, label){
250         var trDiv = document.createElement("tr");
251         var svgEle = document.getElementById(svgId);
252         if(!svgEle){
253             return trDiv;
254         }
255         var colorTd = document.createElement("td");
256         trDiv.appendChild(colorTd);
257 
258         var labelTd = document.createElement("td");
259         trDiv.appendChild(labelTd);
260         var itemLabel = document.createElement("label");
261         itemLabel.style = "margin-left:5px;position:relative;top:3px;";
262         itemLabel.innerHTML = label;
263         labelTd.appendChild(itemLabel);
264 
265         var colorDiv = document.createElement("div");
266         colorTd.appendChild(colorDiv);
267         var divHeight = this.colorDiv_h;
268         var divWidth = this.colorDiv_w;
269 
270         var cln = svgEle.cloneNode(true);
271         if(cln.nodeName.toLowerCase() != "svg"){    //circle,image
272             var rVal = cln.getAttribute("r");
273             if(cln.hasAttribute("x") && cln.hasAttribute("y")){
274                 cln.setAttribute("x", rVal);
275                 cln.setAttribute("y", rVal);                
276             }
277             if(cln.hasAttribute("cx") && cln.hasAttribute("cy")){
278                 cln.setAttribute("cx", rVal);
279                 cln.setAttribute("cy", rVal);
280             }
281             if(cln.hasAttribute("transform")){
282                 var transform = cln.getAttribute("transform");
283                 if(transform.indexOf('rotate(') >= 0){
284                     var transValues = transform.split('rotate(');
285                     var kk = null;
286                     if(transValues.length == 1){
287                         kk = 0;
288                     }
289                     else if(transValues.length > 1){
290                         kk = 1;
291                     }
292                     if(kk != null){
293                         var str = transValues[kk];
294                         var sp = str.indexOf(')');
295                         var rotString = str.substring(0, sp);
296 
297                         var ww = parseFloat(cln.getAttribute('width'));
298                         var hh = parseFloat(cln.getAttribute('height'));
299                         if(ww >= divWidth)
300                             divWidth = ww + 2;
301                         if(hh >= divWidth)
302                             divHeight = hh + 2;
303 
304                         var rotValues = rotString.split(' ');
305                         rotValues[1] = ww / 2;
306                         rotValues[2] = hh / 2;
307 
308                         transValues[kk] = rotValues.join(' ') + str.substring(sp);
309                         cln.setAttribute('transform',transValues.join('rotate('));                            
310                     }
311                 }
312 
313             }
314             //innerHTML
315             colorDiv.innerHTML = '<svg width="100%" height="100%"></svg>';
316             var svgNode = colorDiv.firstChild;
317             svgNode.appendChild(cln);
318             colorDiv.appendChild(svgNode);
319         }
320         else{
321             //change viewBox --from(0,0)
322             var viewBox = cln.getAttribute('viewBox');    // Grab the object representing the SVG element's viewBox attribute.
323             var viewBoxValues = viewBox.split(' ');                // Create an array and insert each individual view box attribute value (assume they're seperated by a single whitespace character).
324 
325             /* The array is filled with strings, convert the first two viewBox values to floats: */
326             viewBoxValues[0] = parseFloat(viewBoxValues[0]);    // Represent the x-coordinate on the viewBox attribute.
327             viewBoxValues[1] = parseFloat(viewBoxValues[1]);    // Represent the y coordinate on the viewBox attribute.
328             viewBoxValues[2] = parseFloat(viewBoxValues[2]);    // Represent the y coordinate on the viewBox attribute.
329 
330             if(viewBoxValues[2] > 300){    //star
331                 viewBoxValues[0] = 250;
332                 viewBoxValues[1] = 75;
333             }
334             else{
335                 viewBoxValues[0] = 0;
336                 viewBoxValues[1] = 0;                
337             }
338 
339             cln.setAttribute('viewBox', viewBoxValues.join(' '));
340             colorDiv.appendChild(cln);                                    
341         }
342 
343         colorDiv.style.height = divHeight + "px";
344         colorDiv.style.width = divWidth + "px";
345         return trDiv;        
346     },
347     parseColor: function(value, opacity){
348         if(value.length == 7){
349             var str = value.substr(1,6);
350             var rgb1 = parseInt(str.substr(0, 2), 16);              
351             var rgb2 = parseInt(str.substr(2, 2), 16);
352             var rgb3 = parseInt(str.substr(4, 2), 16);
353             return "rgba("+rgb1+","+rgb2+","+rgb3+","+opacity+")";
354         }
355         else{
356             return value;
357         }
358     },
359     CLASS_NAME: "OpenLayers.Control.LegendControl"
360 });

LegendControl的样式设置如下:

 1 /*
 2  * olControlLegendControl
 3 */
 4 .olControlLegendControl {
 5     position: absolute;
 6     left: 0px;
 7     bottom: 0px;
 8     width: 18em;
 9     font-family: sans-serif;
10     font-size: smaller;
11     margin-top: 3px;
12     margin-left: 0px;
13     margin-bottom: 0px;
14     color: darkblue;
15     background-color: transparent;    
16 }
17 .olControlLegendControl .legendDiv {
18     padding-top: 5px;
19     padding-left: 10px;
20     padding-bottom: 5px;
21     padding-right: 10px;
22     background-color: rgba(200, 200, 200, 0.5);
23 }
24 .olControlLegendControl .legendDiv .title{
25     margin-top: 3px;
26     margin-left: 40px;
27     margin-bottom: 3px;
28     display: inline-block;
29     height: 30px;
30     font-family: sans-serif;
31     font-weight: bold;
32     font-size: 20px;
33 }
34 .olControlLegendControl .legendDiv .item{
35     margin-top: 3px;
36     margin-left: 3px;
37     margin-bottom: 3px;
38 }

 效果图

 

posted @ 2017-10-20 12:01  GISer-Li  阅读(3768)  评论(0编辑  收藏  举报