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

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

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

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

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

代码如下:

 OpenLayers.Control.LegendControl = OpenLayers.Class(OpenLayers.Control, {
legendDiv: null,
layers: [],
colorDiv_w: 30,
colorDiv_h: 20,
/*
* layers --Array
* */
initialize: function (layers, options) {
OpenLayers.Control.prototype.initialize.apply(this, options); this.setLayers(layers);
},
setMap: function(map) {
var me = this;
OpenLayers.Control.prototype.setMap.apply(this, arguments);
if(me.map){
me.map.events.register("moveend", me, me.redraw);
me.map.events.register("changelayer", me, function(evt){
if(evt.property == "visibility")
this.redraw();
});
}
},
//{Array or Object}
setLayers: function(layers){
var me = this;
if(OpenLayers.Util.isArray(layers)){
me.layers = layers;
}
},
addLayer: function(layer){
this.layers.push(layer); this.redraw();
},
redraw: function(){
if(this.div.style.display == "none"){
return;
}
if(this.legendDiv){
this.div.removeChild(this.legendDiv);
this.legendDiv = null;
}
this.draw();
},
display: function(display) {
this.div.style.display = (display) ? "" : "none";
},
draw: function() {
OpenLayers.Control.prototype.draw.apply(this); // create layout divs
this.loadContents(); return this.div;
},
loadContents: function(){
if(!this.legendDiv){
this.legendDiv = document.createElement("div");
this.legendDiv.id = this.id + "_legendDiv";
OpenLayers.Element.addClass(this.legendDiv, "legendDiv");
this.div.appendChild(this.legendDiv); // create span
var labelSpan = document.createElement("label");
labelSpan.innerHTML = "Legend";
OpenLayers.Element.addClass(labelSpan, "title");
this.legendDiv.appendChild(labelSpan);
var brSpan = document.createElement("br");
this.legendDiv.appendChild(brSpan); for(var i = 0; i < this.layers.length;i ++){
var layer = this.layers[i];
if(!layer.getVisibility()){
continue;
}
var geom = getLayerDefaultGeometry(layer);  //获取图层中的几何要素
if(!geom)
continue; //one table corresponds to a layer
var labelLyr = document.createElement("label");
labelLyr.innerHTML = layer.name;
this.legendDiv.appendChild(labelLyr);
var tableDiv = document.createElement("table");
this.legendDiv.appendChild(tableDiv); var featArray = layer.features;
var unrenderFeatures = layer.unrenderedFeatures;
var arr = Object.keys(unrenderFeatures);
if(arr.length == featArray.length)
continue; var styleRules = layer.styleMap.styles["default"].rules;
var geomType = "point";
//decide symbolizer panel from geometry type
if(geom instanceof OpenLayers.Geometry.Point ||
geom instanceof OpenLayers.Geometry.MultiPoint) {
var allFilters = [];
var bElseFilter = 2;
for(var key in styleRules) {
var filter = styleRules[key].filter;
if(filter){
allFilters.push(filter);
}
else{ //no filter
bElseFilter = styleRules[key].elseFilter;
}
}
//
if(!bElseFilter){ //no else filter --deafault
var trDiv = this.createPointLegend(geom.id, "default");
tableDiv.appendChild(trDiv);
}
else{ //find filter's geometry id
var filterIDs = []; var findResults = {};
var findCount = 0;
for(var dex = 0; dex < featArray.length; dex ++){
if(findCount == allFilters.length + 1)
break; var feat = featArray[dex];
if(arr.indexOf(feat.id) >= 0)
continue; var beInfilter = false;
for(var fk = 0; fk < allFilters.length; fk ++){
var bFilter = allFilters[fk].evaluate(feat);
if(bFilter){
beInfilter = true;
if(!findResults[allFilters[fk].toString()]){
var svgId = feat.geometry.id;
filterIDs.push({
id:svgId,
label: allFilters[fk].toString()
});
findResults[allFilters[fk].toString()] = true;
findCount ++;
}
break;
} }
if(!beInfilter && (!findResults["default"])){ //false
var svgId = feat.geometry.id;
filterIDs.push({
id:svgId,
label: "default"
});
findResults["default"] = true;
findCount ++;
}
}
for(var fDex = 0; fDex < filterIDs.length; fDex ++){
var trDiv = this.createPointLegend(filterIDs[fDex].id, filterIDs[fDex].label);
tableDiv.appendChild(trDiv);
}
} continue; //skip next code
} else if(geom instanceof OpenLayers.Geometry.LineString ||
geom instanceof OpenLayers.Geometry.MultiLineString) {
geomType = "line"; } else if(geom instanceof OpenLayers.Geometry.LinearRing ||
geom instanceof OpenLayers.Geometry.Polygon ||
geom instanceof OpenLayers.Geometry.MultiPolygon) {
geomType = "polygon";
} for(var key in styleRules) {
var filter = styleRules[key].filter;
var sybol = styleRules[key].symbolizer;
var labelTxt = "";
if(filter) {
labelTxt = filter.toString();
}
else{
labelTxt = "default";
} var trDiv = document.createElement("tr");
tableDiv.appendChild(trDiv);
var colorTd = document.createElement("td");
trDiv.appendChild(colorTd); var labelTd = document.createElement("td");
trDiv.appendChild(labelTd); var itemLabel = document.createElement("label");
itemLabel.style = "margin-left:5px;position:relative;top:3px;";
itemLabel.innerHTML = labelTxt;
labelTd.appendChild(itemLabel); if(geomType == "line"){
if(sybol.Line){
var colorDiv = this.createLineLegend(sybol.Line);
colorTd.appendChild(colorDiv);
}
}
else if(geomType == "polygon"){
if(sybol.Polygon){
var colorDiv = this.createPolygonLegend(sybol.Polygon);
colorTd.appendChild(colorDiv);
}
}
}
} }
},
createPolygonLegend: function(polygonSybol){
var colorDiv = document.createElement("div");
if(polygonSybol.fill){
var color = this.parseColor(polygonSybol.fillColor, polygonSybol.fillOpacity);
colorDiv.style.background = color;
}
if(polygonSybol.stroke){
var dashStyle = polygonSybol.strokeDashstyle;
var color = this.parseColor(polygonSybol.strokeColor, polygonSybol.strokeOpacity);
var width = polygonSybol.strokeWidth + "px";
colorDiv.style.border = width + " " + dashStyle + " " + color;
}
colorDiv.style.height = this.colorDiv_h + "px";
colorDiv.style.width = this.colorDiv_w + "px";
return colorDiv;
},
/*
* <svg><polyline points="20,27,34,21" fill="none" stroke="#550000" stroke-opacity="1" stroke-width="3"
* stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none"></polyline></svg>
* */
createLineLegend: function(lineSybol){
var colorDiv = document.createElement("div");
colorDiv.style.height = this.colorDiv_h + "px";
colorDiv.style.width = this.colorDiv_w + "px"; var lineHtml = '<svg width="100%" height="100%">';
lineHtml += '<polyline points="2,2,28,18" fill="none" stroke="' + lineSybol.strokeColor
+ '" stroke-opacity="'+ lineSybol.strokeOpacity +'" stroke-width="'+ lineSybol.strokeWidth + '"';
lineHtml += ' stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none"></polyline></svg>';
colorDiv.innerHTML = lineHtml; return colorDiv;
},
createPointLegend: function(svgId, label){
var trDiv = document.createElement("tr");
var svgEle = document.getElementById(svgId);
if(!svgEle){
return trDiv;
}
var colorTd = document.createElement("td");
trDiv.appendChild(colorTd); var labelTd = document.createElement("td");
trDiv.appendChild(labelTd);
var itemLabel = document.createElement("label");
itemLabel.style = "margin-left:5px;position:relative;top:3px;";
itemLabel.innerHTML = label;
labelTd.appendChild(itemLabel); var colorDiv = document.createElement("div");
colorTd.appendChild(colorDiv);
var divHeight = this.colorDiv_h;
var divWidth = this.colorDiv_w; var cln = svgEle.cloneNode(true);
if(cln.nodeName.toLowerCase() != "svg"){ //circle,image
var rVal = cln.getAttribute("r");
if(cln.hasAttribute("x") && cln.hasAttribute("y")){
cln.setAttribute("x", rVal);
cln.setAttribute("y", rVal);
}
if(cln.hasAttribute("cx") && cln.hasAttribute("cy")){
cln.setAttribute("cx", rVal);
cln.setAttribute("cy", rVal);
}
if(cln.hasAttribute("transform")){
var transform = cln.getAttribute("transform");
if(transform.indexOf('rotate(') >= 0){
var transValues = transform.split('rotate(');
var kk = null;
if(transValues.length == 1){
kk = 0;
}
else if(transValues.length > 1){
kk = 1;
}
if(kk != null){
var str = transValues[kk];
var sp = str.indexOf(')');
var rotString = str.substring(0, sp); var ww = parseFloat(cln.getAttribute('width'));
var hh = parseFloat(cln.getAttribute('height'));
if(ww >= divWidth)
divWidth = ww + 2;
if(hh >= divWidth)
divHeight = hh + 2; var rotValues = rotString.split(' ');
rotValues[1] = ww / 2;
rotValues[2] = hh / 2; transValues[kk] = rotValues.join(' ') + str.substring(sp);
cln.setAttribute('transform',transValues.join('rotate('));
}
} }
//innerHTML
colorDiv.innerHTML = '<svg width="100%" height="100%"></svg>';
var svgNode = colorDiv.firstChild;
svgNode.appendChild(cln);
colorDiv.appendChild(svgNode);
}
else{
//change viewBox --from(0,0)
var viewBox = cln.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute.
var viewBoxValues = viewBox.split(' '); // Create an array and insert each individual view box attribute value (assume they're seperated by a single whitespace character). /* The array is filled with strings, convert the first two viewBox values to floats: */
viewBoxValues[0] = parseFloat(viewBoxValues[0]); // Represent the x-coordinate on the viewBox attribute.
viewBoxValues[1] = parseFloat(viewBoxValues[1]); // Represent the y coordinate on the viewBox attribute.
viewBoxValues[2] = parseFloat(viewBoxValues[2]); // Represent the y coordinate on the viewBox attribute. if(viewBoxValues[2] > 300){ //star
viewBoxValues[0] = 250;
viewBoxValues[1] = 75;
}
else{
viewBoxValues[0] = 0;
viewBoxValues[1] = 0;
} cln.setAttribute('viewBox', viewBoxValues.join(' '));
colorDiv.appendChild(cln);
} colorDiv.style.height = divHeight + "px";
colorDiv.style.width = divWidth + "px";
return trDiv;
},
parseColor: function(value, opacity){
if(value.length == 7){
var str = value.substr(1,6);
var rgb1 = parseInt(str.substr(0, 2), 16);
var rgb2 = parseInt(str.substr(2, 2), 16);
var rgb3 = parseInt(str.substr(4, 2), 16);
return "rgba("+rgb1+","+rgb2+","+rgb3+","+opacity+")";
}
else{
return value;
}
},
CLASS_NAME: "OpenLayers.Control.LegendControl"
});

LegendControl的样式设置如下:

 /*
* olControlLegendControl
*/
.olControlLegendControl {
position: absolute;
left: 0px;
bottom: 0px;
width: 18em;
font-family: sans-serif;
font-size: smaller;
margin-top: 3px;
margin-left: 0px;
margin-bottom: 0px;
color: darkblue;
background-color: transparent;
}
.olControlLegendControl .legendDiv {
padding-top: 5px;
padding-left: 10px;
padding-bottom: 5px;
padding-right: 10px;
background-color: rgba(200, 200, 200, 0.5);
}
.olControlLegendControl .legendDiv .title{
margin-top: 3px;
margin-left: 40px;
margin-bottom: 3px;
display: inline-block;
height: 30px;
font-family: sans-serif;
font-weight: bold;
font-size: 20px;
}
.olControlLegendControl .legendDiv .item{
margin-top: 3px;
margin-left: 3px;
margin-bottom: 3px;
}

效果图

openlayers2地图控件扩展:图例控件LegendControl的更多相关文章

  1. 【完全开源】百度地图Web service API C#.NET版,带地图显示控件、导航控件、POI查找控件

    目录 概述 功能 如何使用 参考帮助 概述 源代码主要包含三个项目,BMap.NET.BMap.NET.WindowsForm以及BMap.NET.WinformDemo. BMap.NET 对百度地 ...

  2. 扩展GridView控件——为内容项添加拖放及分组功能

    引言 相信大家对GridView都不陌生,是非常有用的控件,用于平铺有序的显示多个内容项.打开任何WinRT应用或者是微软合作商的网站,都会在APP中发现GridView的使用.“Tiles”提供了一 ...

  3. 验证控件插图扩展控件ValidatorCalloutExtender(用于扩展验证控件)和TextBoxWatermarkExtender

    <asp:ScriptManager ID="ScriptManager1" runat="server">  </asp:ScriptMan ...

  4. [转]Asp.Net MVC 扩展联想控件

    本文转自:http://www.cnblogs.com/bright-lin/archive/2013/02/06/MVC_SuggestBox.html 在web中,为改善用户体验,我们常会将一些文 ...

  5. cocos2dx - 控件扩展之pageview循环显示

    接上一节内容:cocos2dx - shader实现任意动画的残影效果 本节主要讲一下扩展PageView控件功能 在实际游戏应用中,经常会碰到用原来的控件难以实现的功能.这时候就需要根据需求,通过选 ...

  6. 【转】【完全开源】百度地图Web service API C#.NET版,带地图显示控件、导航控件、POI查找控件

    [转][完全开源]百度地图Web service API C#.NET版,带地图显示控件.导航控件.POI查找控件 目录 概述 功能 如何使用 参考帮助 概述 源代码主要包含三个项目,BMap.NET ...

  7. 给easyui datebox时间框控件扩展一个清空的实例

    给easyui datebox扩展一个清空的实例 步骤一:拓展插件 /** * 给时间框控件扩展一个清除的按钮 */ $.fn.datebox.defaults.cleanText = '清空'; ( ...

  8. 扩展GroupBox控件

    1.GroupBox的边框颜色可以自行设置: 2.GroupBox可以设置边框的为圆角: 3.设置GroupBox标题在控件中的位置. 4.设置GroupBox标题的字体和颜色. 具体实现步骤Pane ...

  9. 一个动态扩展表格控件列和行的 jQuery 插件

    一个动态扩展表格控件列和行的 jQuery 插件 不过这并不影响使用鸭! 看这里:https://github.com/zhuwansu/table-ext.js 一个简单的示范 html <t ...

  10. 玩转控件:扩展Dev中SimpleButton

    何为扩展,顾名思义,就是在原有控件属性.事件的基础上拓展自己需要或实用的属性.事件等等.或者可以理解为,现有的控件已经不能完全满足我(的需求)了.好的扩展会使控件更加完善,实用,好用.不好的扩展,说白 ...

随机推荐

  1. iOS UITextView 展示html

    NSString *htmlString = @"<h1>Header</h1><h2>Subheader</h2><p>Some ...

  2. HTTP协议包分析(小马上传大马)

    最近工作内容是分析防火墙日志,看日志是正确,本地实验小马上传大马  抓取http包如下.可以在分析过程中进行借鉴. 该http请求的行为是通过小马,在小马的当前目录创建一个dama.php的文件,文件 ...

  3. Exchange Version and UpdateRollups

    Exchange Server 2010 Product name Build number Date KB Microsoft Exchange Server 2010 RTM 14.0.639.2 ...

  4. MFC 单选按钮组向导添加和动态创建

    单选按钮组的动态生成 单选按钮也属于CButton类,但由于单选按钮总是成组使用的,所以它在制作和使用上与普通按钮有一定区别. 假设有三个单选按钮组成一组,初始时,第一个单选按钮处于选中状态. 我们先 ...

  5. 常用的SQLAlchemy列选项

    常用的SQLAlchemy列选项 https://blog.csdn.net/weixin_41896508/article/details/80772238 选项名 说明 primary_key 如 ...

  6. MySQL 乐观锁与悲观锁

    悲观锁 悲观锁(Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁. 悲观锁: ...

  7. 原!mysql5.6 存储过程 批量建表

    由于业务需求,需要按天分表,因此写了个存储过程,根据时间生成表. 根据createTime 的时间,以及 while循环的变量设置范围,生成该指定日期及之后的多张表. BEGIN ); ); ; '; ...

  8. PostgreSQL: WITH Queries (Common Table Expressions)

    WITH 允许在 SELECT 语句中定义"表"的表达式,这个"表"的表达式称之为"公共表表达式(Common Table Expression)&q ...

  9. Python 模块之Logging——常用handlers的使用

    一.StreamHandler 流handler——包含在logging模块中的三个handler之一. 能够将日志信息输出到sys.stdout, sys.stderr 或者类文件对象(更确切点,就 ...

  10. centos7 重启网卡失败

    今天在centOS 7 network服务重启不了 现把各种解决方法归纳整理,希望能让后面的同学少走点歪路... 首先看问题:执行service network restart命令后出现下面的错误: ...