前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ArcGIS API for JavaScript 中的 Autocasting

ArcGIS API for JavaScript 中的 Autocasting

作者头像
beginor
发布2021-04-25 10:32:14
8960
发布2021-04-25 10:32:14
举报
文章被收录于专栏:张志敏的技术专栏

ArcGIS API for JavaScript 中的 Autocasting

Autocasting 简介

Autocasting 是 ArcGIS API for JavaScript 4.x 的一个新特性, 将 json 对象转换成对应的 ArcGIS API for JavaScript 类型实例, 而不需要导入对应的 js 模块。

在下面的示例代码中, 为 FeatureLayer 创建一个 SimpleRenderer 需要导入 5 个模块:

代码语言:javascript
复制
require([
  'esri/Color',
  'esri/symbols/SimpleLineSymbol',
  'esri/symbols/SimpleMarkerSymbol',
  'esri/renderers/SimpleRenderer',
  'esri/layers/FeatureLayer',
], function (
  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 , 不必导入 renderersymbol 相关模块, 只需要导入 esri/layers/FeatureLayer 模块即可:

代码语言:javascript
复制
require([ "esri/layers/FeatureLayer" ], function (FeatureLayer) {

  const layer = new FeatureLayer({
    url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/WorldCities/FeatureServer/0",
    renderer: {                        // autocasts as new SimpleRenderer()
      type: "simple",
      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()
        }
      }
    }
  });

});

要知道一个类能否被自动转换, 得查看这个类在 ArcGIS API for JavaScript 中的对应类的文档, 如果一个一个属性能够进行自动转换, 就会出现 Autocast 标记。

比如 FeatureLayerrenderer 就有 autocast 标记。

上面的两段代码是等价的, 很显然使用 autocasting 的代码更加简单, 只需写一个 json 对象, 而这个 json 对象和 ArcGIS API for JavaScript 对应类型的属性相同, ArcGIS API for JavaScript 会内部进行处理, 将这个 json 对象传递给对应类型的构造函数进行初始化。

当模块类型是已知的,或者是固定的, 则不需要指定 type 属性, 比如在下面代码中的 SimpleMarkerSymboloutline 属性, 这个属性是固定的, 只能是 SimpleLineSymbol

代码语言:javascript
复制
const diamondSymbol = {
  type: "simple-marker",
  outline: {
    type: "simple-line", // Not needed, as type `simple-line` is implied
    style: "dash-dot",
    color: [ 255, 128, 45 ]
  }
};

当类型更加的宽泛时, 比如 FeatureLayerrenderer , 就有多种实现, 必须指定 type 才能让 Autocasting 正常工作。

ArcGIS API for JavaScript 官方文档中所有的示例代码 都尽可能的使用了 Autocasting 。

Autocasting 扩展

然而遗憾的是, ArcGIS API for JavaScript 只实现了部分属性的 Autocasting , 并没有将 Autocasting 进行到底, 比如创建一个 WebScene 时, 还需要根据图层类型导入多个模块:

代码语言:javascript
复制
require([
  'esri/WebScene',
  'esri/layers/TileLayer',
  'esri/layers/FeatureLayer',
  'esri/layers/VectorTileLayer'
], function(WebScene, TileLayer, FeatureLayer, VectorTileLayer) {
  var scene = new WebScene({
    basemap: 'streets',
    layers: [
      new TileLayer({ url: '' }),
      new VectorTileLayer({ url: '' }),
      new FeatureLayer({ url: '' })
    ]
  })
});

如果将 Autocasting 进行到底, 可以通过下面的 json 来创建一个 WebScene :

代码语言:javascript
复制
{
  "basemap": "streets",
  "ground": "world-elevation",
  "layers": [
    {
      "type": "tile", // For TileLayer the type is always "tile".
      "url": "https://services.arcgisonline.com/arcgis/rest/services/World_Terrain_Base/MapServer",
      "title": "World Terrain Base"
    },
    {
      "type": "vector-tile", // For VectorTileLayer the type is always "vector-tile".
      "url": "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer",
      "style": { /* ... */ }
    },
    {
      "type": "feature", // For FeatureLayer the type is feature.
      "url": "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/WorldCities/FeatureServer/0",
      "renderer": {
        "type": "simple",
        "symbol": {
          "type": "simple-marker",
          "style": "diamond",
          "color": [ 255, 128, 45 ],
          "outline": { "style": "dash-dot", "color": [ 0, 0, 0 ] }
        }
      }
    }
  ],
}

如果能够像上面这样, 从 json 来创建 WebScene , 使用起来将会非常的方便。 但是不知道是什么原因, ArcGIS API for Javascript 并没有实现这个功能, 不过可以使用 ESRI 官方维护的 esri-loader 对 Autocasting 进行扩展, 实现这样的功能, 部分代码如下:

代码语言:javascript
复制
import { loadModules } from 'esri-loader';

/**
 * create a webscene instance by json;
 * @param properties webscene json properties
 */
export async function createWebScene(
    properties: __esri.WebSceneProperties
): Promise<__esri.WebScene> {
    await createMapLayers(properties);
    let webscene: __esri.WebScene;
    const [WebScene] = await loadModules(['esri/WebScene']);
    webscene = new WebScene(properties);
    return webscene;
}

/** Create a FeatureLayer from properties */
export function createFeatureLayer(
  properties: __esri.FeatureLayerProperties
): Promise<__esri.FeatureLayer> {
  Object.assign(properties, { type: 'feature' });
  return createLayer<__esri.FeatureLayer>(properties);
}

/** Create a TileLayer from properties. */
export function createTileLayer(
  properties: __esri.TileLayerProperties
): Promise<__esri.TileLayer> {
  Object.assign(properties, { type: 'tile' });
  return createLayer<__esri.TileLayer>(properties);
}

/**
 * Create a layer from properties;
 * @param props layer's properties
 */
export async function createLayer<T extends __esri.Layer>(
  props: any
): Promise<T> {
  const layerType = props.type;
  delete props.type; // type is readonly, need delete it here from properties
  let layer: T;
  switch (layerType) {
    case 'feature':
      const [FeatureLayer] = await loadModules([
        'esri/layers/FeatureLayer'
      ]);
      layer = new FeatureLayer(props);
      break;
    case 'tile':
      const [TileLayer] = await loadModules([
        'esri/layers/TileLayer'
      ]);
      layer = new TileLayer(props);
      break;
    case 'vector-tile':
      const [VectorTileLayer] = await loadModules([
        'esri/layers/VectorTileLayer'
      ]);
      layer = new VectorTileLayer(props);
      break;
    default:
      throw new Error(`Unknown layer type: ${layerType}`);
  }
  return layer;
}

这里只贴出了部分代码, 如果继续了解, 请查看这个 esri-service 的代码。

这个类库也发布了 npm 包 esri-service, 如果使用了 nodejs 的话, 只要通过命令 npm i esri-service 即可安装。

有了 esri-service 之后, 可以更加方便的创建图层和地图:

创建要素图层

代码语言:javascript
复制
import * as arcgis from 'esri-service';

const featureLayer = await arcgis.createFeatureLayer({
  url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/WorldCities/FeatureServer/0",
  renderer: {
    type: "simple",
    symbol: {
      type: "simple-marker",
      style: "diamond",
      color: [ 255, 128, 45 ],
      outline: { style: "dash-dot", color: [ 0, 0, 0 ] }
    }
  }
});

创建切片地图

代码语言:javascript
复制
const tileLayer = await arcgis.createTileLayer({
  url: "https://services.arcgisonline.com/arcgis/rest/services/World_Terrain_Base/MapServer",
  title: "World Terrain Base"
});

创建矢量切片图层

代码语言:javascript
复制
const vectorLayer = await arcgis.createVectorTileLayer({
  url: "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer",
  style: { /* ... */ }
});

创建 WebMap

代码语言:javascript
复制
const map = await arcgis.createMap({
  basemap: 'satellite',
  ground: 'world-elevation',
  layers: [
    {
      type: "tile", // For TileLayer the type is always "tile".
      url: "https://services.arcgisonline.com/arcgis/rest/services/World_Terrain_Base/MapServer",
      title: "World Terrain Base"
    },
    {
      type: "vector-tile", // For VectorTileLayer the type is always "vector-tile".
      url: "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer",
      style: { /* ... */ }
    },
    {
      type: "feature", // For FeatureLayer the type is feature.
      url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/WorldCities/FeatureServer/0",
      renderer: {
        type: "simple",
        symbol: {
          type: "simple-marker",
          style: "diamond",
          color: [ 255, 128, 45 ],
          outline: { style: "dash-dot", color: [ 0, 0, 0 ] }
        }
      }
    }
  ]
});

创建地图视图

代码语言:javascript
复制
const sceneView = await arcgis.createSceneView({
    container: document.getElementById('map'),
    map,
    zoom: 7,
    center: { longitude: 113.2, latitude: 23.4 },
    viewingMode: 'local'
});

甚至再进一步, 可以将 WebMap 或者 WebScene 以 json 的形式保存到服务器或者数据库, 实现类似 ArcGIS Portal 的场景式地图管理。

最后

最后说一下, esri-loader 一直是 ArcGIS API for JavaScript 的加载神器, 隔离了 dojo 的入侵性, 让 ArcGIS API for JavaScript 轻松加载到常见的前端开发环境中, 包括今天的对 Autocasting 的扩展, 也是用到了 esri-loader

不过从 4.18 开始, ArcGIS API for JavaScript 提供了原生 ES6 模块 @arcgis/core , 可以直接在受支持的浏览器中运行, 不用在依赖第三方加载器, 也可以很轻松的在各种前端框架中使用。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ArcGIS API for JavaScript 中的 Autocasting
    • Autocasting 简介
      • Autocasting 扩展
        • 创建要素图层
        • 创建切片地图
        • 创建矢量切片图层
        • 创建 WebMap
        • 创建地图视图
      • 最后
      相关产品与服务
      云服务器
      云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档