分类
ArcGIS

入门图层:在视图中绘制图形

Intro to layers

前言

图层是地图中最基础的组件,它是以图形或图像的形式,收集到的真实世界中的空间数据。
图层可以存储矢量数据的离散特征,或存储光栅数据的连续单元/像素。
(译者注:这句话是在说,图层既可以是位图的形式,存放一个一个的像素;也可以是矢量图的形式,存放的一系列生成函数,在需要的时候实时渲染成图形)

一张地图可能包含不同种类的图层,如果想要简单的浏览一下API中可用的图层特点,可以查看这张表格

所有具体的图层对象,都从Layer中继承了属性、方法、事件。本文中将会讨论一些常用的属性。
如果要学习不同图层类型的属性特点,可以看图层类型的示例,比如瓦片图层

在正式操作开始之前,请确保了解视图Map
如有必要,可以先学习下面两篇文章:

1. 创建Map对象、地图视图,以及一个HTML选择框

先来创建一个基本的Map对象,并且基于Map对象创建一个地图视图MapView
JavaScript代码如下:

require(["esri/Map", "esri/views/MapView"], (Map, MapView) => {
  // Create the Map
  const map = new Map({
    basemap: "oceans"
  });

  // Create the MapView
  const view = new MapView({
    container: "viewDiv",
    map: map
  });
});

然后在HTML中添加一个选择框元素,这样做的目的我们后面会提到。

<body>
  <div id="viewDiv"></div>
  <span id="layerToggle" class="esri-widget"> <input type="checkbox" id="streetsLayer" checked /> Transportation </span>
</body>

2. 用瓦片图层TileLayer创建两个图层

接下来创建两个瓦片图层(TileLayer)的实例,注意瓦片图层的代码需要写在创建map和view之前
为了实现这个需要,我们必须引入esri/layers/TileLayer模块并且定制这个图层的url属性。
url属性必须指向一个缓存地图服务,这个服务可以托管在ArcGIS Server上或Portal for ArcGIS上。

所有用于连接ArcGIS服务的图层,都具有url字段,它必须被设置成在视图中显示。
在这个示例中,我们使用Esri World Transportation service服务和一个包含纽约市房屋数据的服务,来创建街道和高速公路图层:

require([
  "esri/Map",
  "esri/views/MapView",
  "esri/layers/TileLayer" // Require the TileLayer module
], (Map, MapView, TileLayer) => {
  const transportationLayer = new TileLayer({
    url: "https://server.arcgisonline.com/arcgis/rest/services/Reference/World_Transportation/MapServer"
  });

  const housingLayer = new TileLayer({
    url: "https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/New_York_Housing_Density/MapServer"
  });

  /*****************************************************************
   * The code to create a map and view instance in the previous step
   * should be placed here.
   *****************************************************************/
});

3. 为图层设置额外的属性

我们可以设置图层额外的属性,例如id, minScale, maxScale, opacity, and visible。这些属性可以在构造函数中设置,也可以直接在实例中设置。
我们增加id属性在每个图层中,并且设置交通图层的不透明度opacity

const transportationLayer = new TileLayer({
  url: "https://server.arcgisonline.com/arcgis/rest/services/Reference/World_Transportation/MapServer",
  id: "streets",
  opacity: 0.7
});

const housingLayer = new TileLayer({
  url: "https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/New_York_Housing_Density/MapServer",
  id: "ny-housing"
});

id属性是一个图层的唯一标识,使得我们容易的在其他位置来引用这个图层。如果开发者没有直接设置id,当图层创建时也会自动生成一个id
minScalemaxScale属性在图层缩放时控制可见性(译者注,说的就是缩放级别)。使用这些属性可以在缩放时改善程序的性能和简化地图的绘制。
此外,visible属性默认是true

4. 为地图增加图层

我们有多种不同的方法来添加图层。想要学习这些方法可以访问Map.layers
在本文的示例中,我们分别尝试一下不同的添加方法。

构造函数法

先来看看使用构造函数的方法,在map创建时添加一个房屋图层(housing layer):

// Both layers were created prior to this code snippet
const map = new Map({
  basemap: "oceans",
  layers: [housingLayer] // layers can be added as an array to the map's constructor
});

add()方法

也可以使用map.layers.add()方法来添加一个交通图层:

map.layers.add(transportationLayer);

到目前为止,所有添加的图层都可以在视图中显示了。

5. 设置图层的可见性

使用addEventListener方法,可以监听我们前面创建的这个checkbox选择框的变化事件(event)。当这个选择框被选中或者取消选中时,我们就可以改变交通图层的可见性(通俗的说就是显示、不显示、缩放、透明度等等一系列属性),例如visible
任何图层的任何属性,都可以直接设置在图层实例中。如下面代码:

require(["esri/Map", "esri/views/MapView", "esri/layers/TileLayer"], (
  Map,
  MapView,
  TileLayer
) => {
  /*****************************************************************
   * All code previously written in the steps above should be placed
   * before the following code
   *******************************************************************/

  // Create a variable referencing the checkbox node
  const streetsLayerToggle = document.getElementById("streetsLayer");

  // Listen to the change event for the checkbox
  streetsLayerToggle.addEventListener("change", () => {
    // When the checkbox is checked (true), set the layer's visibility to true
    transportationLayer.visible = streetsLayerToggle.checked;
  });
});

尽管在上面的示例中,图层是不可见的,但它仍然在map中存在。因此,在用户看不见图层的情况下,我们作为开发者仍然可以访问到这些图层的属性,并且使用它们来数据分析。

6. 理解图层视图(LayerViews)

图层对象管理着来自服务的地理数据和表格数据,但它不处理在视图中的渲染层,渲染的工作是交给图层视图(LayerView)进行的。
图层的LayerView是在图层渲染之前创建的。使用FeatureLayers时,对应的FeatureLayerView可以为开发人员提供访问视图中渲染的与该层的功能相关的图形的权限。

在这个步骤中,我们将会学习视图的layerview-create事件,并且输出住房和交通的LayerViews,以便控制他们的属性。
需要注意的是,我们将会使用第三节中创建的id属性,来准确的找到一个图层。除了地图的操作图层外,这个事件还可以通过基础地图图层和高程图层来触发:

require(["esri/Map", "esri/views/MapView", "esri/layers/TileLayer"], (
  Map,
  MapView,
  TileLayer
) => {
  /*****************************************************************
   * All code previously written in the steps above should be placed
   * before the following code
   *******************************************************************/

  // This event fires each time a layer's LayerView is created for the
  // specified view instance
  view.on("layerview-create", (event) => {
    if (event.layer.id === "ny-housing") {
      // Explore the properties of the housing layer's layer view here
      console.log("LayerView for New York housing density created!", event.layerView);
    }
    if (event.layer.id === "streets") {
      // Explore the properties of the transportation layer's layer view here
      console.log("LayerView for streets created!", event.layerView);
    }
  });
});

7. 使用Layer.when()方法

在图层加载时(loaded)、或者当图层的所有属性对于开发者都可用的时候,这个图层会解析为一个promise
在这个示例中,我们想要让房屋图层有完整的扩展(fullExtent),因为我们事先不知道,视图初始化时使用什么样的扩展(中心点、缩放)比较合适。

在图层被加载之前,我们无法获取到这个图层。因此我们必须在它被解析之后去修改它。
这种修改过程使用的是when()方法:

// When the layer's promise resolves, animate the view to the layer's fullExtent
housingLayer.when(() => {
  view.goTo(housingLayer.fullExtent);
});

8.总结

本文中还有许多图层的属性尚未讨论。如果想了解图层更多的信息,可以看API文档和里面的示例。本文最终的示例代码可以在沙盒中查看。