openlayers2地图控件扩展:图例控件LegendControl
因项目需要在地图中增加图例,以便专题地图查看或输出。
实现思路,折线和多边形图例直接由样式属性创建,多边形直接设置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的更多相关文章
- 【完全开源】百度地图Web service API C#.NET版,带地图显示控件、导航控件、POI查找控件
目录 概述 功能 如何使用 参考帮助 概述 源代码主要包含三个项目,BMap.NET.BMap.NET.WindowsForm以及BMap.NET.WinformDemo. BMap.NET 对百度地 ...
- 扩展GridView控件——为内容项添加拖放及分组功能
引言 相信大家对GridView都不陌生,是非常有用的控件,用于平铺有序的显示多个内容项.打开任何WinRT应用或者是微软合作商的网站,都会在APP中发现GridView的使用.“Tiles”提供了一 ...
- 验证控件插图扩展控件ValidatorCalloutExtender(用于扩展验证控件)和TextBoxWatermarkExtender
<asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptMan ...
- [转]Asp.Net MVC 扩展联想控件
本文转自:http://www.cnblogs.com/bright-lin/archive/2013/02/06/MVC_SuggestBox.html 在web中,为改善用户体验,我们常会将一些文 ...
- cocos2dx - 控件扩展之pageview循环显示
接上一节内容:cocos2dx - shader实现任意动画的残影效果 本节主要讲一下扩展PageView控件功能 在实际游戏应用中,经常会碰到用原来的控件难以实现的功能.这时候就需要根据需求,通过选 ...
- 【转】【完全开源】百度地图Web service API C#.NET版,带地图显示控件、导航控件、POI查找控件
[转][完全开源]百度地图Web service API C#.NET版,带地图显示控件.导航控件.POI查找控件 目录 概述 功能 如何使用 参考帮助 概述 源代码主要包含三个项目,BMap.NET ...
- 给easyui datebox时间框控件扩展一个清空的实例
给easyui datebox扩展一个清空的实例 步骤一:拓展插件 /** * 给时间框控件扩展一个清除的按钮 */ $.fn.datebox.defaults.cleanText = '清空'; ( ...
- 扩展GroupBox控件
1.GroupBox的边框颜色可以自行设置: 2.GroupBox可以设置边框的为圆角: 3.设置GroupBox标题在控件中的位置. 4.设置GroupBox标题的字体和颜色. 具体实现步骤Pane ...
- 一个动态扩展表格控件列和行的 jQuery 插件
一个动态扩展表格控件列和行的 jQuery 插件 不过这并不影响使用鸭! 看这里:https://github.com/zhuwansu/table-ext.js 一个简单的示范 html <t ...
- 玩转控件:扩展Dev中SimpleButton
何为扩展,顾名思义,就是在原有控件属性.事件的基础上拓展自己需要或实用的属性.事件等等.或者可以理解为,现有的控件已经不能完全满足我(的需求)了.好的扩展会使控件更加完善,实用,好用.不好的扩展,说白 ...
随机推荐
- iOS UITextView 展示html
NSString *htmlString = @"<h1>Header</h1><h2>Subheader</h2><p>Some ...
- HTTP协议包分析(小马上传大马)
最近工作内容是分析防火墙日志,看日志是正确,本地实验小马上传大马 抓取http包如下.可以在分析过程中进行借鉴. 该http请求的行为是通过小马,在小马的当前目录创建一个dama.php的文件,文件 ...
- Exchange Version and UpdateRollups
Exchange Server 2010 Product name Build number Date KB Microsoft Exchange Server 2010 RTM 14.0.639.2 ...
- MFC 单选按钮组向导添加和动态创建
单选按钮组的动态生成 单选按钮也属于CButton类,但由于单选按钮总是成组使用的,所以它在制作和使用上与普通按钮有一定区别. 假设有三个单选按钮组成一组,初始时,第一个单选按钮处于选中状态. 我们先 ...
- 常用的SQLAlchemy列选项
常用的SQLAlchemy列选项 https://blog.csdn.net/weixin_41896508/article/details/80772238 选项名 说明 primary_key 如 ...
- MySQL 乐观锁与悲观锁
悲观锁 悲观锁(Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁. 悲观锁: ...
- 原!mysql5.6 存储过程 批量建表
由于业务需求,需要按天分表,因此写了个存储过程,根据时间生成表. 根据createTime 的时间,以及 while循环的变量设置范围,生成该指定日期及之后的多张表. BEGIN ); ); ; '; ...
- PostgreSQL: WITH Queries (Common Table Expressions)
WITH 允许在 SELECT 语句中定义"表"的表达式,这个"表"的表达式称之为"公共表表达式(Common Table Expression)&q ...
- Python 模块之Logging——常用handlers的使用
一.StreamHandler 流handler——包含在logging模块中的三个handler之一. 能够将日志信息输出到sys.stdout, sys.stderr 或者类文件对象(更确切点,就 ...
- centos7 重启网卡失败
今天在centOS 7 network服务重启不了 现把各种解决方法归纳整理,希望能让后面的同学少走点歪路... 首先看问题:执行service network restart命令后出现下面的错误: ...