mcpField
A
arcgis-layers

arcgis-layers

github.com/saschabrunnerch数据与数据库2379 次安装29 周前更新
代码仓库

关于 arcgis-layers

面向使用 ArcGIS Maps SDK for JavaScript 开发地图的开发者,提供图层操作参考。内容涵盖多种数据源与图层类型的配置、管理和要素查询,也包括 3D 与流数据图层。

主要功能

  1. 01涵盖多种 ArcGIS 图层类型
  2. 02从 URL 或 Portal 项目配置图层
  3. 03添加、移除、排序和设置图层样式
  4. 04查询属性和空间要素
  5. 05加载 3D、影像和流数据

适用场景

  1. 01向地图添加 GeoJSON 或 CSV 数据
  2. 02按属性或范围筛选并查询要素
  3. 03管理图层可见性与顺序
  4. 04显示 3D 或实时地图数据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/saschabrunnerch/arcgis-maps-sdk-js-ai-context --skill arcgis-layers

安装后在 Claude Code 中输入/arcgis-layers确认已加载。

附带文件AGENTS.md

详细介绍

ArcGIS 图层

在 ArcGIS 地图中添加、配置或查询数据图层时使用此技能。

导入模式

直接 ESM 导入
import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer.js";
import GeoJSONLayer from "@arcgis/core/layers/GeoJSONLayer.js";
动态导入(CDN)
const FeatureLayer = await $arcgis.import(
  "@arcgis/core/layers/FeatureLayer.js",
);
const [GraphicsLayer, Graphic] = await $arcgis.import([
  "@arcgis/core/layers/GraphicsLayer.js",
  "@arcgis/core/Graphic.js",
]);

图层类型概览

图层类型用途几何类型
FeatureLayer最常见——要素服务、可编辑数据点、线、面
GraphicsLayer客户端临时图形任意
GeoJSONLayerGeoJSON 文件/URL点、线、面
CSVLayer带坐标的 CSV 文件点
TileLayer缓存地图切片栅格
VectorTileLayer矢量切片(Mapbox 样式)矢量
ImageryTileLayer栅格影像栅格
SceneLayer3D 建筑物、网格3D 对象
IntegratedMeshLayer摄影测量网格3D 网格
PointCloudLayerLiDAR 点云点
ParquetLayerApache Parquet 文件点、线、面
StreamLayer实时 WebSocket 数据点、线、面

FeatureLayer

从 URL 创建
import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";

const featureLayer = new FeatureLayer({
  url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0",
  outFields: ["*"],
  popupTemplate: {
    title: "{Tree_ID}",
    content: "Height: {Crown_Height} ft",
  },
});

map.add(featureLayer);
从 Portal 项创建
const featureLayer = new FeatureLayer({
  portalItem: {
    id: "51c851fef66143959986b473b345b7ca",
  },
  outFields: ["*"],
});
客户端(内存中)
const featureLayer = new FeatureLayer({
  source: graphics, // Array of Graphic objects
  fields: [
    { name: "ObjectID", type: "oid" },
    { name: "name", type: "string" },
    { name: "value", type: "double" },
  ],
  objectIdField: "ObjectID",
  geometryType: "point",
  spatialReference: { wkid: 4326 },
  renderer: {
    type: "simple",
    symbol: { type: "simple-marker", color: "blue" },
  },
});
配置选项
const featureLayer = new FeatureLayer({
  url: "...",
  outFields: ["*"],           // Fields to include (* = all)
  definitionExpression: "population > 10000", // SQL filter
  minScale: 500000,           // Hide when zoomed out beyond this
  maxScale: 0,                // Hide when zoomed in beyond this
  visible: true,              // Initial visibility
  opacity: 0.8,               // Transparency (0-1)
  title: "Cities",            // Display name
  blendMode: "normal",        // Blend mode for compositing
  orderBy: [{ field: "population" }], // Feature draw order
  featureReduction: null,     // Clustering / binning config
  labelingInfo: [...],        // Labels
  renderer: {...},            // Symbology
  popupTemplate: {...},       // Popup configuration
  elevationInfo: {            // 3D elevation mode
    mode: "relative-to-ground"
  }
});

GraphicsLayer

import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer.js";
import Graphic from "@arcgis/core/Graphic.js";

const graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);

// Add a point
const pointGraphic = new Graphic({
  geometry: {
    type: "point",
    longitude: -118.24,
    latitude: 34.05,
  },
  symbol: {
    type: "simple-marker",
    color: "red",
    size: 12,
  },
  attributes: { name: "Los Angeles" },
  popupTemplate: { title: "{name}" },
});

graphicsLayer.add(pointGraphic);

// Add multiple graphics
graphicsLayer.addMany([graphic1, graphic2, graphic3]);

// Remove graphics
graphicsLayer.remove(pointGraphic);
graphicsLayer.removeAll();

GeoJSONLayer

import GeoJSONLayer from "@arcgis/core/layers/GeoJSONLayer.js";

const geojsonLayer = new GeoJSONLayer({
  url: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson",
  copyright: "USGS Earthquakes",
  popupTemplate: {
    title: "Earthquake Info",
    content: "Magnitude {mag} hit {place} on {time}",
    fieldInfos: [
      {
        fieldName: "time",
        format: { dateFormat: "short-date-short-time" },
      },
    ],
  },
  renderer: {
    type: "simple",
    symbol: { type: "simple-marker", color: "orange" },
    visualVariables: [
      {
        type: "size",
        field: "mag",
        stops: [
          { value: 2.5, size: "4px" },
          { value: 8, size: "40px" },
        ],
      },
    ],
  },
  orderBy: [{ field: "mag" }], // Draw smaller on top
});

map.add(geojsonLayer);

CSVLayer

import CSVLayer from "@arcgis/core/layers/CSVLayer.js";

const csvLayer = new CSVLayer({
  url: "https://example.com/data.csv",
  latitudeField: "latitude", // Column name for lat
  longitudeField: "longitude", // Column name for lon
  delimiter: ",",
  popupTemplate: {
    title: "{name}",
    content: "{description}",
  },
});

TileLayer(缓存切片)

import TileLayer from "@arcgis/core/layers/TileLayer.js";

const tileLayer = new TileLayer({
  url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
});

map.add(tileLayer);

VectorTileLayer

import VectorTileLayer from "@arcgis/core/layers/VectorTileLayer.js";

// From portal item
const vtl = new VectorTileLayer({
  portalItem: { id: "VECTOR_TILE_ITEM_ID" },
});

// From URL
const vtl2 = new VectorTileLayer({
  url: "https://basemaps.arcgis.com/v1/arcgis/rest/services/World_Basemap/VectorTileServer",
});

ImageryTileLayer

import ImageryTileLayer from "@arcgis/core/layers/ImageryTileLayer.js";

const imageryLayer = new ImageryTileLayer({
  url: "https://tiledimageservices.arcgis.com/...",
});

// From Cloud Optimized GeoTIFF (COG)
const cogLayer = new ImageryTileLayer({
  url: "https://example.com/image.tif",
});

3D 图层

SceneLayer(3D 建筑物)
import SceneLayer from "@arcgis/core/layers/SceneLayer.js";

const sceneLayer = new SceneLayer({
  portalItem: { id: "2e0761b9a4274b8db52c4bf34356911e" },
  popupEnabled: false,
});

// Add to SceneView map
map.add(sceneLayer);

// Custom 3D symbology
sceneLayer.renderer = {
  type: "simple",
  symbol: {
    type: "mesh-3d",
    symbolLayers: [
      {
        type: "fill",
        material: { color: [244, 247, 134] },
      },
    ],
  },
};
IntegratedMeshLayer
import IntegratedMeshLayer from "@arcgis/core/layers/IntegratedMeshLayer.js";

const meshLayer = new IntegratedMeshLayer({
  url: "https://tiles.arcgis.com/tiles/.../IntegratedMeshServer",
});
PointCloudLayer
import PointCloudLayer from "@arcgis/core/layers/PointCloudLayer.js";

const pcLayer = new PointCloudLayer({
  url: "https://tiles.arcgis.com/tiles/.../SceneServer",
});

专用图层

关于 WMS、WFS、KML、MapImageLayer 和 CatalogLayer,请参阅 arcgis-advanced-layers。

StreamLayer(实时)
import StreamLayer from "@arcgis/core/layers/StreamLayer.js";

const streamLayer = new StreamLayer({
  url: "wss://example.com/stream/service",
  purgeOptions: {
    displayCount: 10000,
  },
});
ParquetLayer(基于文件)
import ParquetLayer from "@arcgis/core/layers/ParquetLayer.js";

const parquetLayer = new ParquetLayer({
  urls: ["https://example.com/data.parquet"],
  title: "Parquet Data",
  renderer: {
    type: "simple",
    symbol: { type: "simple-marker", color: "blue" },
  },
  popupTemplate: {
    title: "{name}",
    content: [
      {
        type: "fields",
        fieldInfos: [{ fieldName: "field1", label: "Field 1" }],
      },
    ],
  },
});

// Query feature count
const count = await parquetLayer.queryFeatureCount();
GeoRSSLayer
import GeoRSSLayer from "@arcgis/core/layers/GeoRSSLayer.js";

const georssLayer = new GeoRSSLayer({
  url: "https://example.com/feed.xml",
});

map.add(georssLayer);

// Zoom to layer extent
await view.whenLayerView(georssLayer);
view.goTo(georssLayer.fullExtent);
WebTileLayer
import WebTileLayer from "@arcgis/core/layers/WebTileLayer.js";

// OpenStreetMap tiles
const osmLayer = new WebTileLayer({
  urlTemplate: "https://{subDomain}.tile.openstreetmap.org/{z}/{x}/{y}.png",
  subDomains: ["a", "b", "c"],
  copyright: "OpenStreetMap contributors",
});

// Custom tile service
const customTileLayer = new WebTileLayer({
  urlTemplate: "https://tiles.example.com/{level}/{col}/{row}.png",
});

map.add(osmLayer);
MapNotesLayer
import MapNotesLayer from "@arcgis/core/layers/MapNotesLayer.js";

// Layer for sketches and annotations
const notesLayer = new MapNotesLayer();
map.add(notesLayer);

// Access sublayers
const pointLayer = notesLayer.pointLayer;
const polylineLayer = notesLayer.polylineLayer;
const polygonLayer = notesLayer.polygonLayer;
const textLayer = notesLayer.textLayer;

// Add a text annotation
const textGraphic = new Graphic({
  geometry: point,
  symbol: {
    type: "text",
    text: "Note here",
    color: [255, 255, 255],
    haloColor: [0, 0, 0],
    haloSize: 2,
    font: { family: "Arial", size: 14 },
  },
});
textLayer.add(textGraphic);

图层管理

添加图层
// Add single layer
map.add(layer);

// Add at specific index (0 = bottom)
map.add(layer, 0);

// Add multiple layers
map.addMany([layer1, layer2, layer3]);

// Add to Map Component
const viewElement = document.querySelector("arcgis-map");
viewElement.map.add(layer);
移除图层
map.remove(layer);
map.removeMany([layer1, layer2]);
map.removeAll();
图层排序
// Reorder layer
map.reorder(layer, newIndex);

// Get layer position
const index = map.layers.indexOf(layer);

// Find layer by id
const layer = map.findLayerById("myLayerId");

// Find layer by title
const layer = map.layers.find((l) => l.title === "Cities");
可见性和不透明度
layer.visible = false;
layer.opacity = 0.5; // 0-1

// Watch visibility changes
import * as reactiveUtils from "@arcgis/core/core/reactiveUtils.js";

reactiveUtils.watch(
  () => layer.visible,
  (newValue) => console.log("Visibility changed:", newValue),
);

查询要素

基本查询
// Create query from layer settings
const query = featureLayer.createQuery();
query.where = "population > 100000";
query.outFields = ["name", "population"];
query.returnGeometry = true;

const result = await featureLayer.queryFeatures(query);
console.log(result.features); // Array of Graphic objects
分页查询
const query = featureLayer.createQuery();
query.start = 0; // Start index
query.num = 20; // Number of features
query.orderByFields = ["population DESC"];

const result = await featureLayer.queryFeatures(query);
空间查询
const query = featureLayer.createQuery();
query.geometry = view.extent; // Or any geometry
query.spatialRelationship = "intersects"; // contains, crosses, etc.
query.returnGeometry = true;

const result = await featureLayer.queryFeatures(query);
计数查询
const count = await featureLayer.queryFeatureCount();
console.log("Total features:", count);
范围查询
const result = await featureLayer.queryExtent();
console.log("Feature count:", result.count);
await view.goTo(result.extent);
统计查询
const query = featureLayer.createQuery();
query.outStatistics = [
  {
    statisticType: "sum",
    onStatisticField: "population",
    outStatisticFieldName: "totalPop",
  },
  {
    statisticType: "avg",
    onStatisticField: "population",
    outStatisticFieldName: "avgPop",
  },
];

const result = await featureLayer.queryFeatures(query);
console.log(result.features[0].attributes.totalPop);
从 LayerView 查询(客户端)
const layerView = await view.whenLayerView(featureLayer);

// Query only currently visible features
const query = layerView.createQuery();
query.geometry = view.extent;

const result = await layerView.queryFeatures(query);

查询方法参考

方法返回值适用场景
queryFeatures(query)FeatureSet(图形)需要实际要素数据时
queryObjectIds(query)number[](OID)只需要 ID 来突出显示时
queryFeatureCount(query)number需要计数但不获取数据时
queryExtent(query){ count, extent }要缩放至匹配要素时
queryRelatedFeatures(params)相关要素集需要相关表记录时
queryAttachments(params)AttachmentInfo[]需要文件附件时
服务端查询与客户端查询
方面featureLayer.queryFeatures()layerView.queryFeatures()
运行位置服务端客户端(浏览器)
数据范围服务中的所有要素视图或缓存中的要素
网络开销每次调用都发送 HTTP 请求无网络请求(数据已加载)
适用场景需要完整数据集、分页或统计信息需要快速筛选可见要素

图层加载

// Wait for layer to load
await featureLayer.load();
console.log("Fields:", featureLayer.fields);
console.log("Extent:", featureLayer.fullExtent);

// Wait for layer view
const layerView = await view.whenLayerView(featureLayer);

// Check if updating
reactiveUtils.watch(
  () => layerView.updating,
  (updating) => {
    if (!updating) {
      console.log("Layer view finished updating");
    }
  },
);

定义表达式(筛选条件)

// SQL WHERE clause filter
featureLayer.definitionExpression = "state = 'California'";

// Clear filter
featureLayer.definitionExpression = null;

// Dynamic filter
function filterByYear(year) {
  featureLayer.definitionExpression = `year = ${year}`;
}

TypeScript 用法

带有 type 属性的图层配置支持自动类型转换。为确保 TypeScript 类型安全,请使用 as const:

// Use 'as const' for type safety
const featureLayer = new FeatureLayer({
  source: graphics,
  fields: [
    { name: "ObjectID", type: "oid" },
    { name: "name", type: "string" },
  ],
  geometryType: "point",
  renderer: {
    type: "simple",
    symbol: { type: "simple-marker", color: "blue" },
  } as const,
});

对于复杂的图层配置,请使用类型注解:

const renderer: __esri.SimpleRendererProperties = {
  type: "simple",
  symbol: { type: "simple-marker", color: "blue" },
};

layer.renderer = renderer;

**提示:**有关自动类型转换与显式类的详细说明,请参阅 arcgis-core-maps。

参考示例

  • intro-layers - 图层使用简介
  • layers-featurelayer - FeatureLayer 配置与用法
  • layers-geojson - 将 GeoJSON 数据加载为图层
  • featurelayer-query - 查询 FeatureLayer 中的要素
  • get-started-graphics - 使用 Graphics 和 GraphicsLayer

相关技能

  • 地图和视图设置请参阅 arcgis-core-maps。
  • 渲染器、符号和视觉变量请参阅 arcgis-visualization。
  • 弹出窗口配置请参阅 arcgis-popup-templates。
  • 使用 applyEdits 编辑要素请参阅 arcgis-editing。
  • WMS、WFS、KML、MapImageLayer 和 CatalogLayer 请参阅 arcgis-advanced-layers。
  • 3D 专用图层配置请参阅 arcgis-3d-layers。

常见问题

  1. GeoJSON 的 CORS 错误:GeoJSON URL 必须启用 CORS,或使用代理。

  2. 缺少 outFields:未指定 outFields 时,查询不会返回任何属性值。

    // Anti-pattern: querying without outFields
    const results = await featureLayer.queryFeatures({
      where: "population > 100000",
      returnGeometry: true,
    });
    console.log(results.features[0].attributes.name); // undefined
    
    // Correct: specify outFields to include desired attributes
    const results = await featureLayer.queryFeatures({
      where: "population > 100000",
      returnGeometry: true,
      outFields: ["name", "population", "state"],
    });
    console.log(results.features[0].attributes.name); // "Los Angeles"
    

    **影响:**要素属性会返回 undefined 或 null。查询虽然成功,但响应中不包含可用的属性数据,导致难以察觉的数据错误。

  3. 未等待图层加载完成:图层元数据(字段、范围、渲染器)只有在图层加载完成后才可用。

    // Anti-pattern: accessing properties before load
    const layer = new FeatureLayer({
      url: "https://services.arcgis.com/.../FeatureServer/0",
    });
    console.log(layer.fields); // null - layer has not loaded yet
    console.log(layer.fullExtent); // null
    
    // Correct: await layer.load() first
    const layer = new FeatureLayer({
      url: "https://services.arcgis.com/.../FeatureServer/0",
    });
    await layer.load();
    console.log(layer.fields); // Array of Field objects
    console.log(layer.fullExtent); // Extent object
    

    影响:fields 为 null 或空数组,fullExtent 为 null,任何依赖图层元数据的代码都会报错或静默失败。

  4. MapView 与 SceneView 使用了错误的图层:某些图层仅适用于 3D(SceneLayer、IntegratedMeshLayer、PointCloudLayer)。

  5. 空间参考不匹配:在视图不支持投影的情况下,添加空间参考与视图不同的图层。

    // Anti-pattern: adding a layer in a different SR without handling projection
    const view = new MapView({
      spatialReference: { wkid: 4326 }, // WGS84
    });
    const layer = new FeatureLayer({
      url: "https://services.arcgis.com/.../FeatureServer/0", // Data in Web Mercator (3857)
    });
    view.map.add(layer); // Features may render in wrong location
    
    // Correct: match spatial references or load the projection engine
    import * as projection from "@arcgis/core/geometry/projection.js";
    await projection.load();
    
    const view = new MapView({
      spatialReference: { wkid: 4326 },
    });
    const layer = new FeatureLayer({
      url: "https://services.arcgis.com/.../FeatureServer/0",
    });
    view.map.add(layer); // Projection engine handles the transformation
    

    **影响:**要素会显示在错误的位置、偏移数千公里,或者在空间参考不兼容时完全不显示。

评论

支持 Markdown