OpenLayers: layerSwitcher扩展,加入group layer功能
做开发时,有时候图层很多,需要有同时打开关闭多个图层的功能,但是正式版的layerSwitcher不支持group layer功能.
从网上搜到layerSwitcher的扩展,是在源代码里添加对grouplayer的操作和事件支持.
对layerSwitcher.js进行修改后,需要重新build一下,生成新的openlayers.js
在写script添加图层的时候,加入group信息,如下例子:
代码var dm = new OpenLayers.Layer.WMS( "DM Solutions Transit",
"http://www2.dmsolutions.ca/cgi-bin/mswms_gmap",
{layers: "rail,road",
transparent: "true", format: "image/png"
},
{ //将"DM Solutions Transit"放入名叫Transit的组里
group:"Transit"
});
如果想嵌套图层,只需要加“/”表示层级关系
...
group: "Transit/Roads",
...
看看效果图:
这是修改后的layerSwitcher.js的压缩文件: 下载
下面详细列出layerSwitcher.js需要添加的代码:
粗体字为添加的代码
代码
minimizeDiv: null,
/**
* Property: maximizeDiv
* {DOMElement}
*/
maximizeDiv: null,
/**
* APIProperty: ascending
* {Boolean}
*/
ascending: true,
/** * Property: groupDivs
* Object with {DOMElements}, {Booleans} and {Strings}
*/
groups: {
groupDivs:{},
checked: {},
layers:{},
display: {}
},
/**
* Property: maximizeDiv
* {DOMElement}
*/
maximizeDiv: null,
/**
* APIProperty: ascending
* {Boolean}
*/
ascending: true,
/** * Property: groupDivs
* Object with {DOMElements}, {Booleans} and {Strings}
*/
groups: {
groupDivs:{},
checked: {},
layers:{},
display: {}
},
代码
clearLayersArray: function(layersType) {
var layers = this[layersType + "Layers"];
if (layers) {
for(var i=0, len=layers.length; i<len ; i++) {
var layer = layers[i];
OpenLayers.Event.stopObservingElement(layer.inputElem);
OpenLayers.Event.stopObservingElement(layer.labelSpan);
}
}
this[layersType + "LayersDiv"].innerHTML = "";
this[layersType + "Layers"] = [];
this.groups.groupDivs = {};
},
var layers = this[layersType + "Layers"];
if (layers) {
for(var i=0, len=layers.length; i<len ; i++) {
var layer = layers[i];
OpenLayers.Event.stopObservingElement(layer.inputElem);
OpenLayers.Event.stopObservingElement(layer.labelSpan);
}
}
this[layersType + "LayersDiv"].innerHTML = "";
this[layersType + "Layers"] = [];
this.groups.groupDivs = {};
},
代码
redraw: function() {
//if the state hasn't changed since last redraw, no need
// to do anything. Just return the existing div.
if (!this.checkRedraw()) {
return this.div;
}
//clear out previous layers
this.clearLayersArray("base");
this.clearLayersArray("data");
var containsOverlays = false;
var containsBaseLayers = false;
// Save state -- for checking layer if the map state changed.
// We save this before redrawing, because in the process of redrawing
// we will trigger more visibility changes, and we want to not redraw
// and enter an infinite loop.
var len = this.map.layers.length;
this.layerStates = new Array(len);
for (var i=0; i <len; i++) {
var layer = this.map.layers[i];
this.layerStates[i] = {
'name': layer.name,
'visibility': layer.visibility,
'inRange': layer.inRange,
'id': layer.id
};
/**
//if the state hasn't changed since last redraw, no need
// to do anything. Just return the existing div.
if (!this.checkRedraw()) {
return this.div;
}
//clear out previous layers
this.clearLayersArray("base");
this.clearLayersArray("data");
var containsOverlays = false;
var containsBaseLayers = false;
// Save state -- for checking layer if the map state changed.
// We save this before redrawing, because in the process of redrawing
// we will trigger more visibility changes, and we want to not redraw
// and enter an infinite loop.
var len = this.map.layers.length;
this.layerStates = new Array(len);
for (var i=0; i <len; i++) {
var layer = this.map.layers[i];
this.layerStates[i] = {
'name': layer.name,
'visibility': layer.visibility,
'inRange': layer.inRange,
'id': layer.id
};
/**
* create group divs
*/
if (layer.group && !layer.isBaseLayer) {
layer.group = layer.group.replace(/\/$/,"");
layer.group = layer.group.replace(/^\//,"");
this.createGroupDiv(layer.group);
}
}
var layers = this.map.layers.slice();
*/
if (layer.group && !layer.isBaseLayer) {
layer.group = layer.group.replace(/\/$/,"");
layer.group = layer.group.replace(/^\//,"");
this.createGroupDiv(layer.group);
}
}
var layers = this.map.layers.slice();
代码
// create line break
var br = document.createElement("br");
var groupArray = (baseLayer) ? this.baseLayers
: this.dataLayers;
groupArray.push({
'layer': layer,
'inputElem': inputElem,
'labelSpan': labelSpan
});
var groupDiv = (baseLayer) ? this.baseLayersDiv
: this.dataLayersDiv;
groupDiv.appendChild(inputElem);
groupDiv.appendChild(labelSpan);
groupDiv.appendChild(br);
/*
* layer group for data layers
*/
if (!baseLayer) {
// no group
if (layer.group == null) {
this.dataLayersDiv.appendChild(inputElem);
this.dataLayersDiv.appendChild(labelSpan);
this.dataLayersDiv.appendChild(br);
}
// group exists it is most probably allready there
else {
var groupname = layer.group;
var div = this.groups.groupDivs[groupname];
div.appendChild(inputElem);
div.appendChild(labelSpan);
div.appendChild(br);
// append layer to the group
this.appendLayerToGroups(layer);
}
}
// base layers
else {
this.baseLayersDiv.appendChild(inputElem);
this.baseLayersDiv.appendChild(labelSpan);
this.baseLayersDiv.appendChild(br);
}
}
}
// if no overlays, dont display the overlay label
this.dataLbl.style.display = (containsOverlays) ? "" : "none";
var br = document.createElement("br");
var groupArray = (baseLayer) ? this.baseLayers
: this.dataLayers;
groupArray.push({
'layer': layer,
'inputElem': inputElem,
'labelSpan': labelSpan
});
var groupDiv = (baseLayer) ? this.baseLayersDiv
: this.dataLayersDiv;
groupDiv.appendChild(inputElem);
groupDiv.appendChild(labelSpan);
groupDiv.appendChild(br);
/*
* layer group for data layers
*/
if (!baseLayer) {
// no group
if (layer.group == null) {
this.dataLayersDiv.appendChild(inputElem);
this.dataLayersDiv.appendChild(labelSpan);
this.dataLayersDiv.appendChild(br);
}
// group exists it is most probably allready there
else {
var groupname = layer.group;
var div = this.groups.groupDivs[groupname];
div.appendChild(inputElem);
div.appendChild(labelSpan);
div.appendChild(br);
// append layer to the group
this.appendLayerToGroups(layer);
}
}
// base layers
else {
this.baseLayersDiv.appendChild(inputElem);
this.baseLayersDiv.appendChild(labelSpan);
this.baseLayersDiv.appendChild(br);
}
}
}
// if no overlays, dont display the overlay label
this.dataLbl.style.display = (containsOverlays) ? "" : "none";
代码
onInputClick: function(e) {
if (!this.inputElem.disabled) {
if (this.inputElem.type == "radio") {
this.inputElem.checked = true;
this.layer.map.setBaseLayer(this.layer);
} else {
this.inputElem.checked = !this.inputElem.checked;
this.layerSwitcher.updateMap();
}
}
OpenLayers.Event.stop(e);
},
/**
if (!this.inputElem.disabled) {
if (this.inputElem.type == "radio") {
this.inputElem.checked = true;
this.layer.map.setBaseLayer(this.layer);
} else {
this.inputElem.checked = !this.inputElem.checked;
this.layerSwitcher.updateMap();
}
}
OpenLayers.Event.stop(e);
},
/**
* Method:
* A group label has been clicked, check or uncheck its corresponding input
*
* Parameters:
* e - {Event}
*
* Context:
* - {DOMElement} inputElem
* - {<OpenLayers.Control.LayerSwitcher>} layerSwitcher
* - {DOMElement} groupDiv
*/
onInputGroupClick: function(e) {
// setup the check value
var check = !this.inputElem.checked;
// get all <input></input> tags in this div
var inputs = this.groupDiv.getElementsByTagName("input");
// check the group input, other inputs are in groupDiv,
// inputElem is in parent div
this.inputElem.checked=check;
// store to groupCheckd structure, where it can be later found
this.layerSwitcher.groups.checked[this.inputElem.value] = check;
for (var i = 0; i < inputs.length; i++) {
// same as above
inputs[i].checked=check;
this.layerSwitcher.groups.checked[inputs[i].value] = check;
}
// groups are done, now the layers
var dataLayers = this.layerSwitcher.dataLayers;
for (var j = 0; j < dataLayers.length; j++) {
var layerEntry = dataLayers[j];
if (this.layerSwitcher.isInGroup(
this.inputElem.value,layerEntry.layer.id)) {
layerEntry.inputElem.checked = check;
layerEntry.layer.setVisibility(check);
}
}
OpenLayers.Event.stop(e);
},
* A group label has been clicked, check or uncheck its corresponding input
*
* Parameters:
* e - {Event}
*
* Context:
* - {DOMElement} inputElem
* - {<OpenLayers.Control.LayerSwitcher>} layerSwitcher
* - {DOMElement} groupDiv
*/
onInputGroupClick: function(e) {
// setup the check value
var check = !this.inputElem.checked;
// get all <input></input> tags in this div
var inputs = this.groupDiv.getElementsByTagName("input");
// check the group input, other inputs are in groupDiv,
// inputElem is in parent div
this.inputElem.checked=check;
// store to groupCheckd structure, where it can be later found
this.layerSwitcher.groups.checked[this.inputElem.value] = check;
for (var i = 0; i < inputs.length; i++) {
// same as above
inputs[i].checked=check;
this.layerSwitcher.groups.checked[inputs[i].value] = check;
}
// groups are done, now the layers
var dataLayers = this.layerSwitcher.dataLayers;
for (var j = 0; j < dataLayers.length; j++) {
var layerEntry = dataLayers[j];
if (this.layerSwitcher.isInGroup(
this.inputElem.value,layerEntry.layer.id)) {
layerEntry.inputElem.checked = check;
layerEntry.layer.setVisibility(check);
}
}
OpenLayers.Event.stop(e);
},
代码
onLayerClick: function(e) {
this.updateMap();
},
/**
* Method: onGroupClick
* Make the div with layers invisible
*
* Context:
* layergroup - {String}
* groups - {Array} of {DOMElements}
*/
onGroupClick: function(e) {
var layergroup = this.layergroup;
var div = this.groups.groupDivs[layergroup];
if (div) {
if (div.style.display != "block") {
div.style.display = "block";
this.groups.display[layergroup] = "block";
}
else {
div.style.display = "none";
this.groups.display[layergroup] = "none";
}
}
},
this.updateMap();
},
/**
* Method: onGroupClick
* Make the div with layers invisible
*
* Context:
* layergroup - {String}
* groups - {Array} of {DOMElements}
*/
onGroupClick: function(e) {
var layergroup = this.layergroup;
var div = this.groups.groupDivs[layergroup];
if (div) {
if (div.style.display != "block") {
div.style.display = "block";
this.groups.display[layergroup] = "block";
}
else {
div.style.display = "none";
this.groups.display[layergroup] = "none";
}
}
},
代码
mouseUp: function(evt) {
if (this.isMouseDown) {
this.isMouseDown = false;
this.ignoreEvent(evt);
}
},
/**
* Method: createGroupDiv
* Creates <div></div> element for group of layers defined by input string.
*
* Parameters:
* layergroup - {Strin} with group structure as "Parent Group/It's child"
*
* Returns:
* {DOMElement} <div></div> object for this group of layers
*/
createGroupDiv: function(layergroup) {
var groupNames = layergroup.split("/"); // array with layer names
var groupName = groupNames[groupNames.length-1]; // name of the last group in the line
var br = document.createElement("br");
var groupDiv = this.groups.groupDivs[layergroup];
// groupDiv does not exist: create
if (!groupDiv) {
// search for the parent div - it can be another group div, or
// this dataLayersDiv directly
var parentDiv = this.groups.groupDivs[groupNames.slice(0,groupNames.length-2).join("/")];
if (!parentDiv) {
// dataLayersDiv is parent div
if (groupNames.length == 1) {
parentDiv = this.dataLayersDiv;
}
// there is no such thing, like parent div,
else {
parentDiv = this.createGroupDiv( groupNames.slice(0,groupNames.length-1).join("/"));
}
}
// create the div
groupDiv = document.createElement("div");
groupDiv.classes="olLayerGroup";
groupDiv.style.marginLeft="10px";
groupDiv.style.marginBottom="5px";
if (!this.groups.display[layergroup]) {
this.groups.display[layergroup] = "block";
}
groupDiv.style.display= this.groups.display[layergroup];
this.groups.groupDivs[layergroup] = groupDiv;
// create the label
var groupLbl = document.createElement("span");
groupLbl.innerHTML="<u>"+groupName+"</u><br/>";
groupLbl.style.marginTop = "3px";
groupLbl.style.marginLeft = "3px";
groupLbl.style.marginBottom = "3px";
groupLbl.style.fontWeight = "bold";
// setup mouse click event on groupLbl
OpenLayers.Event.observe(groupLbl, "mouseup",
OpenLayers.Function.bindAsEventListener(
this.onGroupClick, {layergroup: layergroup, groups:
this.groups}));
// create input checkbox
var groupInput = document.createElement("input");
groupInput.id = "input_" + groupNames.join("_");
groupInput.name = groupNames.join("_");
groupInput.type = "checkbox";
groupInput.value = layergroup;
groupInput.checked = false;
groupInput.defaultChecked = false;
if (!this.groups.checked[layergroup]) {
this.groups.checked[layergroup] = false;
}
groupInput.checked = this.groups.checked[layergroup];
groupInput.defaultChecked = this.groups.checked[layergroup];
// create empty array of layers
if (!this.groups.layers[layergroup]) {
this.groups.layers[layergroup] = [];
}
// setup mouse click event on groupInput
var context = {groupDiv: groupDiv,
layerSwitcher: this,
inputElem: groupInput};
OpenLayers.Event.observe(groupInput, "mouseup",
OpenLayers.Function.bindAsEventListener(
this.onInputGroupClick, context));
// append to parent div
parentDiv.appendChild(groupInput);
parentDiv.appendChild(groupLbl);
parentDiv.appendChild(groupDiv);
}
return this.groups.groupDivs[layergroup];
},
appendLayerToGroups: function(layer) {
var groupNames = layer.group.split("/");
var groupName = null;
for (var i = 1; i <= groupNames.length; i++) {
var groupName = groupNames.slice(0,i).join("/");
if (!this.isInGroup(groupName,layer.id)) {
this.groups.layers[groupName].push(layer);
}
}
},
isInGroup: function (groupName, id) {
for (var j = 0; j < this.groups.layers[groupName].length; j++) {
if (this.groups.layers[groupName][j].id == id) {
return true;
}
}
return false;
},
if (this.isMouseDown) {
this.isMouseDown = false;
this.ignoreEvent(evt);
}
},
/**
* Method: createGroupDiv
* Creates <div></div> element for group of layers defined by input string.
*
* Parameters:
* layergroup - {Strin} with group structure as "Parent Group/It's child"
*
* Returns:
* {DOMElement} <div></div> object for this group of layers
*/
createGroupDiv: function(layergroup) {
var groupNames = layergroup.split("/"); // array with layer names
var groupName = groupNames[groupNames.length-1]; // name of the last group in the line
var br = document.createElement("br");
var groupDiv = this.groups.groupDivs[layergroup];
// groupDiv does not exist: create
if (!groupDiv) {
// search for the parent div - it can be another group div, or
// this dataLayersDiv directly
var parentDiv = this.groups.groupDivs[groupNames.slice(0,groupNames.length-2).join("/")];
if (!parentDiv) {
// dataLayersDiv is parent div
if (groupNames.length == 1) {
parentDiv = this.dataLayersDiv;
}
// there is no such thing, like parent div,
else {
parentDiv = this.createGroupDiv( groupNames.slice(0,groupNames.length-1).join("/"));
}
}
// create the div
groupDiv = document.createElement("div");
groupDiv.classes="olLayerGroup";
groupDiv.style.marginLeft="10px";
groupDiv.style.marginBottom="5px";
if (!this.groups.display[layergroup]) {
this.groups.display[layergroup] = "block";
}
groupDiv.style.display= this.groups.display[layergroup];
this.groups.groupDivs[layergroup] = groupDiv;
// create the label
var groupLbl = document.createElement("span");
groupLbl.innerHTML="<u>"+groupName+"</u><br/>";
groupLbl.style.marginTop = "3px";
groupLbl.style.marginLeft = "3px";
groupLbl.style.marginBottom = "3px";
groupLbl.style.fontWeight = "bold";
// setup mouse click event on groupLbl
OpenLayers.Event.observe(groupLbl, "mouseup",
OpenLayers.Function.bindAsEventListener(
this.onGroupClick, {layergroup: layergroup, groups:
this.groups}));
// create input checkbox
var groupInput = document.createElement("input");
groupInput.id = "input_" + groupNames.join("_");
groupInput.name = groupNames.join("_");
groupInput.type = "checkbox";
groupInput.value = layergroup;
groupInput.checked = false;
groupInput.defaultChecked = false;
if (!this.groups.checked[layergroup]) {
this.groups.checked[layergroup] = false;
}
groupInput.checked = this.groups.checked[layergroup];
groupInput.defaultChecked = this.groups.checked[layergroup];
// create empty array of layers
if (!this.groups.layers[layergroup]) {
this.groups.layers[layergroup] = [];
}
// setup mouse click event on groupInput
var context = {groupDiv: groupDiv,
layerSwitcher: this,
inputElem: groupInput};
OpenLayers.Event.observe(groupInput, "mouseup",
OpenLayers.Function.bindAsEventListener(
this.onInputGroupClick, context));
// append to parent div
parentDiv.appendChild(groupInput);
parentDiv.appendChild(groupLbl);
parentDiv.appendChild(groupDiv);
}
return this.groups.groupDivs[layergroup];
},
appendLayerToGroups: function(layer) {
var groupNames = layer.group.split("/");
var groupName = null;
for (var i = 1; i <= groupNames.length; i++) {
var groupName = groupNames.slice(0,i).join("/");
if (!this.isInGroup(groupName,layer.id)) {
this.groups.layers[groupName].push(layer);
}
}
},
isInGroup: function (groupName, id) {
for (var j = 0; j < this.groups.layers[groupName].length; j++) {
if (this.groups.layers[groupName][j].id == id) {
return true;
}
}
return false;
},
-----------------------------------------------------------
佛对我说:你心里有尘。我用力的拭擦。