arcgis-core-maps
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseArcGIS 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 in HTML
<script src="https://js.arcgis.com/4.34/"></script>
Note: The examples in this skill use Direct ESM imports. For CDN usage, replacewithimport X from "path".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 , , etc. when:
new SimpleRenderer()new Point()- You need instance methods or checks
instanceof - Building shared internal libraries - constructor APIs surface breaking changes at compile time
- You want strong editor discoverability - exposes properties clearly
new SimpleRenderer({ ... }) - 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 property when:
type- 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 - works cleanly in React
layer.renderer = { ... }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 or
as constto maintain type safety with autocastingsatisfies
- 配置类内容使用Autocast(渲染器、符号、弹窗、标签)
- 行为类内容使用显式类(当需要调用方法或进行instanceof检查时)
- **使用或
as const**在Autocast时保持类型安全satisfies
Two Approaches
两种实现方式
1. Map Components (Modern - Recommended)
1. Map Components(现代方式 - 推荐)
Web components approach using and .
<arcgis-map><arcgis-scene>使用和的Web组件方式。
<arcgis-map><arcgis-scene>2. Core API
2. Core API
Traditional JavaScript approach using , , and classes.
MapMapViewSceneView使用、和类的传统JavaScript方式。
MapMapViewSceneViewCDN 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 component is a third view container alongside and , used for displaying video feeds from video services.
arcgis-videoarcgis-maparcgis-scenearcgis-videoarcgis-maparcgis-sceneMap 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:supports the same position slots asarcgis-videoandarcgis-map: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
导航组件
| Component | Purpose |
|---|---|
| Zoom in/out buttons |
| Orientation indicator, click to reset north |
| Return to initial extent |
| Find user's location |
| Switch between pan/rotate modes (3D) |
| Toggle fullscreen mode |
| Display map scale |
| 组件 | 用途 |
|---|---|
| 放大/缩小按钮 |
| 方向指示器,点击可重置为正北方向 |
| 返回初始视图范围 |
| 定位用户当前位置 |
| 在平移/旋转模式间切换(3D场景) |
| 切换全屏模式 |
| 显示地图比例尺 |
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-lefttop-rightbottom-leftbottom-righttop-starttop-endbottom-startbottom-endhtml
<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-lefttop-rightbottom-leftbottom-righttop-starttop-endbottom-startbottom-endView 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 ID | Description |
|---|---|
| Street map |
| Topographic |
| Satellite imagery |
| Satellite with labels |
| Dark gray canvas |
| Light gray canvas |
| OpenStreetMap |
| 3D topographic (SceneView) |
| 底图ID | 描述 |
|---|---|
| 街道地图 |
| 地形地图 |
| 卫星影像 |
| 带标签的卫星影像 |
| 深灰色底图 |
| 浅灰色底图 |
| OpenStreetMap |
| 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
参考示例
- - Basic MapView setup and configuration
intro-mapview - - Basic SceneView setup for 3D
intro-sceneview - - Loading a WebMap from portal
webmap-basic - - Reactive property watching with reactiveUtils
watch-for-changes-reactiveutils - - Creating an overview/inset map
overview-map
- - 基础MapView配置与设置
intro-mapview - - 基础3D SceneView配置
intro-sceneview - - 从门户加载WebMap
webmap-basic - - 使用reactiveUtils监听属性变化
watch-for-changes-reactiveutils - - 创建概览/嵌入地图
overview-map
Common Pitfalls
常见陷阱
-
Missing CSS for Core API: The Core API requiresfor widgets and popups to render correctly.
main.csshtml<!-- 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. -
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 undefinedjavascript// 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:isviewornullbefore the component initializes, causing runtime errors on any property access or method call.undefined -
Coordinate order: ArcGIS uses, not
[longitude, latitude].[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. -
Missing viewDiv height: Ensure the container has height:css
html, body, #viewDiv { height: 100%; margin: 0; } -
Script type: Usefor async/await support:
type="module"html<script type="module"> // async/await works here </script>
-
Core API缺失CSS:Core API需要才能正确渲染组件和弹窗。
main.csshtml<!-- 错误示例:未引入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>影响:地图本身可以渲染,但组件(缩放、图例、搜索)和弹窗样式错乱或完全无法使用,布局崩溃,控件失效。 -
未等待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 -
坐标顺序错误: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 });影响:地图会定位到错误的位置,通常是海洋或其他大陆,且无错误提示说明问题。 -
viewDiv高度缺失:确保容器设置了高度:css
html, body, #viewDiv { height: 100%; margin: 0; } -
脚本类型错误:使用以支持async/await:
type="module"html<script type="module"> // 此处可正常使用async/await </script>