ArcGIS开发基础教程(五):实战前准备——API使用的正确方式

ArcGIS API for JavaScript 使用方法说明

构造函数

ArcGIS API for JavaScript中的所有类都有一个构造函数,所有属性都可以通过向构造函数传递参数来设置。

const map = new Map({
  basemap: "topo-vector"
});

const view = new MapView({
  map: map,
  container: "map-div",
  center: [ -122, 38 ],
  scale: 5
});

另外,对象的属性可以直接使用setters来指定。

const map = new Map();
const view = new MapView();

map.basemap = "topo-vector";           // Set a property

const viewProps = {                    // Object with property data
  container: "map-div",
  map: map,
  scale: 5000,
  center: [ -122, 38 ]
};

view.set(viewProps);                   // Use a setter

属性

Getters

get方法返回一个属性的值,这个方法是一个快捷方法,因为如果不使用get(),要返回嵌套属性的值,例如,要返回一个Map对象的属性basemap的标题,需要一个if语句来检查basemap是否未定义或为空。

const basemapTitle = null;
if (map.basemap) {                     // Make sure `map.basemap` exists
  basemapTitle = map.basemap.title;
}

get 方法不需要 if 语句,如果 map.basemap 存在,则返回 map.basemap.title 的值,否则返回 null

const basemapTitle = map.get("basemap.title");

注意:

也可以采用可选链(?.)操作规避这类问题,但是需要考虑浏览器兼容性。

const basemapTitle = map?.basemap.title;

Setters

可以直接设置属性的值。

view.center = [ -100, 40 ];
view.zoom = 6;
map.basemap = "oceans";

当需要更改多个属性值时, set() 可以传递一个带有属性名和新值的 JavaScript 对象。

const newViewProperties = {
  center: [ -100, 40 ],
  zoom: 6
};

view.set(newViewProperties);

监听属性变化

使用 watch() 来监听属性的变化,它带有两个参数:作为字符串的属性名称,以及当属性值更改时调用的回调函数。watch()返回一个WatchHandle实例。
代码示例监听一个Map对象的basemap.title属性,每当底图标题发生改变时,就调用titleChangeCallback函数。

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

function titleChangeCallback (newValue, oldValue, property, object) {
  console.log("New value: ", newValue,
              "<br>Old value: ", oldValue,
              "<br>Watched property: ", property,
              "<br>Watched object: ", object);
};

const handle = map.watch('basemap.title', titleChangeCallback);

可以在 WatchHandle 对象上调用 remove 方法来停止监听。

handle.remove();

注意:

并非所有的属性都可以被监听,例如集合。注册一个事件处理程序,以便在一个集合发生changes时可以被监听。

因为FeatureLayer.sourceGraphicsLayer.graphics属性都是集合,使用on()而不是watch()来监听这些属性的变化。

Autocasting

Autocasting将JavaScript对象作为ArcGIS API for JavaScript 类类型,而不需要开发人员显式导入这些类。

注意:

目前,由于TypeScript的限制,Autocasting在非TypeScript应用程序中效果最好。

代码示例中,需要五个API类来为一个FeatureLayer创建一个SimpleRenderer

require([
  "esri/Color",
  "esri/symbols/SimpleLineSymbol",
  "esri/symbols/SimpleMarkerSymbol",
  "esri/renderers/SimpleRenderer",
  "esri/layers/FeatureLayer",
], (
  Color, SimpleLineSymbol, SimpleMarkerSymbol, SimpleRenderer, FeatureLayer
) => {
  const layer = new FeatureLayer({
    url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/WorldCities/FeatureServer/0",
    renderer: new SimpleRenderer({
      symbol: new SimpleMarkerSymbol({
        style: "diamond",
        color: new Color([255, 128, 45]),
        outline: new SimpleLineSymbol({
          style: "dash-dot",
          color: new Color([0, 0, 0])
        })
      })
    })
  });
});

通过Autocasting,不必导入渲染器和符号类;唯一需要导入的模块是esri/layers/FeatureLayer

require([ "esri/layers/FeatureLayer" ], (FeatureLayer) => {
  const layer = new FeatureLayer({
    url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/WorldCities/FeatureServer/0",
    renderer: {                        // autocasts as new SimpleRenderer()
      symbol: {                        // autocasts as new SimpleMarkerSymbol()
        type: "simple-marker",
        style: "diamond",
        color: [ 255, 128, 45 ],       // autocasts as new Color()
        outline: {                     // autocasts as new SimpleLineSymbol()
          style: "dash-dot",
          color: [ 0, 0, 0 ]           // autocasts as new Color()
        }
      }
    }
  });
});

想知道一个类是否可以Autocasting,查看每个类的文档。如果一个属性可以被Autocasting,就会出现以下图片:

image-20210903161646550

异步数据

Promise

Promise通常与then()一起使用,它定义了回调函数,如果resolved,则调用该函数,如果rejected,则调用错误函数。第一个参数始终是成功回调,第二个可选参数是错误回调。

someAsyncFunction().then(callback, errorCallback);

catch()方法可以用来指定一个PromisePromise函数链的错误回调函数。

someAsyncFunction()
  .then((resolvedVal) => {
    console.log(resolvedVal);
  }).catch((error) => {
    console.error(error);
  });

示例中,GeometryService被用来将几个点的几何图形投射到一个新的空间参考。在GeometryService.project的文档中,project()返回一个Promise,该Promise解析为一个投影的几何体数组。

require([
  "esri/tasks/GeometryService",
  "esri/tasks/support/ProjectParameters",
  ], (GeometryService, ProjectParameters) => {
    const geoService = new GeometryService( "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer" );
    const projectParams = new ProjectParameters({
      geometries: [points],            
      outSR: outSR,
      transformation = transformation
    });
    geoService.project(projectParams)
      .then((projectedGeoms) => {
       console.log("projected points: ", projectedGeoms);
      }, (error) => {
        console.error(error);
      });
});

Promise 函数链

使用Promise 的优点之一是可以利用then()将多个Promise 连接起来。
当一个以上的Promise 被链在一起时,一个Promise 的解析值将被被传递给下一个Promise 。这使得代码块可以按顺序执行,而不需要在彼此之间嵌套回调。

注意:

回调函数必须使用return关键字来返回一个值给下一个Promise 。

  const bufferLayer = new GraphicsLayer();

  function bufferPoints(points) {
    return geometryEngine.geodesicBuffer(points, 1000, "feet");
  }

  function addGraphicsToBufferLayer(buffers) {
    buffers.forEach((buffer) => {
      bufferLayer.add(new Graphic(buffer));
    });
    return buffers;
  }

  function calculateArea(buffer) {
    return geometryEngine.geodesicArea(buffer, "square-feet");
  }

  function calculateAreas(buffers) {
    return buffers.map(calculateArea);
  }

  function sumArea(areas) {
    for (let i = 0, total = 0; i < areas.length; i++) {
      total += areas[i];
    }
    return total;
  }

  geoService.project(projectParams)
    .then(bufferPoints)
    .then(addGraphicsToBufferLayer)
    .then(calculateAreas)
    .then(sumArea)
    .catch((error) => {
      console.error("One of the promises in the chain was rejected! Message:", error);
    });

也可以使用asyncawait关键词,简单来说,它们是基于Promise的语法糖,使异步代码看起来更像是同步代码。具体请查阅文档

手动加载

如果View是用Map实例构造的,那么load方法会自动执行,加载View和关联的Map中引用的所有资源。简单来讲,当实例化的图层并没有被map或view引用时,图层服务的所有资源并不会自动加载,需要手动调用load方法加载它所需的资源来完成初始化。

load状态包括not-loadedloadingfailedloaded,分别代表尚未加载,加载中,加载失败和加载成功。

下面的状态转换代表了一个可加载资源所经历的阶段。

loadable-pattern

可以用以下代码验证load状态:

require(["esri/Map", "esri/views/MapView", "esri/layers/FeatureLayer"], (Map, MapView, FeatureLayer) => {
        const map = new Map({
            basemap: "osm"
        })
        const view = new MapView({
            map,
            container: "view"
        })
        const layer = new FeatureLayer({
            url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/0"
        });
        console.log(layer.loadStatus)
        console.log(layer.fields)
        layer.load().then(() => {
            console.log(layer.loadStatus)
            console.log(layer.fields)
        }, (err) => {
            console.log(err)
        })
    });

这是一个没有与Map或者View关联的FeatureLayer,在实例化之后输出它的加载状态和包含的字段属性,并在手动调用load()之后再次输出加载状态和包含的字段。浏览器输出如下所示:

image-20210903180058302

从结果可验证如上所说。

fromJSON 方法

fromJSON方法从ArcGIS产品生成的JSON中创建一个指定类的实例。这种格式的JSON通常由toJSON()方法或通过REST API的查询创建。不能与一般的JSONGeoJSON混用。

jsonUtils 辅助方法

在使用fromJSON()实例化一个对象时,有几个jsonUtils类作为工具类提供。

当一个JSON对象是来自REST API的几何体、渲染器或符号,但对象类型未知时,这些类可以快速处理这种情况。例如,当一个图层的渲染器来自于REST请求,并且不确定该渲染器是否是UniqueValueRenderer时,调用esri/renderers/support/jsonUtils类来帮助确定该渲染器的类型。

require([ "esri/renderers/support/jsonUtils",
          "esri/layers/FeatureLayer"
], ( rendererJsonUtils, FeatureLayer ) => {

  const rendererJSON = {               // renderer object obtained via REST request
     "authoringInfo":null,
     "type":"uniqueValue",
     "field1":"CLASS",
     "field2":null,
     "field3":null,
     "expression":null,
     "fieldDelimiter":null,
     "defaultSymbol":{
        "color":[
           235,
           235,
           235,
           255
        ],
        "type":"esriSLS",
        "width":3,
        "style":"esriSLSShortDot"
     },
     "defaultLabel":"Other major roads",
     "uniqueValueInfos":[
        {
           "value":"I",
           "symbol":{
              "color":[
                 255,
                 170,
                 0,
                 255
              ],
              "type":"esriSLS",
              "width":10,
              "style":"esriSLSSolid"
           },
           "label":"Interstate"
        },
        {
           "value":"U",
           "symbol":{
              "color":[
                 223,
                 115,
                 255,
                 255
              ],
              "type":"esriSLS",
              "width":7,
              "style":"esriSLSSolid"
           },
           "label":"US Highway"
        }
     ]
  };

  // Create a renderer object from its JSON representation
  const flRenderer = rendererJsonUtils.fromJSON(rendererJSON);

  // Set the renderer on a layer
  const layer = new FeatureLayer({
    renderer: flRenderer
  });
});
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值