分类
ArcGIS

入门弹出窗口:实现点击地址弹出信息的效果

前言

弹出窗口popups是一个简单的方法,用来在使用ArcGIS API的应用程序中增加交互面板,响应用户的操作。
每个视图都有与之关联的弹出窗口。大多数情况下,弹出窗口的内容允许用户从图层图形中获取数据。

尽管弹出窗口通常被用在图层图层和特征图层,你仍然可以使用弹出窗口来响应查询,或者响应其他不涉及图形和特征的操作。例如,可以在用户点击视图之后显示经度纬度坐标。

这个示例中我们将会学习,在视图中通过设置视图的属性(如content,title,location),来调用默认的弹出窗口,并且在不从PopupTemplategraphic、或图层的features获取信息的情况下显示它。

这个示例使用定位器locator来从视图上单击的位置反向对点进行地理编码。
它返回的地址被展示在弹出窗口的内容中,与此同时,被点击地址的精度和维度被显示在弹出窗口的标题中。

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

1. 引入locator定位器、map地图对象、MapView地图视图模块,创建新的实例对象

使用世界地理服务the World Geocoding Service创建一个locator url
然后创建一个Map对象,基于这个Map创建一个视图实例。你的JavaScript代码应该像下面这样:

require(["esri/rest/locator", "esri/Map", "esri/views/MapView"], (locator, Map, MapView) => {
  // Create a locator url using the world geocoding service
  const locatorUrl = "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer";

  // Create the Map
  const map = new Map({
    basemap: "streets-navigation-vector"
  });

  // Create the MapView
  const view = new MapView({
    container: "viewDiv",
    map: map,
    center: [-71.6899, 43.7598],
    zoom: 12
  });
});

2. 监听视图的点击事件,在点击的位置显示弹出窗口

监听视图的点击事件,获得点击位置的经纬度。在被点击的位置显示弹出窗口,然后在弹出窗口的标题中显示被点击的坐标。
为了实现这个效果,我们将会通过open()方法,设置弹出窗口的地址标题属性。

view.popup.autoOpenEnabled = false;
view.on("click", (event) => {
  // Get the coordinates of the click on the view
  // around the decimals to 3 decimals
  const lat = Math.round(event.mapPoint.latitude * 1000) / 1000;
  const lon = Math.round(event.mapPoint.longitude * 1000) / 1000;

  view.popup.open({
    // Set the popup's title to the coordinates of the clicked location
    title: "Reverse geocode: [" + lon + ", " + lat + "]",
    location: event.mapPoint // Set the location of the popup to the clicked location
  });
});

3.定位点击位置的地址,在弹出窗口中显示匹配的地址

被点击的位置作为一个反向地理编码方法的输入,并且结果地址被显示在弹出窗口的内容中。
最后,如果在点击位置没有找到地址,弹出窗口的暖会显示消息,来告诉用户没有找到地址:

const params = {
  location: event.mapPoint
};

// Execute a reverse geocode using the clicked location
locator
  .locationToAddress(locatorUrl, params)
  .then((response) => {
    // If an address is successfully found, show it in the popup's content
    view.popup.content = response.address;
  })
  .catch(() => {
    // If the promise fails and no result is found, show a generic message
    view.popup.content = "No address was found for this location";
  });
分类
ArcGIS

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

前言

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

一张地图可能包含不同种类的图层,如果想要简单的浏览一下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文档和里面的示例。本文最终的示例代码可以在沙盒中查看。

分类
ArcGIS

入门MapView:创建2D地图

前言

在这个教程中,我们将会学习如何创建2D地图视图(MapView)。

注意:这篇文章使用AMD模块,你也可以下载一个兼容ES模块的示例,该示例使用Vite.js来创建本地构建
如果想了解关于不同API模块的区别,可以看这篇文章。

一、引用ArcGIS Map SDK for JavaScript

名词解释:
JS——JavaScript
SDK——Software Development Kit,指的是某种计算机语言的一系列开发工具

ArcGIS Map SDK for JavaScript就是ArcGIS为JS编写的一个地图API。

第一步就是初始化一个HTML文件,类似下面代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
    <title>Intro to MapView - Create a 2D map</title>
  </head>
</html>

我们需要在<Head>标签中,通过<script><link>标签引入ArcGIS Map JS SDK:

<link rel="stylesheet" href="https://js.arcgis.com/4.26/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.26/"></script>

<script>标签通过CDN加载了ArcGIS Map JS SDK。如果出现了版本更新,可以通过修改代码中引用的版本号,来获取最新版本。

<link>标签实现了对于main.css的引用,这个css包含了Esri控件和组件样式特性。(译者注,就是官方必备的CSS样式,原文说的比较啰嗦)

2. 加载模块

使用另一个<script>标签去加载特定的API模块。
esri/Map用来加载特定代码以便创建一个Map对象
esri/views/MapView用来创建一个2D地图
使用方法如下:

<script>
  require([ "esri/Map", "esri/views/MapView" ], (Map, MapView) => {
    // 这里是回调函数,可以操作创建好的对象
  });
</script>

示例中的JS代码放在了HTML脚本中,但对于大型项目来说这种做法并适合,应该放在单独的JS文件中

全局的require()方法用来加载API的AMD模块。对于不同模块的区别,可以访问这个链接来查看教程。

3. 创建Map对象

一张地图使用的是Map对象,这个对象来自esri/Map模块的Map类。在创建Map对象的过程中,我们可以在构造函数中定制它的属性,例如可以修改basemap底图。

require(["esri/Map", "esri/views/MapView"], (Map, MapView) => {
  const map = new Map({
    basemap: "topo-vector"
  });
});

其他的参数包括: satellite, hybrid, gray-vector, dark-gray-vector, oceans, streets-vector, osm, national-geographic, streets-night-vector。在沙盒中更改basemap属性,就可以切换底图。

4. 创建2D视图(View)

作为HTML文件中的容器,视图引用结点(View)允许用户在HTML中嵌入一张地图。通过对象的构造函数,我们可以创建新的MapView并且设置它的属性:

require(["esri/Map", "esri/views/MapView"], (Map, MapView) => {
  const map = new Map({
    basemap: "topo-vector"
  });

  const view = new MapView({
    container: "viewDiv", // Reference to the DOM node that will contain the view
    map: map // References the map object created in step 3
  });
});

在这个小节中,我们为DOM结点设置一个容器属性(container),以便让它能够承载地图,因此我们给div标签添加一个id属性。地图视图的map属性实际上引用的就是上一步中我们创建的map对象。
可以点击MapView documentation来查看此视图的其他属性,例如center(中心)zoom(缩放),这些属性用来定义视图的初始范围。

视图共有两种:地图视图MapView用来显示2D地图,场景视图SceneView用来显示3D视图,点击这篇文章可以学习使用3D视图。

5. 定义页面内容

到目前为止,我们已经写好了负责创建map对象和view视图的JavaScript代码。
(译者注,如果搞不清楚这几个对象的关系,可以理解成:最下层是map对象,map对象的上层是view视图,view视图的上层是layer图层,图层有很多层。
所以无论使用2D还是3D,都要先创建map,基于map创建view,最后在view上绘制layer即可)

下一步我们就来添加HTML以便展示我们的地图。HTML的写法非常简单:先写一个<body>标签,然后在<body>标签中想要显示这个视图的位置放一个<div>标签

<body>
  <div id="viewDiv"></div>
</body>

其中,<div>标签的id,必须与前面MapView中container属性的字符串相匹配。

6.为页面设置样式

样式的代码写在<style>标签中,<style>标签需要被<head>标签包裹,当然,你也可以根据自己的习惯,把样式写在单独的CSS文件中,与普通的前端开发别无二致。

<style>
  html,
  body,
  #viewDiv {
    padding: 0;
    margin: 0;
    height: 100%;
    width: 100%;
  }
</style>

到目前为止,我们使用ArcGIS Maps SDK for JavaScript 4.26!完成了一个2D地图应用,最终的代码效果类似下面:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
    <title>Intro to MapView - Create a 2D map</title>
    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
    </style>
    <link rel="stylesheet" href="https://js.arcgis.com/4.26/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.26/"></script>
    <script>
      require(["esri/Map", "esri/views/MapView"], (Map, MapView) => {
        const map = new Map({
          basemap: "topo-vector"
        });
        const view = new MapView({
          container: "viewDiv", // Reference to the view div created in step 5
          map: map, // Reference to the map object created before the view
          zoom: 4, // Sets zoom level based on level of detail (LOD)
          center: [15, 65] // Sets center point of view using longitude,latitude
        });
      });
    </script>
  </head>
  <body>
    <div id="viewDiv"></div>
  </body>
</html>