使用ArcGIS API for JavaScript实现类似ArcMap的图层控制面板Tab of Contents

最近由于项目需要封装了一个web端类似ArcMap中的Table of Contents的图层控制面板,暂时只是支持WMTS为 底图,动态服务和要素服务作为业务图层。

/*********封装接口************/
define(["dojo/_base/declare",
        "dojo/_base/lang",
        "esri/map",
        "esri/layers/WMTSLayer",
        "esri/layers/ArcGISDynamicMapServiceLayer",
        "esri/layers/FeatureLayer"
], function(Declare, Lang, Map, WMTSLayer, ArcGISDynamicMapServiceLayer, FeatureLayer) {
return Declare("AIMapToc", null, {
map:null,
ztree:null, 
layerIds:null,
allChildrenIds:null

constructor : function(_map){
this.map = _map;

// 控制服务及图层当前比例尺是否可见
map.on("zoom-end", Lang.hitch(this, function(){

// 更新图层树
this.updateTree();

}));
},
createTree:function(domId){

if(this.ztree != null){

// 重置ztree,因为跟踪map的addlayer事件,需要重新读取地图图层数据建立图层面板
this.ztree  = null;
$('#'+domId).empty();
}

var layerAutoNodes = [];// ztree节点集合
this.layerIds = this.map.layerIds;// 动态图层
var graphicsIds = this.map.graphicsLayerIds;// 几何图层
this.layerIds = this.layerIds.concat(graphicsIds);
var currentScale = this.map.getScale();// 当前比例尺
var isServiceScale = true;// 服务在当前比例尺下是否可见
var isLayerScale = true;// 图层在当前比例尺下是否可见
var check = false;//  节点选中情况

// 遍历所有的图层,构造ztree
for(var i = 0, len = this.layerIds.length;i < len;i++){


var layer = this.map.getLayer(this.layerIds[i]);
if(layer instanceof WMTSLayer){// 底图不加入图层面板

continue;
}else{


if(layer instanceof ArcGISDynamicMapServiceLayer){//动态地图服务


isServiceScale = (!layer.minScale || currentScale >= layer.maxScale && currentScale <= layer.minScale);// 不设置图层显示比例尺范围时minScale等于0
var layerInfos = layer.layerInfos;
isCheck = layer.visible;
layerAutoNodes.push({"name":"地图服务"+i,"id":i, "pId":-1,"checked":isCheck,"chkDisabled":!isServiceScale});
if(layerInfos && layerInfos.length > 0){
// 遍历服务的所有子图层
for(var j=0, len2 = layerInfos.length; j < len2; j++){

isLayerScale = (!layerInfos[j].minScale || currentScale >= layerInfos[j].maxScale && currentScale <= layerInfos[j].minScale);
isCheck = layerInfos[j].defaultVisibility;
var pId = layerInfos[j].parentLayerId;
if(pId == -1){// 一级子图层设置父id为当前服务序号
layerAutoNodes.push({"name":layerInfos[j].name,"id": (layerInfos[j].id + (i+1) * 1000), "pId":i,"checked":isCheck,"chkDisabled":!isLayerScale});
}else{// 大于一级子图层设置父id为(pId + (i+1) * 1000),主要是为了防止不同服务的子图层id重复,以后用的时候解密到自然id
layerAutoNodes.push({"name":layerInfos[j].name,"id": (layerInfos[j].id + (i+1) * 1000), "pId":(pId + (i+1) * 1000),"checked":isCheck,"chkDisabled":!isLayerScale});
}

}
}

}else if(layer instanceof FeatureLayer){// 要素地图服务
isServiceScale = (!layer.minScale || currentScale >= layer.maxScale && currentScale <= layer.minScale);
check = layer.visible;
layerAutoNodes.push({"name":"要素服务"+i,"id":i, "pId":-1,"checked":isCheck,"chkDisabled":!isServiceScale});

}else{// 其他图层类型忽略(有待扩展)
continue;
}
}
}

// ztree 初始化设置
var setting={
check: { 
         enable: true,  
 chkStyle: "checkbox" 
       },  
       view: {                                    
         dblClickExpand: true
       },                            
       data: {                                    
         simpleData: {                         
          enable: true,  
          idKey: "id",  
          pIdKey: "pId",  
          rootPId: -1  
         }                            
       }, 
        callback: {     
            onCheck: Lang.hitch(this,this.layersOnCheck)       
       } 
};
$('#'+domId).append("
"
); this.ztree = $.fn.zTree.init($("#layertree"),setting, layerAutoNodes); this.ztree.expandAll(true); // 主动触发一次,去除子节点都禁用时父节点未禁用的情况 this.updateTree(); }, // 节点点击操作函数 layersOnCheck:function (event, treeId, treeNode){ var id = treeNode.id;// 节点加密id var pid = treeNode.pId;// 节点加密父id var checked = treeNode.checked;// 节点选中情况 var layer = null;// 地图服务图层 var visibleLayers = [];// 可视化图层数组 this.allChildrenIds = [];// 节点的所有子节点自然序号 var layerId = null;// 图层id var layerSeq = null;// 地图服务序号 if(pid == -1){// 地图服务节点 layerSeq = id; layerId = this.layerIds[layerSeq]; layer = this.map.getLayer(layerId); // 设置图层可见情况 layer.setVisibility(checked); }else if(!treeNode.isParent){// 叶子图层节点 var node = treeNode; // 寻找这是第几个地图服务 var pnodes = [];// 存储当前节点的所有父节点,不包括服务根节点 while(node.getParentNode()){ node = node.getParentNode(); pnodes.push(node); } pnodes.pop();// 删除服务根节点,不计入考虑 layerSeq = node.id; layerId = this.layerIds[layerSeq]; layer = this.map.getLayer(layerId); visibleLayers = layer.visibleLayers; if(checked){ // 从可视化图层数组中添加当前节点 visibleLayers.push(treeNode.id - 1000 * (layerSeq +1)); }else{ // 从可视化图层数组中删除所有父节点 for(var j in pnodes){ var pnode = pnodes[j]; for(var i in visibleLayers){ if(visibleLayers[i] == (pnode.id - 1000 * (layerSeq +1))){ visibleLayers.splice(i,1); break; } } } // 从可视化图层数组中删除当前节点 for(var i in visibleLayers){ if(visibleLayers[i] == (treeNode.id - 1000 * (layerSeq +1))){ visibleLayers.splice(i,1); break; } } // 从可视化图层数组中清空 if(visibleLayers.length == 0){ visibleLayers.push(-1); } } // 设置可见子图层 layer.setVisibleLayers(visibleLayers); }else{// 非根非叶子节点的情况 var node = treeNode; // 寻找这是第几个地图服务 var pnodes = [];// 存储当前节点的所有父节点,不包括服务根节点 while(node.getParentNode()){ node = node.getParentNode(); pnodes.push(node); } pnodes.pop();// 删除服务根节点,不计入考虑 layerSeq = node.id; // 寻找所有子节点的自然序号 this.findAllChildren(treeNode, layerSeq); layerId = this.layerIds[layerSeq]; layer = this.map.getLayer(layerId); visibleLayers = layer.visibleLayers; if(checked){ visibleLayers = visibleLayers.concat(this.allChildrenIds); }else{ // 从可视化图层数组中删除所有父节点 for(var j in pnodes){ var pnode = pnodes[j]; for(var i in visibleLayers){ if(visibleLayers[i] == (pnode.id - 1000 * (layerSeq +1))){ visibleLayers.splice(i,1); break; } } } // 从可视化图层数组中删除当前节点 for(var i in visibleLayers){ if(visibleLayers[i] == (treeNode.id - 1000 * (layerSeq +1))){ visibleLayers.splice(i,1); break; } } // 从可视化图层数组中删除子节点 for(var j in this.allChildrenIds){ for(var i in visibleLayers){ if(this.allChildrenIds[j] == visibleLayers[i]){ visibleLayers.splice(i,1); break; } } } // 从可视化图层数组中清空 if(visibleLayers.length == 0){ visibleLayers.push(-1); } } // 设置可见子图层 layer.setVisibleLayers(visibleLayers); } }, // 更新图层树 updateTree:function(){ var currentScale = this.map.getScale();// 当前比例尺 var layerId = null;// 图层id var layerSeq = null;// 地图服务序号 var layer = null;// 地图服务图层 var isServiceScale = true;// 服务在当前比例尺下是否可见 var isLayerScale = true;// 图层在当前比例尺下是否可见 // 获取ztree对象 var treeObj = $.fn.zTree.getZTreeObj("layertree"); //获取所有服务节点 var nodes = treeObj.getNodes(); // 广度遍历获取所有节点(利用队列的非递归方式) var queue = [];// 队列 var arr = [];// 遍历结果 for(var i in nodes){ queue.push(nodes[i]); } var tnode = queue.shift(); arr.push(tnode); while(tnode){ var tnodes = tnode.children; for(var j in tnodes){ queue.push(tnodes[j]); } tnode = queue.shift(); if(tnode){ arr.push(tnode); } } // 倒序处理数组(从树的底层向上遍历) for(var i = arr.length - 1; i >= 0; i-- ){ var node = arr[i]; // 寻找这是第几个地图服务 var pnode = node.getParentNode(); while(node.getParentNode()){ node = node.getParentNode(); } layerSeq = node.id; layerId = this.layerIds[layerSeq]; layer = this.map.getLayer(layerId); if(layer instanceof ArcGISDynamicMapServiceLayer){//动态服务 var layerInfos = layer.layerInfos; if(!arr[i].isParent){ //叶子节点 var k = arr[i].id - 1000 * (layerSeq +1); isLayerScale = (!layerInfos[k].minScale || currentScale >= layerInfos[k].maxScale && currentScale <= layerInfos[k].minScale); treeObj.setChkDisabled(arr[i], !isLayerScale); }else{// 非叶子节点 var cnodes = arr[i].children; chkDisabled = true; for(var j in cnodes){ chkDisabled = chkDisabled && cnodes[j].chkDisabled; } treeObj.setChkDisabled(arr[i], chkDisabled); } }else{// 要素服务 isServiceScale = (!layer.minScale || currentScale >= layer.maxScale && currentScale <= layer.minScale); treeObj.setChkDisabled(arr[i], !isServiceScale); } } }, // 寻找所有子节点的自然序号 findAllChildren:function(treeNode, layerSeq){ // 递归寻找子节点 if(treeNode.children && treeNode.children.length > 0){ var nodes = treeNode.children; for(var i = 0, len = nodes.length; i < len; i++){ // 解密成自然序号 this.allChildrenIds.push(nodes[i].id - 1000 * (layerSeq +1)); // 加入集合 this.findAllChildren(nodes[i], layerSeq); } } } }); }); /*********使用方法************/ // JS var toc = new AIMapToc(map); map.on("layer-add-result", function(layers){ toc.createTree("toc"); }); // HTML class="tundra"> <div id="container"> <div id="mapDiv"> div> <div style="z-index:1040;width:230px;min-height:200px;position:absolute;top:10px;right:10px;background:#fff;border:1px solid #ccc;"> <div style="height:30px;line-height:29px;border-bottom:1px solid #ccc;text-align:center;font-size:13px;background:#f2f2f2;">图层控制div> <div id="toc" style="max-height:400px;overflow:auto;">div> div> div> body>

你可能感兴趣的:(WebGIS,图层控制,ArcGIS,JavaScript,TOC)