arcgis-core-maps

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ArcGIS Core Maps

ArcGIS核心地图

Use this skill when creating 2D maps (MapView) or 3D scenes (SceneView) with the ArcGIS Maps SDK for JavaScript.
当你使用ArcGIS Maps SDK for JavaScript创建2D地图(MapView)或3D场景(SceneView)时,可以参考本内容。

Import Patterns

导入方式

Direct ESM Imports (Recommended for Build Tools)

直接ESM导入(推荐用于构建工具)

Use with Vite, webpack, Rollup, or other build tools:
javascript
import Map from "@arcgis/core/Map.js";
import MapView from "@arcgis/core/views/MapView.js";
import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
  • Tree-shakeable
  • Standard JavaScript modules
  • Best for production applications
适用于Vite、webpack、Rollup或其他构建工具:
javascript
import Map from "@arcgis/core/Map.js";
import MapView from "@arcgis/core/views/MapView.js";
import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
  • Tree-shakeable
  • 标准JavaScript模块
  • 最适合生产环境应用

Dynamic Imports (CDN / No Build Tools)

动态导入(CDN / 无构建工具场景)

Use with CDN script tags when no build step is available:
javascript
const Map = await $arcgis.import("@arcgis/core/Map.js");
const MapView = await $arcgis.import("@arcgis/core/views/MapView.js");

// Multiple imports
const [FeatureLayer, Graphic] = await $arcgis.import([
  "@arcgis/core/layers/FeatureLayer.js",
  "@arcgis/core/Graphic.js"
]);
  • Works with Map Components (web components)
  • No build step required
  • Good for quick prototypes and demos
  • Requires
    <script src="https://js.arcgis.com/4.34/"></script>
    in HTML
Note: The examples in this skill use Direct ESM imports. For CDN usage, replace
import X from "path"
with
const X = await $arcgis.import("path")
.
当没有构建步骤时,可配合CDN脚本标签使用:
javascript
const Map = await $arcgis.import("@arcgis/core/Map.js");
const MapView = await $arcgis.import("@arcgis/core/views/MapView.js");

// 批量导入
const [FeatureLayer, Graphic] = await $arcgis.import([
  "@arcgis/core/layers/FeatureLayer.js",
  "@arcgis/core/Graphic.js"
]);
  • 兼容Map Components(Web组件)
  • 无需构建步骤
  • 适合快速原型开发和演示
  • 需要在HTML中引入
    <script src="https://js.arcgis.com/4.34/"></script>
注意: 本内容中的示例使用直接ESM导入方式。如果使用CDN,请将
import X from "path"
替换为
const X = await $arcgis.import("path")

Autocasting vs Explicit Classes (TypeScript)

Autocasting与显式类(TypeScript)

The ArcGIS SDK supports autocasting - passing plain objects instead of class instances. Understanding when to use each approach is important for TypeScript projects.
ArcGIS SDK支持autocasting——即传递普通对象而非类实例。在TypeScript项目中,理解两种方式的适用场景十分重要。

When to Use Explicit Classes (Non-Autocast)

何时使用显式类(非Autocast方式)

Use
new SimpleRenderer()
,
new Point()
, etc. when:
  • You need instance methods or
    instanceof
    checks
  • Building shared internal libraries - constructor APIs surface breaking changes at compile time
  • You want strong editor discoverability -
    new SimpleRenderer({ ... })
    exposes properties clearly
  • You mutate objects incrementally - long-lived instances are clearer as real classes
typescript
import SimpleRenderer from "@arcgis/core/renderers/SimpleRenderer.js";
import SimpleMarkerSymbol from "@arcgis/core/symbols/SimpleMarkerSymbol.js";

const renderer = new SimpleRenderer({
  symbol: new SimpleMarkerSymbol({
    color: [226, 119, 40],
    size: 8
  })
});
当以下场景时,使用
new SimpleRenderer()
new Point()
等显式类:
  • 需要调用实例方法或进行
    instanceof
    检查
  • 构建内部共享库——构造函数API会在编译阶段暴露破坏性变更
  • 需要强编辑器提示——
    new SimpleRenderer({ ... })
    会清晰展示可用属性
  • 需要增量修改对象——长生命周期的实例作为真实类会更清晰
typescript
import SimpleRenderer from "@arcgis/core/renderers/SimpleRenderer.js";
import SimpleMarkerSymbol from "@arcgis/core/symbols/SimpleMarkerSymbol.js";

const renderer = new SimpleRenderer({
  symbol: new SimpleMarkerSymbol({
    color: [226, 119, 40],
    size: 8
  })
});

When to Use Autocasting

何时使用Autocasting

Use plain objects with
type
property when:
  • Configuration-heavy code - renderers, symbols, popups are usually data, not behavior
  • UI-driven configuration - React state → plain objects → SDK properties is simpler
  • Serialization and reuse matter - configs can be stored, diffed, tested, reused
  • Property updates after creation -
    layer.renderer = { ... }
    works cleanly in React
    useEffect
typescript
// Use 'as const' or 'satisfies' to keep discriminated unions narrow
const renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    color: [226, 119, 40],
    size: 8
  }
} as const;

// Or with satisfies for better type inference
import type { SimpleRenderer } from "@arcgis/core/renderers/SimpleRenderer.js";

const renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    color: [226, 119, 40],
    size: 8
  }
} satisfies __esri.SimpleRendererProperties;
当以下场景时,使用带
type
属性的普通对象:
  • 配置密集型代码——渲染器、符号、弹窗通常是数据而非行为
  • UI驱动的配置——React状态 → 普通对象 → SDK属性的流程更简洁
  • 需要序列化和复用——配置可被存储、对比、测试和复用
  • 创建后需更新属性——在React的
    useEffect
    中,
    layer.renderer = { ... }
    的写法更简洁
typescript
// 使用'as const'或'satisfies'保持判别联合类型的窄化
const renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    color: [226, 119, 40],
    size: 8
  }
} as const;

// 或使用satisfies获得更好的类型推断
import type { SimpleRenderer } from "@arcgis/core/renderers/SimpleRenderer.js";

const renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    color: [226, 119, 40],
    size: 8
  }
} satisfies __esri.SimpleRendererProperties;

TypeScript Best Practices

TypeScript最佳实践

The real TypeScript concern is keeping discriminated unions narrow:
typescript
// ❌ BAD - type widens to string
const symbol = { type: "simple-marker", color: "red" };

// ✅ GOOD - type stays literal
const symbol = { type: "simple-marker", color: "red" } as const;

// ✅ GOOD - explicit type annotation
const symbol: __esri.SimpleMarkerSymbolProperties = {
  type: "simple-marker",
  color: "red"
};
TypeScript的核心关注点是保持判别联合类型的窄化:
typescript
// ❌ 错误示例 - 类型被拓宽为string
const symbol = { type: "simple-marker", color: "red" };

// ✅ 正确示例 - 类型保持字面量
const symbol = { type: "simple-marker", color: "red" } as const;

// ✅ 正确示例 - 显式类型注解
const symbol: __esri.SimpleMarkerSymbolProperties = {
  type: "simple-marker",
  color: "red"
};

Recommended Default

推荐默认方案

  • Autocast for configuration (renderers, symbols, popups, labels)
  • Explicit classes for behavior (when you need methods or instanceof)
  • Use
    as const
    or
    satisfies
    to maintain type safety with autocasting
  • 配置类内容使用Autocast(渲染器、符号、弹窗、标签)
  • 行为类内容使用显式类(当需要调用方法或进行instanceof检查时)
  • **使用
    as const
    satisfies
    **在Autocast时保持类型安全

Two Approaches

两种实现方式

1. Map Components (Modern - Recommended)

1. Map Components(现代方式 - 推荐)

Web components approach using
<arcgis-map>
and
<arcgis-scene>
.
使用
<arcgis-map>
<arcgis-scene>
的Web组件方式。

2. Core API

2. Core API

Traditional JavaScript approach using
Map
,
MapView
, and
SceneView
classes.
使用
Map
MapView
SceneView
类的传统JavaScript方式。

CDN Setup

CDN配置

Map Components Approach

Map Components方式

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>ArcGIS Map</title>
  <style>
    html, body { height: 100%; margin: 0; }
  </style>
  <!-- Load Calcite components -->
  <script type="module" src="https://js.arcgis.com/calcite-components/3.3.3/calcite.esm.js"></script>
  <!-- Load ArcGIS Maps SDK -->
  <script src="https://js.arcgis.com/4.34/"></script>
  <!-- Load Map components -->
  <script type="module" src="https://js.arcgis.com/4.34/map-components/"></script>
</head>
<body>
  <arcgis-map basemap="topo-vector" center="-118.24,34.05" zoom="12">
    <arcgis-zoom slot="top-left"></arcgis-zoom>
  </arcgis-map>
</body>
</html>
html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>ArcGIS Map</title>
  <style>
    html, body { height: 100%; margin: 0; }
  </style>
  <!-- 加载Calcite组件 -->
  <script type="module" src="https://js.arcgis.com/calcite-components/3.3.3/calcite.esm.js"></script>
  <!-- 加载ArcGIS Maps SDK -->
  <script src="https://js.arcgis.com/4.34/"></script>
  <!-- 加载Map组件 -->
  <script type="module" src="https://js.arcgis.com/4.34/map-components/"></script>
</head>
<body>
  <arcgis-map basemap="topo-vector" center="-118.24,34.05" zoom="12">
    <arcgis-zoom slot="top-left"></arcgis-zoom>
  </arcgis-map>
</body>
</html>

Core API Approach

Core API方式

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>ArcGIS Map</title>
  <style>
    html, body, #viewDiv { height: 100%; margin: 0; }
  </style>
  <!-- REQUIRED: main.css for Core API -->
  <link rel="stylesheet" href="https://js.arcgis.com/4.34/esri/themes/light/main.css" />
  <script src="https://js.arcgis.com/4.34/"></script>
</head>
<body>
  <div id="viewDiv"></div>
  <script type="module">
    import Map from "@arcgis/core/Map.js";
    import MapView from "@arcgis/core/views/MapView.js";

    const map = new Map({ basemap: "topo-vector" });
    const view = new MapView({
      container: "viewDiv",
      map: map,
      center: [-118.24, 34.05], // [longitude, latitude]
      zoom: 12
    });
  </script>
</body>
</html>
html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>ArcGIS Map</title>
  <style>
    html, body, #viewDiv { height: 100%; margin: 0; }
  </style>
  <!-- 必需:Core API的main.css -->
  <link rel="stylesheet" href="https://js.arcgis.com/4.34/esri/themes/light/main.css" />
  <script src="https://js.arcgis.com/4.34/"></script>
</head>
<body>
  <div id="viewDiv"></div>
  <script type="module">
    import Map from "@arcgis/core/Map.js";
    import MapView from "@arcgis/core/views/MapView.js";

    const map = new Map({ basemap: "topo-vector" });
    const view = new MapView({
      container: "viewDiv",
      map: map,
      center: [-118.24, 34.05], // [经度, 纬度]
      zoom: 12
    });
  </script>
</body>
</html>

2D Maps

2D地图

Map Components

Map Components方式

html
<arcgis-map basemap="topo-vector" center="-118.24,34.05" zoom="12">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
  <arcgis-compass slot="top-left"></arcgis-compass>
  <arcgis-home slot="top-left"></arcgis-home>
  <arcgis-locate slot="top-left"></arcgis-locate>
</arcgis-map>

<script type="module">
  const mapElement = document.querySelector("arcgis-map");
  await mapElement.viewOnReady(); // Wait for view to be ready
  const view = mapElement.view;   // Access the MapView
  const map = mapElement.map;     // Access the Map
</script>
html
<arcgis-map basemap="topo-vector" center="-118.24,34.05" zoom="12">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
  <arcgis-compass slot="top-left"></arcgis-compass>
  <arcgis-home slot="top-left"></arcgis-home>
  <arcgis-locate slot="top-left"></arcgis-locate>
</arcgis-map>

<script type="module">
  const mapElement = document.querySelector("arcgis-map");
  await mapElement.viewOnReady(); // 等待视图准备完成
  const view = mapElement.view;   // 获取MapView实例
  const map = mapElement.map;     // 获取Map实例
</script>

Core API

Core API方式

javascript
import Map from "@arcgis/core/Map.js";
import MapView from "@arcgis/core/views/MapView.js";

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

const view = new MapView({
  container: "viewDiv",
  map: map,
  center: [-118.24, 34.05],
  zoom: 12,
  // Optional constraints
  constraints: {
    minZoom: 5,
    maxZoom: 18,
    rotationEnabled: false
  }
});
javascript
import Map from "@arcgis/core/Map.js";
import MapView from "@arcgis/core/views/MapView.js";

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

const view = new MapView({
  container: "viewDiv",
  map: map,
  center: [-118.24, 34.05],
  zoom: 12,
  // 可选约束
  constraints: {
    minZoom: 5,
    maxZoom: 18,
    rotationEnabled: false
  }
});

3D Scenes

3D场景

Map Components

Map Components方式

html
<arcgis-scene basemap="topo-3d" ground="world-elevation">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
  <arcgis-navigation-toggle slot="top-left"></arcgis-navigation-toggle>
</arcgis-scene>

<script type="module">
  const sceneElement = document.querySelector("arcgis-scene");
  await sceneElement.viewOnReady();
  const view = sceneElement.view; // SceneView
</script>
html
<arcgis-scene basemap="topo-3d" ground="world-elevation">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
  <arcgis-navigation-toggle slot="top-left"></arcgis-navigation-toggle>
</arcgis-scene>

<script type="module">
  const sceneElement = document.querySelector("arcgis-scene");
  await sceneElement.viewOnReady();
  const view = sceneElement.view; // SceneView实例
</script>

Core API

Core API方式

javascript
import Map from "@arcgis/core/Map.js";
import SceneView from "@arcgis/core/views/SceneView.js";

const map = new Map({
  basemap: "topo-3d",
  ground: "world-elevation"
});

const view = new SceneView({
  container: "viewDiv",
  map: map,
  camera: {
    position: {
      longitude: -118.24,
      latitude: 34.05,
      z: 25000 // altitude in meters
    },
    heading: 0,   // compass direction
    tilt: 45      // 0 = straight down, 90 = horizon
  }
});
javascript
import Map from "@arcgis/core/Map.js";
import SceneView from "@arcgis/core/views/SceneView.js";

const map = new Map({
  basemap: "topo-3d",
  ground: "world-elevation"
});

const view = new SceneView({
  container: "viewDiv",
  map: map,
  camera: {
    position: {
      longitude: -118.24,
      latitude: 34.05,
      z: 25000 // 海拔高度(米)
    },
    heading: 0,   // 罗盘方向
    tilt: 45      // 0=垂直向下,90=水平视角
  }
});

Video View Container

视频视图容器

The
arcgis-video
component is a third view container alongside
arcgis-map
and
arcgis-scene
, used for displaying video feeds from video services.
arcgis-video
组件是除
arcgis-map
arcgis-scene
之外的第三种视图容器,用于显示视频服务的视频流。

Map Component

Map Component方式

html
<arcgis-video>
  <arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-video>
javascript
import "@arcgis/map-components/dist/components/arcgis-video";

const videoElement = document.querySelector("arcgis-video");
videoElement?.addEventListener("arcgisViewReadyChange", (event) => {
  const { view } = event.detail;
  console.log("Video view ready:", view);
});
Note:
arcgis-video
supports the same position slots as
arcgis-map
and
arcgis-scene
:
top-left
,
top-right
,
bottom-left
,
bottom-right
,
top-start
,
top-end
,
bottom-start
,
bottom-end
.
html
<arcgis-video>
  <arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-video>
javascript
import "@arcgis/map-components/dist/components/arcgis-video";

const videoElement = document.querySelector("arcgis-video");
videoElement?.addEventListener("arcgisViewReadyChange", (event) => {
  const { view } = event.detail;
  console.log("Video view ready:", view);
});
注意:
arcgis-video
支持与
arcgis-map
arcgis-scene
相同的位置插槽:
top-left
top-right
bottom-left
bottom-right
top-start
top-end
bottom-start
bottom-end

Loading WebMaps and WebScenes

加载WebMap和WebScene

WebMap (2D)

WebMap(2D)

html
<!-- Map Components -->
<arcgis-map item-id="f2e9b762544945f390ca4ac3671cfa72">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-map>
javascript
// Core API
import MapView from "@arcgis/core/views/MapView.js";
import WebMap from "@arcgis/core/WebMap.js";

const webmap = new WebMap({
  portalItem: { id: "f2e9b762544945f390ca4ac3671cfa72" }
});

const view = new MapView({
  map: webmap,
  container: "viewDiv"
});
html
<!-- Map Components方式 -->
<arcgis-map item-id="f2e9b762544945f390ca4ac3671cfa72">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-map>
javascript
// Core API方式
import MapView from "@arcgis/core/views/MapView.js";
import WebMap from "@arcgis/core/WebMap.js";

const webmap = new WebMap({
  portalItem: { id: "f2e9b762544945f390ca4ac3671cfa72" }
});

const view = new MapView({
  map: webmap,
  container: "viewDiv"
});

WebScene (3D)

WebScene(3D)

html
<!-- Map Components -->
<arcgis-scene item-id="YOUR_WEBSCENE_ID">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-scene>
javascript
// Core API
import SceneView from "@arcgis/core/views/SceneView.js";
import WebScene from "@arcgis/core/WebScene.js";

const webscene = new WebScene({
  portalItem: { id: "YOUR_WEBSCENE_ID" }
});

const view = new SceneView({
  map: webscene,
  container: "viewDiv"
});
html
<!-- Map Components方式 -->
<arcgis-scene item-id="YOUR_WEBSCENE_ID">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-scene>
javascript
// Core API方式
import SceneView from "@arcgis/core/views/SceneView.js";
import WebScene from "@arcgis/core/WebScene.js";

const webscene = new WebScene({
  portalItem: { id: "YOUR_WEBSCENE_ID" }
});

const view = new SceneView({
  map: webscene,
  container: "viewDiv"
});

Navigation Components

导航组件

ComponentPurpose
arcgis-zoom
Zoom in/out buttons
arcgis-compass
Orientation indicator, click to reset north
arcgis-home
Return to initial extent
arcgis-locate
Find user's location
arcgis-navigation-toggle
Switch between pan/rotate modes (3D)
arcgis-fullscreen
Toggle fullscreen mode
arcgis-scale-bar
Display map scale
组件用途
arcgis-zoom
放大/缩小按钮
arcgis-compass
方向指示器,点击可重置为正北方向
arcgis-home
返回初始视图范围
arcgis-locate
定位用户当前位置
arcgis-navigation-toggle
在平移/旋转模式间切换(3D场景)
arcgis-fullscreen
切换全屏模式
arcgis-scale-bar
显示地图比例尺

Slot Positions

插槽位置示例

html
<arcgis-map basemap="streets-vector">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
  <arcgis-home slot="top-left"></arcgis-home>
  <arcgis-search slot="top-right"></arcgis-search>
  <arcgis-legend slot="bottom-left"></arcgis-legend>
  <arcgis-scale-bar slot="bottom-right"></arcgis-scale-bar>
</arcgis-map>
Available slots:
top-left
,
top-right
,
bottom-left
,
bottom-right
,
top-start
,
top-end
,
bottom-start
,
bottom-end
html
<arcgis-map basemap="streets-vector">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
  <arcgis-home slot="top-left"></arcgis-home>
  <arcgis-search slot="top-right"></arcgis-search>
  <arcgis-legend slot="bottom-left"></arcgis-legend>
  <arcgis-scale-bar slot="bottom-right"></arcgis-scale-bar>
</arcgis-map>
可用插槽:
top-left
top-right
bottom-left
bottom-right
top-start
top-end
bottom-start
bottom-end

View Configuration

视图配置

Setting Initial Extent

设置初始范围

javascript
// By center and zoom
const view = new MapView({
  container: "viewDiv",
  map: map,
  center: [-118.24, 34.05],
  zoom: 12
});

// By scale
const view = new MapView({
  container: "viewDiv",
  map: map,
  center: [-118.24, 34.05],
  scale: 50000 // 1:50,000
});

// By extent
const view = new MapView({
  container: "viewDiv",
  map: map,
  extent: {
    xmin: -118.5,
    ymin: 33.8,
    xmax: -117.9,
    ymax: 34.3,
    spatialReference: { wkid: 4326 }
  }
});
javascript
// 通过中心点和缩放级别
const view = new MapView({
  container: "viewDiv",
  map: map,
  center: [-118.24, 34.05],
  zoom: 12
});

// 通过比例尺
const view = new MapView({
  container: "viewDiv",
  map: map,
  center: [-118.24, 34.05],
  scale: 50000 // 1:50,000
});

// 通过范围
const view = new MapView({
  container: "viewDiv",
  map: map,
  extent: {
    xmin: -118.5,
    ymin: 33.8,
    xmax: -117.9,
    ymax: 34.3,
    spatialReference: { wkid: 4326 }
  }
});

Programmatic Navigation

程序化导航

javascript
// Go to location
await view.goTo({
  center: [-118.24, 34.05],
  zoom: 15
});

// Animated navigation
await view.goTo(
  { center: [-118.24, 34.05], zoom: 15 },
  { duration: 2000, easing: "ease-in-out" }
);

// Go to extent
await view.goTo(layer.fullExtent);

// Go to features
await view.goTo(featureSet.features);
javascript
// 跳转到指定位置
await view.goTo({
  center: [-118.24, 34.05],
  zoom: 15
});

// 带动画的导航
await view.goTo(
  { center: [-118.24, 34.05], zoom: 15 },
  { duration: 2000, easing: "ease-in-out" }
);

// 跳转到图层范围
await view.goTo(layer.fullExtent);

// 跳转到要素集合
await view.goTo(featureSet.features);

View Constraints

视图约束

javascript
// Constrain zoom levels
view.constraints = {
  minZoom: 5,
  maxZoom: 18
};

// Constrain to area
view.constraints = {
  geometry: layer.fullExtent,
  minScale: 500000
};

// Disable rotation
view.constraints = {
  rotationEnabled: false
};
javascript
// 约束缩放级别
view.constraints = {
  minZoom: 5,
  maxZoom: 18
};

// 约束到指定区域
view.constraints = {
  geometry: layer.fullExtent,
  minScale: 500000
};

// 禁用旋转
view.constraints = {
  rotationEnabled: false
};

Event Handling

事件处理

javascript
// View ready
view.when(() => {
  console.log("View is ready");
});

// Click event
view.on("click", (event) => {
  console.log("Clicked at:", event.mapPoint);
});

// Pointer move
view.on("pointer-move", (event) => {
  const point = view.toMap(event);
  console.log("Mouse at:", point.longitude, point.latitude);
});

// Extent change (using reactiveUtils)
import * as reactiveUtils from "@arcgis/core/core/reactiveUtils.js";

reactiveUtils.watch(
  () => view.extent,
  (extent) => console.log("Extent changed:", extent)
);

// Stationary (after pan/zoom completes)
reactiveUtils.watch(
  () => view.stationary,
  (isStationary) => {
    if (isStationary) {
      console.log("Navigation complete");
    }
  }
);
javascript
// 视图准备完成
view.when(() => {
  console.log("View is ready");
});

// 点击事件
view.on("click", (event) => {
  console.log("Clicked at:", event.mapPoint);
});

// 指针移动事件
view.on("pointer-move", (event) => {
  const point = view.toMap(event);
  console.log("Mouse at:", point.longitude, point.latitude);
});

// 范围变化(使用reactiveUtils)
import * as reactiveUtils from "@arcgis/core/core/reactiveUtils.js";

reactiveUtils.watch(
  () => view.extent,
  (extent) => console.log("Extent changed:", extent)
);

// 视图静止(平移/缩放完成后)
reactiveUtils.watch(
  () => view.stationary,
  (isStationary) => {
    if (isStationary) {
      console.log("Navigation complete");
    }
  }
);

Module Imports

模块导入

javascript
// Single import
import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";

// Multiple imports
import Map from "@arcgis/core/Map.js";
import MapView from "@arcgis/core/views/MapView.js";
import Graphic from "@arcgis/core/Graphic.js";
javascript
// 单个导入
import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";

// 多个导入
import Map from "@arcgis/core/Map.js";
import MapView from "@arcgis/core/views/MapView.js";
import Graphic from "@arcgis/core/Graphic.js";

Common Basemaps

常用底图

Basemap IDDescription
streets-vector
Street map
topo-vector
Topographic
satellite
Satellite imagery
hybrid
Satellite with labels
dark-gray-vector
Dark gray canvas
gray-vector
Light gray canvas
osm
OpenStreetMap
topo-3d
3D topographic (SceneView)
底图ID描述
streets-vector
街道地图
topo-vector
地形地图
satellite
卫星影像
hybrid
带标签的卫星影像
dark-gray-vector
深灰色底图
gray-vector
浅灰色底图
osm
OpenStreetMap
topo-3d
3D地形底图(SceneView专用)

esriRequest (HTTP Requests)

esriRequest(HTTP请求)

Basic Request

基础请求

javascript
import esriRequest from "@arcgis/core/request.js";

// GET request with JSON response
const response = await esriRequest(url, {
  query: { f: "json" },
  responseType: "json"
});

console.log("Status:", response.httpStatus);
console.log("Data:", response.data);
javascript
import esriRequest from "@arcgis/core/request.js";

// GET请求,返回JSON
const response = await esriRequest(url, {
  query: { f: "json" },
  responseType: "json"
});

console.log("Status:", response.httpStatus);
console.log("Data:", response.data);

Request with Options

带参数的请求

javascript
const response = await esriRequest(url, {
  query: {
    f: "json",
    param1: "value1"
  },
  responseType: "json",  // "json", "text", "array-buffer", "blob", "image"
  method: "post",        // "auto", "head", "post"
  body: formData,        // For POST requests
  timeout: 30000,        // Timeout in ms
  headers: {
    "X-Custom-Header": "value"
  }
});
javascript
const response = await esriRequest(url, {
  query: {
    f: "json",
    param1: "value1"
  },
  responseType: "json",  // 可选值:"json", "text", "array-buffer", "blob", "image"
  method: "post",        // 可选值:"auto", "head", "post"
  body: formData,        // POST请求的请求体
  timeout: 30000,        // 超时时间(毫秒)
  headers: {
    "X-Custom-Header": "value"
  }
});

Download Binary Data

下载二进制数据

javascript
// Image response
const imageResponse = await esriRequest(imageUrl, {
  responseType: "image"
});
const imageElement = imageResponse.data;

// Binary data
const binaryResponse = await esriRequest(fileUrl, {
  responseType: "array-buffer"
});
const arrayBuffer = binaryResponse.data;
javascript
// 图片响应
const imageResponse = await esriRequest(imageUrl, {
  responseType: "image"
});
const imageElement = imageResponse.data;

// 二进制数据
const binaryResponse = await esriRequest(fileUrl, {
  responseType: "array-buffer"
});
const arrayBuffer = binaryResponse.data;

Planetary Visualization (Mars)

行星可视化(火星)

Mars Scene

火星场景

html
<arcgis-scene>
  <arcgis-zoom slot="top-left"></arcgis-zoom>
  <arcgis-navigation-toggle slot="top-left"></arcgis-navigation-toggle>
</arcgis-scene>

<script type="module">
  import ElevationLayer from "@arcgis/core/layers/ElevationLayer.js";
  import TileLayer from "@arcgis/core/layers/TileLayer.js";
  import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";

  const viewElement = document.querySelector("arcgis-scene");

  // Set Mars spatial reference
  viewElement.spatialReference = { wkid: 104971 }; // Mars 2000

  // Configure camera for Mars
  viewElement.camera = {
    position: {
      x: 27.63423,
      y: -6.34466,
      z: 1281525,
      spatialReference: { wkid: 104971 }
    },
    heading: 332,
    tilt: 37
  };

  await viewElement.viewOnReady();

  // Mars elevation
  const marsElevation = new ElevationLayer({
    url: "https://astro.arcgis.com/arcgis/rest/services/OnMars/MDEM200M/ImageServer"
  });
  viewElement.ground = { layers: [marsElevation] };

  // Mars imagery
  const marsImagery = new TileLayer({
    url: "https://astro.arcgis.com/arcgis/rest/services/OnMars/MDIM/MapServer",
    title: "Mars Imagery"
  });
  viewElement.map.add(marsImagery);
</script>
html
<arcgis-scene>
  <arcgis-zoom slot="top-left"></arcgis-zoom>
  <arcgis-navigation-toggle slot="top-left"></arcgis-navigation-toggle>
</arcgis-scene>

<script type="module">
  import ElevationLayer from "@arcgis/core/layers/ElevationLayer.js";
  import TileLayer from "@arcgis/core/layers/TileLayer.js";
  import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";

  const viewElement = document.querySelector("arcgis-scene");

  // 设置火星空间参考
  viewElement.spatialReference = { wkid: 104971 }; // 火星2000坐标系

  // 配置火星相机位置
  viewElement.camera = {
    position: {
      x: 27.63423,
      y: -6.34466,
      z: 1281525,
      spatialReference: { wkid: 104971 }
    },
    heading: 332,
    tilt: 37
  };

  await viewElement.viewOnReady();

  // 火星高程图层
  const marsElevation = new ElevationLayer({
    url: "https://astro.arcgis.com/arcgis/rest/services/OnMars/MDEM200M/ImageServer"
  });
  viewElement.ground = { layers: [marsElevation] };

  // 火星影像图层
  const marsImagery = new TileLayer({
    url: "https://astro.arcgis.com/arcgis/rest/services/OnMars/MDIM/MapServer",
    title: "Mars Imagery"
  });
  viewElement.map.add(marsImagery);
</script>

Overview Map (Synchronized Views)

概览地图(同步视图)

Overview Map with Scene

场景搭配概览地图

html
<arcgis-scene basemap="hybrid" ground="world-elevation">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
  <!-- Embed overview map inside scene -->
  <arcgis-map basemap="topo-vector" id="overviewDiv" slot="top-right"></arcgis-map>
</arcgis-scene>

<style>
  #overviewDiv { width: 300px; height: 200px; border: 1px solid black; }
</style>

<script type="module">
  import Graphic from "@arcgis/core/Graphic.js";
  import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";

  const sceneElement = document.querySelector("arcgis-scene");
  const overviewElement = document.querySelector("arcgis-map");

  await sceneElement.viewOnReady();
  await overviewElement.viewOnReady();

  // Disable rotation on overview
  overviewElement.constraints.rotationEnabled = false;
  overviewElement.view.ui.components = [];

  // Add visible area graphic
  const visibleAreaGraphic = new Graphic({
    symbol: {
      type: "simple-fill",
      color: [0, 0, 0, 0.5],
      outline: null
    }
  });
  overviewElement.graphics.add(visibleAreaGraphic);

  // Sync overview with main scene
  reactiveUtils.watch(
    () => sceneElement.visibleArea,
    async (visibleArea) => {
      visibleAreaGraphic.geometry = visibleArea;
      await overviewElement.goTo(visibleArea);
    },
    { initial: true }
  );
</script>
html
<arcgis-scene basemap="hybrid" ground="world-elevation">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
  <!-- 在场景中嵌入概览地图 -->
  <arcgis-map basemap="topo-vector" id="overviewDiv" slot="top-right"></arcgis-map>
</arcgis-scene>

<style>
  #overviewDiv { width: 300px; height: 200px; border: 1px solid black; }
</style>

<script type="module">
  import Graphic from "@arcgis/core/Graphic.js";
  import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";

  const sceneElement = document.querySelector("arcgis-scene");
  const overviewElement = document.querySelector("arcgis-map");

  await sceneElement.viewOnReady();
  await overviewElement.viewOnReady();

  // 禁用概览地图的旋转功能
  overviewElement.constraints.rotationEnabled = false;
  overviewElement.view.ui.components = [];

  // 添加可视区域图形
  const visibleAreaGraphic = new Graphic({
    symbol: {
      type: "simple-fill",
      color: [0, 0, 0, 0.5],
      outline: null
    }
  });
  overviewElement.graphics.add(visibleAreaGraphic);

  // 同步概览地图与主场景
  reactiveUtils.watch(
    () => sceneElement.visibleArea,
    async (visibleArea) => {
      visibleAreaGraphic.geometry = visibleArea;
      await overviewElement.goTo(visibleArea);
    },
    { initial: true }
  );
</script>

promiseUtils (Async Utilities)

promiseUtils(异步工具)

Debounce

防抖

javascript
import promiseUtils from "@arcgis/core/core/promiseUtils.js";

// Create debounced function
const debouncedUpdate = promiseUtils.debounce(async () => {
  // This only runs after 300ms of no calls
  await updateFeatures();
});

view.on("pointer-move", () => {
  debouncedUpdate();
});
javascript
import promiseUtils from "@arcgis/core/core/promiseUtils.js";

// 创建防抖函数
const debouncedUpdate = promiseUtils.debounce(async () => {
  // 仅在停止调用300ms后执行
  await updateFeatures();
});

view.on("pointer-move", () => {
  debouncedUpdate();
});

Abort Error Handling

中止错误处理

javascript
import promiseUtils from "@arcgis/core/core/promiseUtils.js";

const abortController = new AbortController();

try {
  await someAsyncOperation({ signal: abortController.signal });
} catch (error) {
  if (promiseUtils.isAbortError(error)) {
    // Operation was intentionally cancelled
    console.log("Operation cancelled");
  } else {
    // Real error
    throw error;
  }
}

// Cancel the operation
abortController.abort();
javascript
import promiseUtils from "@arcgis/core/core/promiseUtils.js";

const abortController = new AbortController();

try {
  await someAsyncOperation({ signal: abortController.signal });
} catch (error) {
  if (promiseUtils.isAbortError(error)) {
    // 操作被主动取消
    console.log("Operation cancelled");
  } else {
    // 真实错误
    throw error;
  }
}

// 取消操作
abortController.abort();

reactiveUtils (Property Watching)

reactiveUtils(属性监听)

Watch Properties

监听属性

javascript
import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";

// Watch single property
reactiveUtils.watch(
  () => view.scale,
  (scale) => console.log("Scale:", scale)
);

// Watch with initial value
reactiveUtils.watch(
  () => view.extent,
  (extent) => console.log("Extent:", extent),
  { initial: true }
);

// Watch once
reactiveUtils.once(
  () => view.stationary === true
).then(() => {
  console.log("View became stationary");
});

// When condition becomes true
reactiveUtils.when(
  () => layer.loaded,
  () => console.log("Layer loaded")
);
javascript
import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";

// 监听单个属性
reactiveUtils.watch(
  () => view.scale,
  (scale) => console.log("Scale:", scale)
);

// 监听并获取初始值
reactiveUtils.watch(
  () => view.extent,
  (extent) => console.log("Extent:", extent),
  { initial: true }
);

// 监听一次
reactiveUtils.once(
  () => view.stationary === true
).then(() => {
  console.log("View became stationary");
});

// 当条件变为true时执行
reactiveUtils.when(
  () => layer.loaded,
  () => console.log("Layer loaded")
);

Reference Samples

参考示例

  • intro-mapview
    - Basic MapView setup and configuration
  • intro-sceneview
    - Basic SceneView setup for 3D
  • webmap-basic
    - Loading a WebMap from portal
  • watch-for-changes-reactiveutils
    - Reactive property watching with reactiveUtils
  • overview-map
    - Creating an overview/inset map
  • intro-mapview
    - 基础MapView配置与设置
  • intro-sceneview
    - 基础3D SceneView配置
  • webmap-basic
    - 从门户加载WebMap
  • watch-for-changes-reactiveutils
    - 使用reactiveUtils监听属性变化
  • overview-map
    - 创建概览/嵌入地图

Common Pitfalls

常见陷阱

  1. Missing CSS for Core API: The Core API requires
    main.css
    for widgets and popups to render correctly.
    html
    <!-- Anti-pattern: no CSS import -->
    <script type="module">
      import MapView from "@arcgis/core/views/MapView";
      import Map from "@arcgis/core/Map";
      const view = new MapView({ container: "viewDiv", map: new Map({ basemap: "topo-vector" }) });
    </script>
    html
    <!-- Correct: include the CSS -->
    <link rel="stylesheet" href="https://js.arcgis.com/4.34/esri/themes/light/main.css" />
    <script type="module">
      import MapView from "@arcgis/core/views/MapView";
      import Map from "@arcgis/core/Map";
      const view = new MapView({ container: "viewDiv", map: new Map({ basemap: "topo-vector" }) });
    </script>
    Impact: The map itself renders, but widgets (Zoom, Legend, Search) and popups appear unstyled or completely broken. Layouts collapse and controls become unusable.
  2. Not awaiting viewOnReady(): View properties are not available until the view is ready.
    javascript
    // Anti-pattern: accessing view before it is ready
    const mapElement = document.querySelector("arcgis-map");
    const view = mapElement.view; // undefined - view is not ready yet
    view.goTo({ center: [-118, 34] }); // TypeError: Cannot read properties of undefined
    javascript
    // Correct: wait for the view to be ready
    const mapElement = document.querySelector("arcgis-map");
    await mapElement.viewOnReady();
    const view = mapElement.view; // MapView instance, safe to use
    view.goTo({ center: [-118, 34] });
    Impact:
    view
    is
    null
    or
    undefined
    before the component initializes, causing runtime errors on any property access or method call.
  3. Coordinate order: ArcGIS uses
    [longitude, latitude]
    , not
    [latitude, longitude]
    .
    javascript
    // Anti-pattern: lat/lng order (Google Maps convention)
    const view = new MapView({
      center: [34.05, -118.24], // lat first, lng second - WRONG
      zoom: 12
    });
    javascript
    // Correct: lng/lat order (ArcGIS convention)
    const view = new MapView({
      center: [-118.24, 34.05], // lng first, lat second
      zoom: 12
    });
    Impact: The map centers on the wrong location, often in the middle of the ocean or on a different continent, with no error message to indicate the mistake.
  4. Missing viewDiv height: Ensure the container has height:
    css
    html, body, #viewDiv { height: 100%; margin: 0; }
  5. Script type: Use
    type="module"
    for async/await support:
    html
    <script type="module">
      // async/await works here
    </script>
  1. Core API缺失CSS:Core API需要
    main.css
    才能正确渲染组件和弹窗。
    html
    <!-- 错误示例:未引入CSS -->
    <script type="module">
      import MapView from "@arcgis/core/views/MapView";
      import Map from "@arcgis/core/Map";
      const view = new MapView({ container: "viewDiv", map: new Map({ basemap: "topo-vector" }) });
    </script>
    html
    <!-- 正确示例:引入CSS -->
    <link rel="stylesheet" href="https://js.arcgis.com/4.34/esri/themes/light/main.css" />
    <script type="module">
      import MapView from "@arcgis/core/views/MapView";
      import Map from "@arcgis/core/Map";
      const view = new MapView({ container: "viewDiv", map: new Map({ basemap: "topo-vector" }) });
    </script>
    影响:地图本身可以渲染,但组件(缩放、图例、搜索)和弹窗样式错乱或完全无法使用,布局崩溃,控件失效。
  2. 未等待viewOnReady():视图属性在准备完成前无法访问。
    javascript
    // 错误示例:在视图准备完成前访问
    const mapElement = document.querySelector("arcgis-map");
    const view = mapElement.view; // undefined - 视图未准备完成
    view.goTo({ center: [-118, 34] }); // 类型错误:无法读取undefined的属性
    javascript
    // 正确示例:等待视图准备完成
    const mapElement = document.querySelector("arcgis-map");
    await mapElement.viewOnReady();
    const view = mapElement.view; // MapView实例,可安全使用
    view.goTo({ center: [-118, 34] });
    影响
    view
    在组件初始化完成前为
    null
    undefined
    ,导致任何属性访问或方法调用都会触发运行时错误。
  3. 坐标顺序错误:ArcGIS使用
    [经度, 纬度]
    ,而非
    [纬度, 经度]
    javascript
    // 错误示例:纬度在前(Google Maps惯例)
    const view = new MapView({
      center: [34.05, -118.24], // 纬度在前,经度在后 - 错误
      zoom: 12
    });
    javascript
    // 正确示例:经度在前(ArcGIS惯例)
    const view = new MapView({
      center: [-118.24, 34.05], // 经度在前,纬度在后
      zoom: 12
    });
    影响:地图会定位到错误的位置,通常是海洋或其他大陆,且无错误提示说明问题。
  4. viewDiv高度缺失:确保容器设置了高度:
    css
    html, body, #viewDiv { height: 100%; margin: 0; }
  5. 脚本类型错误:使用
    type="module"
    以支持async/await:
    html
    <script type="module">
      // 此处可正常使用async/await
    </script>