Arcgis for Javascript之featureLayer图和属性的互操作

本文介绍如何在GIS应用中实现FeatureLayer属性表的分页加载与显示,以及地图与属性表之间的互动,包括鼠标操作时的名称显示与高亮、点击显示详细信息框的功能。

说明: 主要实现加载FeatureLayer与显示属性表,并实现属性表与地图的联动,首先,看看实现后的效果:

显示效果

如上图所示,本文章主要实现了以下几个功能:1、FeatureLayer属性表的分页加载与显示;2、属性表和地图的互操作,包括鼠标经过时在地图上显示名称并高亮显示、点击列表显示对象的信息框,如下图:

显示信息框

下面,说说具体的实现思路与代码。

1、FeatureLayer属性表的获取

获取FeatureLayer的属性表,首先得创建FeatureLayer对象,如下:

ftch = new FeatureLayer("http://localhost:6080/arcgis/rest/services/shpchina/MapServer/0",{
        outFields: ["*"]
      })
      var symbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_SQUARE,
        10,
        new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
          new Color([255,0,0]),
          1
        ),
        new Color([0,255,0,0.25])
      );
      //简单渲染
      var  sr = new SimpleRenderer(symbol);
      ftch.setRenderer(sr);
      map.addLayer(ftch,1);

有了FeatureLayer对象,可以通过ftch.graphics获取所有的记录,获取到graphics就能获取到单个的graphic,就能获取每一个graphic的attributes,如下:

var graphics=ftch.graphics;
  console.log(graphics);
  var item = "";
  for(var i=0;i<graphics.length;i++){
      var attr = graphics[i].attributes;
      var id=attr.FID, name=attr.name;
      item+= "{\"id\":"+id+",\"text\":'"+name+"'},";
  }

此时,就能组装分页显示属性的json对象了,如下:

var graphics=ftch.graphics;
           console.log(graphics);
           var item = "";
           for(var i=0;i<graphics.length;i++){
             var attr = graphics[i].attributes;
             var id=attr.FID, name=attr.name;
             item+= "{\"id\":"+id+",\"text\":'"+name+"'},";
           }
           item = "["+item.substring(0,item.length-1)+"]";
           attr="{'total':"+graphics.length+",'items':"+item+"}";
           PAGE_DATA = eval('(' + attr + ')');

将属性表分页显示,如博文http://blog.youkuaiyun.com/gisshixisheng/article/details/40048451 所示。

3、每一个对象事件的绑定与实现

每一个显示对象的都是一个div,给div分别添加onclick,onmouseover和onmouseout事件,三个事件传递的参数都一样,是在graphics里面的index值,接下来就是实现三个事件,详细代码如下:

showInfo = function(index){
    var pt=ftch.graphics[index].geometry;
    var attr=ftch.graphics[index].attributes;
    map.infoWindow.setTitle(attr.name);
    map.infoWindow.setContent(attr.name);
    map.infoWindow.show(pt);
      };
      showObj = function(index){
    var symbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE,
      12,
      new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
        new Color([255,0,0]),
        1
      ),
      new Color([255,0,0,1])
    );
    ftch.graphics[index].symbol=symbol;
    ftch.redraw();
    var pt=ftch.graphics[index].geometry;
    var font  = new esri.symbol.Font();
    font.setSize("10pt");
    font.setWeight(esri.symbol.Font.WEIGHT_BOLD);
    var text = new esri.symbol.TextSymbol(ftch.graphics[index].attributes.name);
    text.setAlign(esri.symbol.TextSymbol.ALIGN_START);
    text.setFont(font);
    text.setOffset(2,-15);
    text.setColor(new dojo.Color([255,0,0,1]));
    var labelGraphic = new esri.Graphic(pt,text);
    labelLayer.add(labelGraphic);
      };
      restoreObj = function(index){
    labelLayer.clear();
    var symbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_SQUARE,
        10,
        new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
      new Color([255,0,0]),
      1
        ),
        new Color([0,255,0,0.25])
      );
      ftch.graphics[index].symbol=symbol;
      ftch.redraw();
      };
  });

showInfo对应的是单击事件,showObject对应的是鼠标经过事件,restoreObj对应的是鼠标移除事件,这样基本并能就实现了。详细代码如下:

map.html

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
  <title>Simple Map</title>
  <link rel="stylesheet" href="http://localhost/arcgis_js_api/library/3.9/3.9/js/esri/css/esri.css">
  <link rel="stylesheet" href="page.css">
  <style>
    html, body, #map {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    body {
      background-color: #FFF;
      overflow: hidden;
      font-family: "Trebuchet MS";
    }
    #map_ctrl{
      z-index: 99;
      position: absolute;
      top: 20pt;
      right: 10pt;
      background: #fff;
    }
    .button{
      padding: 3px;
      background: #eee;
      text-align: center;
      font-size: 12px;
      font-family: "微软雅黑";
    }
    .button:hover,.attr_ctrl:hover{
      background: #ccc;
      cursor: pointer;
    }
    #attr_ctrl{
      z-index: 99;
      width: 155px;
      position:absolute;
      right: 0px;
      bottom:5px;
      text-align: right;
    }
    .attr_ctrl{
      padding: 5px;
      font-size: 12px;
      font-family: "微软雅黑";
      width: 100px;
      background: #eee;
      border: 1px solid #000;
      border-bottom: none;
    }
    #map_attr{
      z-index: 99;
      font-size: 12px;
      font-family: "微软雅黑";
      width: 176px;
      height: 150px;
      background: #eee;
      position: absolute;
      bottom: 0px;
      right:0px;
      border: 1px solid #000;
      border-bottom: none;
    }
  </style>
  <script src="http://localhost/arcgis_js_api/library/3.9/3.9/init.js"></script>
  <script src="jquery-1.8.3.js"></script>
  <script src="jquery.page.js"></script>
  <script>
    var map, mapCenter, ftch;
    var PAGE_DATA, currpage= 1, pagesize=5;
    var showInfo, showObj, restoreObj;
    require([
      "esri/map",
      "esri/layers/ArcGISTiledMapServiceLayer",
      "esri/layers/FeatureLayer",
      "esri/layers/GraphicsLayer",
      "esri/geometry/Point",
      "esri/symbols/SimpleMarkerSymbol",
      "esri/symbols/SimpleLineSymbol",
      "esri/renderers/SimpleRenderer",
      "dojo/_base/Color",
      "dojo/on",
      "dojo/dom",
      "dojo/domReady!"],
    function(Map,
       Tiled,
       FeatureLayer,
       GraphicsLayer,
       Point,
       SimpleMarkerSymbol,
       SimpleLineSymbol,
       SimpleRenderer,
       Color,
       on,
       dom)
    {
      map = new Map("map", {logo:false,slider: true});
      var tiled = new Tiled("http://localhost:6080/arcgis/rest/services/chinamap/MapServer");
      map.addLayer(tiled,0);
      ftch = new FeatureLayer("http://localhost:6080/arcgis/rest/services/shpchina/MapServer/0",{
        outFields: ["*"]
      })
      var symbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_SQUARE,
        10,
        new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
          new Color([255,0,0]),
          1
        ),
        new Color([0,255,0,0.25])
      );
      //简单渲染
      var  sr = new SimpleRenderer(symbol);
      ftch.setRenderer(sr);
      map.addLayer(ftch,1);
      var labelLayer = new GraphicsLayer();
      map.addLayer(labelLayer,2);
      mapCenter = new Point(103.847, 36.0473, map.spatialReference);
      map.centerAndZoom(mapCenter,4);
      var navToolbar = new esri.toolbars.Navigation(map);
      on(dom.byId("full_extent"), "click", function(event){//全图
        map.centerAndZoom(mapCenter,4);
      });
      on(dom.byId("zoom_in"), "click", function(event){//拉框放大
        map.setMapCursor("url(cursor/zoom-in.cur),auto");
        navToolbar.activate(esri.toolbars.Navigation.ZOOM_IN);
      });
      on(dom.byId("zoom_out"), "click", function(event){//拉框缩小
        map.setMapCursor("url(cursor/zoom-out.cur),auto");
        navToolbar.activate(esri.toolbars.Navigation.ZOOM_OUT);
      });
      navToolbar.on("extent-history-change", function(){
        map.setMapCursor("default");
        navToolbar.deactivate();
      });
      on(dom.byId("attr_ctrl"), "click", function(event){//显示或隐藏属性表
         if($(".attr_ctrl").html()=="显示属性"){
           var graphics=ftch.graphics;
           console.log(graphics);
           var item = "";
           for(var i=0;i<graphics.length;i++){
             var attr = graphics[i].attributes;
             var id=attr.FID, name=attr.name;
             item+= "{\"id\":"+id+",\"text\":'"+name+"'},";
           }
           item = "["+item.substring(0,item.length-1)+"]";
           attr="{'total':"+graphics.length+",'items':"+item+"}";
           PAGE_DATA = eval('(' + attr + ')');
           loadPages(1);
           $("#map_attr").show();
           $(".attr_ctrl").html("隐藏属性");
           $("#attr_ctrl").css("bottom","155px");
         }
        else{
           $("#map_attr").hide();
           $(".attr_ctrl").html("显示属性");
           $("#attr_ctrl").css("bottom","5px");
         }
      });
      showInfo = function(index){
        var pt=ftch.graphics[index].geometry;
        var attr=ftch.graphics[index].attributes;
        map.infoWindow.setTitle(attr.name);
        map.infoWindow.setContent(attr.name);
        map.infoWindow.show(pt);
      };
      showObj = function(index){
        var symbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE,
            12,
            new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                new Color([255,0,0]),
                1
            ),
            new Color([255,0,0,1])
        );
        ftch.graphics[index].symbol=symbol;
        ftch.redraw();
        var pt=ftch.graphics[index].geometry;
        var font  = new esri.symbol.Font();
        font.setSize("10pt");
        font.setWeight(esri.symbol.Font.WEIGHT_BOLD);
        var text = new esri.symbol.TextSymbol(ftch.graphics[index].attributes.name);
        text.setAlign(esri.symbol.TextSymbol.ALIGN_START);
        text.setFont(font);
        text.setOffset(2,-15);
        text.setColor(new dojo.Color([255,0,0,1]));
        var labelGraphic = new esri.Graphic(pt,text);
        labelLayer.add(labelGraphic);
      };
      restoreObj = function(index){
        labelLayer.clear();
        var symbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_SQUARE,
          10,
          new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
            new Color([255,0,0]),
            1
          ),
          new Color([0,255,0,0.25])
          );
          ftch.graphics[index].symbol=symbol;
          ftch.redraw();
      };
    });
    function loadPages(page){
      $('#pages').html("");
      $('#pages').itemPage({
        data:PAGE_DATA,
        currpage:page,
        pagesize:pagesize
      });
    };
    function showPage(page){
      console.log(page);
      switch(page){
        case "prev":{//前一页
          if(currpage>1){
            currpage=currpage-1;
          }
          else{
            alert("没有上一页了!");
          }
          break;
        }
        case "next":{//后一页
          if(currpage!=getLastPage()){
            currpage=currpage+1;
          }
          else{
            alert("没有下一页了!");
          }
          break;
        }
        case "last":{//最后一页
          currpage=getLastPage();
          break;
        }
        default:{
          currpage=1;//第一页
          break;
        }
      }
      loadPages(currpage);
    };
    function getLastPage(){
      var total=PAGE_DATA.total;
      if(total%pagesize==0){
        return total/pagesize;
      }
      else{
        return parseInt(total/pagesize)+1;
      }
    }
  </script>
</head>

<body>
<div id="map">
  <div id="map_ctrl">
    <a id="full_extent" class="button">全  图</a>
    <a id="zoom_in" class="button">拉框放大</a>
    <a id="zoom_out" class="button">拉框缩小</a>
  </div>
  <div  id="attr_ctrl">
    <a class="attr_ctrl">显示属性</a>
  </div>
  <div id="map_attr" style="display: none">
    <div id="pages">
    </div>
  </div>
</div>
</body>
</html>

page.css

.page_item{
  background:#C9DCD7;
  width:170px;
  text-align:left;
  padding-left:10px;
  padding-top:3px;
  padding-bottom:3px;
  border-bottom:1px solid #3CF;
}
.page_item:hover{
  background:#A9C9FA;
  cursor:pointer;
}
#page_ctrl{
  padding-top:5px;
}
.page_ctrl{
  width:40px;
  text-align:center;
  background:#A9C9FA;
  float:left;
  margin:2px;
  padding-top:5px;
  padding-bottom:5px;
}
.page_ctrl:hover{
  background:#C9DCD7;
  cursor:pointer;
}

jquery.page.js

/**
 * Created by Administrator on 14-10-18.
 */
(function($){
  $.fn.itemPage = function(options){
    var defaults = {};
    var options = $.extend(defaults, options);

    var data=options.data,//数据
      currpage=options.currpage,//当前页
      pagesize=options.pagesize;//每页显示的数据条目器

    var total=data.total;

    var items=$("<div id='items'></div>"),
      pagectrl=$("<div id='page_ctrl'></div>");

    var first=$("<div id=\"first\" class=\"page_ctrl\" onClick=\"showPage('first')\">首 页</div>"),
      prev=$("<div id=\"prev\" class=\"page_ctrl\" onClick=\"showPage('prev')\">前一页</div>"),
      next=$("<div id=\"next\" class=\"page_ctrl\" onClick=\"showPage('next')\">后一页</div>"),
      last=$("<div id=\"last\" class=\"page_ctrl\" onClick=\"showPage('last')\">末 页</div>");

    var start=getStartindex(),
      end=getEndindex();

    for(var i=start;i<end;i++){
      var itemi=$("<div class='page_item' onclick='showInfo("+i+")' onmouseout='restoreObj("+i+")' onmouseover='showObj("+i+")'>"+data.items[i].text+"</div>");
      items.append(itemi);
    }

    pagectrl.append(first),
      pagectrl.append(prev),
      pagectrl.append(next)
    pagectrl.append(last);

    var container = $(this);
    container.append(items),
      container.append(pagectrl);

    function getStartindex(){
      return (currpage-1)*pagesize;
    }
    function getEndindex(){
      var endIndex=0;
      if(data.total%pagesize!=0 && currpage==getLastPage()){
        endIndex = data.total;
      }
      else {
        endIndex = currpage*pagesize;
      }
      return endIndex;
    }
  }
})(jQuery);


<think>我们正在处理一个关于ArcGIS API for JavaScript的问题:用户想要对FeatureLayer执行缓冲区查询。根据引用资料,我们知道FeatureLayer是用于操作显示特征数据的层。用户需要一个缓冲区查询的示例。 缓冲区查询通常涉及以下步骤: 1. 创建一个FeatureLayer实例。 2. 定义一个几何(点、线或面)作为缓冲区的中心。 3. 在该几何周围创建一个缓冲区(多边形)。 4. 使用该缓冲区作为空间过滤器来查询FeatureLayer,获取落在缓冲区内的特征。 在ArcGIS API for JavaScript中,我们可以使用GeometryService来创建缓冲区,然后使用Query对象FeatureLayer的queryFeatures方法执行查询。 注意:GeometryService是一个独立的服务,需要ArcGIS Server的GeometryService支持。 我们将按照以下步骤编写代码: 1. 加载所需的模块(FeatureLayer, GeometryService, BufferParameters, Query等)。 2. 创建FeatureLayer实例。 3. 创建GeometryService实例(指向可用的GeometryService)。 4. 定义缓冲区参数(几何、距离、单位等)。 5. 使用GeometryService执行缓冲区操作,得到缓冲区多边形。 6. 构建一个Query对象,设置其geometry为缓冲区多边形,并设置空间关系(spatialRelationship)为包含或相交。 7. 使用FeatureLayer的queryFeatures方法执行查询,处理返回的结果。 下面是一个示例代码:</think>### ArcGIS API for JavaScript 实现 FeatureLayer 缓冲区查询 在 ArcGIS API for JavaScript 中,对 `FeatureLayer` 执行缓冲区查询需要以下步骤: #### 1. **创建 FeatureLayer** 首先初始化特征层,确保设置了正确的 URL 或 GeoJSON 数据源: ```javascript require(["esri/layers/FeatureLayer"], function(FeatureLayer) { const featureLayer = new FeatureLayer({ url: "https://services.arcgis.com/.../FeatureServer/0", // 替换为实际服务URL outFields: ["*"] // 返回所有字段 }); map.add(featureLayer); // 将层添加到地 }); ``` #### 2. **执行缓冲区查询** 使用 `geometryEngine` 生成缓冲区,然后构建空间查询: ```javascript require(["esri/geometry/geometryEngine", "esri/tasks/support/Query"], function(geometryEngine, Query) { // 步骤1:定义中心点缓冲区半径 const centerPoint = { // 示例点坐标 type: "point", longitude: -118.15, latitude: 33.80 }; const bufferDistance = 10; // 缓冲距离(单位:千米) // 步骤2:生成缓冲区多边形 const bufferPolygon = geometryEngine.geodesicBuffer( centerPoint, bufferDistance, "kilometers" ); // 步骤3:构建查询对象 const query = new Query({ geometry: bufferPolygon, // 使用缓冲区作为查询范围 spatialRelationship: "intersects", // 空间关系:相交 returnGeometry: true, outFields: ["*"] }); // 步骤4:执行查询 featureLayer.queryFeatures(query) .then(function(results){ console.log("查询结果:", results.features); // 处理结果:高亮显示/弹窗等 }) .catch(function(error){ console.error("查询失败:", error); }); }); ``` #### 关键参数说明: - **空间关系 (`spatialRelationship`)**: - `intersects`:返回与缓冲区相交的要素(最常用) - `contains`:完全包含在缓冲区内的要素 - `within`:要素完全包含缓冲区(较少用) - **缓冲区类型**: - `geometryEngine.geodesicBuffer()`:考虑地球曲率的精确缓冲区(推荐) - `geometryEngine.buffer()`:平面坐标系缓冲区 #### 3. **结果可视化** 在查询回调中可添加结果渲染: ```javascript results.features.forEach(function(feature){ feature.symbol = { // 自定义符号 type: "simple-fill", color: [255, 0, 0, 0.5], outline: { width: 2, color: "red" } }; graphicsLayer.add(feature); // 添加到层 }); ``` #### 注意事项: 1. **服务支持**:确保 FeatureLayer 的 REST 服务启用了 `query` 操作 2. **坐标系匹配**:缓冲区几何与层坐标系需一致 3. **性能优化**:对于大数据量层,建议设置 `where` 条件缩小查询范围 [^1]: FeatureLayer 支持空间查询属性过滤,可通过定义表达式优化性能 [^2]: 使用 GeometryService 可处理复杂空间运算,但需额外配置服务 [^3]: 查询结果可通过 Graphic 对象渲染,实现交互式可视化 --- ### 相关问题 1. **如何优化 FeatureLayer 缓冲区查询的性能?** - 建议方案:使用 `where` 子句过滤数据量,设置合理的 `maxRecordCount` 2. **FeatureLayer 与 GraphicsLayer 在渲染查询结果时的区别?** - 关键差异:FeatureLayer 连接动态服务,GraphicsLayer 只处理客户端形 3. **如何处理跨日期变更线的缓冲区查询?** - 解决方案:使用 `geometryEngine.geodesicBuffer()` 自动处理坐标系转换 4. **如何将缓冲区查询结果导出为 GeoJSON?** - 实现方法:通过 `esriRequest` 模块转换查询结果为标准格式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值