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
何为扩展,顾名思义,就是在原有控件属性.事件的基础上拓展自己需要或实用的属性.事件等等.或者可以理解为,现有的控件已经不能完全满足我(的需求)了.好的扩展会使控件更加完善,实用,好用.不好的扩展,说白 ...
随机推荐
- css 横线中间添加文字
demoline01.02选一个用足够了 <style> .demo_line_01 { width: 200px;/*这指的是文字的宽度*/ padding: 0 20px 0; m ...
- Word Formation
构词 Word Formation 1.派生Derivation 2.合成Compounding 3.截短Clipping 4.混合Blending 1派生Derivation 1).前缀 除少数英语 ...
- 找不到ifconfig命令
对于新安装的系统,可能会缺少ifconfig命令,这是因为少安装了net-tools工具,所以只要安装上即可. yum install net-tools -y
- java 统计文件注释个数
参考:https://segmentfault.com/q/1010000012636380/a-1020000012640905 题目:统计文件中//和/* */注释的个数,双引号中的不算 impo ...
- 在Mac OS X使用Elasticsearch的基本流程
这篇日志的目的非常easy,就是记录一些主要的流程.要在OS X上使用Elasticsearch,事实上非常easy,在这里:https://www.elastic.co/downloads/elas ...
- 使用win32ole进行页面加载和跳转
require "win32ole" #包含库 ie = WIN32OLE.new('internetExplorer.Application') ie.visible = tru ...
- BFC(Block Formatting Context)基础分析
W3C官方对于BFC的描述只有3小段,强烈建议想理解BFC的朋友先去看看,链接见文末. 常见的文档流分为:定位流.浮动流.普通流3种.BFC是普通流中的一种. 本文提出3个问题并给出使用BFC来解决这 ...
- beego——模型定义
复杂的模型定义不是必须的,此功能用作数据库数据转换和自动建表 默认的表名规则,使用驼峰转蛇形: AuthUser -> auth_user Auth_User -> auth__user ...
- CodeForces - 451E Devu and Flowers (容斥+卢卡斯)
题意:有N个盒子,每个盒子里有fi 朵花,求从这N个盒子中取s朵花的方案数.两种方法不同当且仅当两种方案里至少有一个盒子取出的花的数目不同. 分析:对 有k个盒子取出的数目超过了其中的花朵数,那么此时 ...
- HDU - 3829 Cat VS Dog (二分图最大独立集)
题意:P个小朋友,每个人有喜欢的动物和讨厌的动物.留下喜欢的动物并且拿掉讨厌的动物,这个小朋友就会开心.问最多有几个小朋友能开心. 分析:对于每个动物来说,可能既有人喜欢又有人讨厌,那么这样的动物实际 ...