关于 arcgis-layers
面向使用 ArcGIS Maps SDK for JavaScript 开发地图的开发者,提供图层操作参考。内容涵盖多种数据源与图层类型的配置、管理和要素查询,也包括 3D 与流数据图层。
主要功能
- 01涵盖多种 ArcGIS 图层类型
- 02从 URL 或 Portal 项目配置图层
- 03添加、移除、排序和设置图层样式
- 04查询属性和空间要素
- 05加载 3D、影像和流数据
适用场景
- 01向地图添加 GeoJSON 或 CSV 数据
- 02按属性或范围筛选并查询要素
- 03管理图层可见性与顺序
- 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 | 客户端临时图形 | 任意 |
| GeoJSONLayer | GeoJSON 文件/URL | 点、线、面 |
| CSVLayer | 带坐标的 CSV 文件 | 点 |
| TileLayer | 缓存地图切片 | 栅格 |
| VectorTileLayer | 矢量切片(Mapbox 样式) | 矢量 |
| ImageryTileLayer | 栅格影像 | 栅格 |
| SceneLayer | 3D 建筑物、网格 | 3D 对象 |
| IntegratedMeshLayer | 摄影测量网格 | 3D 网格 |
| PointCloudLayer | LiDAR 点云 | 点 |
| ParquetLayer | Apache 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。
常见问题
-
GeoJSON 的 CORS 错误:GeoJSON URL 必须启用 CORS,或使用代理。
-
缺少 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。查询虽然成功,但响应中不包含可用的属性数据,导致难以察觉的数据错误。 -
未等待图层加载完成:图层元数据(字段、范围、渲染器)只有在图层加载完成后才可用。
// 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,任何依赖图层元数据的代码都会报错或静默失败。 -
MapView 与 SceneView 使用了错误的图层:某些图层仅适用于 3D(SceneLayer、IntegratedMeshLayer、PointCloudLayer)。
-
空间参考不匹配:在视图不支持投影的情况下,添加空间参考与视图不同的图层。
// 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**影响:**要素会显示在错误的位置、偏移数千公里,或者在空间参考不兼容时完全不显示。