@saschabrunnerch/arcgis-maps-sdk-js-ai-context 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +163 -201
  2. package/bin/cli.js +157 -173
  3. package/contexts/4.34/{claude → skills}/arcgis-3d-advanced/SKILL.md +586 -586
  4. package/contexts/4.34/{claude → skills}/arcgis-advanced-layers/SKILL.md +431 -431
  5. package/contexts/4.34/{claude → skills}/arcgis-analysis-services/SKILL.md +607 -607
  6. package/contexts/4.34/{claude → skills}/arcgis-authentication/SKILL.md +301 -301
  7. package/contexts/4.34/{claude → skills}/arcgis-cim-symbols/SKILL.md +486 -486
  8. package/contexts/4.34/{claude → skills}/arcgis-coordinates-projection/SKILL.md +406 -406
  9. package/contexts/4.34/{claude → skills}/arcgis-core-maps/SKILL.md +739 -739
  10. package/contexts/4.34/{claude → skills}/arcgis-core-utilities/SKILL.md +732 -732
  11. package/contexts/4.34/{claude → skills}/arcgis-custom-rendering/SKILL.md +445 -445
  12. package/contexts/4.34/{claude → skills}/arcgis-editing-advanced/SKILL.md +702 -702
  13. package/contexts/4.34/{claude → skills}/arcgis-feature-effects/SKILL.md +393 -393
  14. package/contexts/4.34/{claude → skills}/arcgis-geometry-operations/SKILL.md +489 -489
  15. package/contexts/4.34/{claude → skills}/arcgis-imagery/SKILL.md +307 -307
  16. package/contexts/4.34/{claude → skills}/arcgis-interaction/SKILL.md +572 -572
  17. package/contexts/4.34/{claude → skills}/arcgis-knowledge-graphs/SKILL.md +582 -582
  18. package/contexts/4.34/{claude → skills}/arcgis-layers/SKILL.md +601 -601
  19. package/contexts/4.34/{claude → skills}/arcgis-map-tools/SKILL.md +668 -668
  20. package/contexts/4.34/{claude → skills}/arcgis-media-layers/SKILL.md +290 -290
  21. package/contexts/4.34/{claude → skills}/arcgis-portal-content/SKILL.md +679 -679
  22. package/contexts/4.34/{claude → skills}/arcgis-scene-effects/SKILL.md +512 -512
  23. package/contexts/4.34/{claude → skills}/arcgis-smart-mapping/SKILL.md +686 -686
  24. package/contexts/4.34/skills/arcgis-starter-app/SKILL.md +273 -0
  25. package/contexts/4.34/skills/arcgis-starter-app-extended/SKILL.md +649 -0
  26. package/contexts/4.34/{claude → skills}/arcgis-tables-forms/SKILL.md +877 -877
  27. package/contexts/4.34/{claude → skills}/arcgis-time-animation/SKILL.md +722 -722
  28. package/contexts/4.34/{claude → skills}/arcgis-utility-networks/SKILL.md +301 -301
  29. package/contexts/4.34/{claude → skills}/arcgis-visualization/SKILL.md +580 -580
  30. package/contexts/4.34/{claude → skills}/arcgis-widgets-ui/SKILL.md +574 -574
  31. package/lib/installer.js +294 -379
  32. package/package.json +45 -45
  33. package/contexts/4.34/copilot/arcgis-3d.instructions.md +0 -267
  34. package/contexts/4.34/copilot/arcgis-analysis.instructions.md +0 -294
  35. package/contexts/4.34/copilot/arcgis-arcade.instructions.md +0 -234
  36. package/contexts/4.34/copilot/arcgis-authentication.instructions.md +0 -187
  37. package/contexts/4.34/copilot/arcgis-cim-symbols.instructions.md +0 -177
  38. package/contexts/4.34/copilot/arcgis-core-maps.instructions.md +0 -246
  39. package/contexts/4.34/copilot/arcgis-core-utilities.instructions.md +0 -247
  40. package/contexts/4.34/copilot/arcgis-editing.instructions.md +0 -262
  41. package/contexts/4.34/copilot/arcgis-geometry.instructions.md +0 -225
  42. package/contexts/4.34/copilot/arcgis-layers.instructions.md +0 -278
  43. package/contexts/4.34/copilot/arcgis-popup-templates.instructions.md +0 -266
  44. package/contexts/4.34/copilot/arcgis-portal-advanced.instructions.md +0 -275
  45. package/contexts/4.34/copilot/arcgis-smart-mapping.instructions.md +0 -184
  46. package/contexts/4.34/copilot/arcgis-time-animation.instructions.md +0 -112
  47. package/contexts/4.34/copilot/arcgis-visualization.instructions.md +0 -321
  48. package/contexts/4.34/copilot/arcgis-widgets-ui.instructions.md +0 -277
  49. /package/contexts/4.34/{claude → skills}/arcgis-arcade/SKILL.md +0 -0
  50. /package/contexts/4.34/{claude → skills}/arcgis-popup-templates/SKILL.md +0 -0
@@ -1,739 +1,739 @@
1
- ---
2
- name: arcgis-core-maps
3
- description: Create 2D and 3D maps using ArcGIS Maps SDK for JavaScript. Use for initializing maps, scenes, views, and navigation. Supports both Map Components (web components) and Core API approaches.
4
- ---
5
-
6
- # ArcGIS Core Maps
7
-
8
- Use this skill when creating 2D maps (MapView) or 3D scenes (SceneView) with the ArcGIS Maps SDK for JavaScript.
9
-
10
- ## Import Patterns
11
-
12
- ### Direct ESM Imports (Recommended for Build Tools)
13
- Use with Vite, webpack, Rollup, or other build tools:
14
- ```javascript
15
- import Map from "@arcgis/core/Map.js";
16
- import MapView from "@arcgis/core/views/MapView.js";
17
- import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
18
- ```
19
- - Tree-shakeable
20
- - Standard JavaScript modules
21
- - Best for production applications
22
-
23
- ### Dynamic Imports (CDN / No Build Tools)
24
- Use with CDN script tags when no build step is available:
25
- ```javascript
26
- const Map = await $arcgis.import("@arcgis/core/Map.js");
27
- const MapView = await $arcgis.import("@arcgis/core/views/MapView.js");
28
-
29
- // Multiple imports
30
- const [FeatureLayer, Graphic] = await $arcgis.import([
31
- "@arcgis/core/layers/FeatureLayer.js",
32
- "@arcgis/core/Graphic.js"
33
- ]);
34
- ```
35
- - Works with Map Components (web components)
36
- - No build step required
37
- - Good for quick prototypes and demos
38
- - Requires `<script src="https://js.arcgis.com/4.34/"></script>` in HTML
39
-
40
- > **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")`.
41
-
42
- ## Autocasting vs Explicit Classes (TypeScript)
43
-
44
- The ArcGIS SDK supports [autocasting](https://developers.arcgis.com/javascript/latest/autocasting/) - passing plain objects instead of class instances. Understanding when to use each approach is important for TypeScript projects.
45
-
46
- ### When to Use Explicit Classes (Non-Autocast)
47
-
48
- Use `new SimpleRenderer()`, `new Point()`, etc. when:
49
-
50
- - **You need instance methods or `instanceof` checks**
51
- - **Building shared internal libraries** - constructor APIs surface breaking changes at compile time
52
- - **You want strong editor discoverability** - `new SimpleRenderer({ ... })` exposes properties clearly
53
- - **You mutate objects incrementally** - long-lived instances are clearer as real classes
54
-
55
- ```typescript
56
- import SimpleRenderer from "@arcgis/core/renderers/SimpleRenderer.js";
57
- import SimpleMarkerSymbol from "@arcgis/core/symbols/SimpleMarkerSymbol.js";
58
-
59
- const renderer = new SimpleRenderer({
60
- symbol: new SimpleMarkerSymbol({
61
- color: [226, 119, 40],
62
- size: 8
63
- })
64
- });
65
- ```
66
-
67
- ### When to Use Autocasting
68
-
69
- Use plain objects with `type` property when:
70
-
71
- - **Configuration-heavy code** - renderers, symbols, popups are usually data, not behavior
72
- - **UI-driven configuration** - React state → plain objects → SDK properties is simpler
73
- - **Serialization and reuse matter** - configs can be stored, diffed, tested, reused
74
- - **Property updates after creation** - `layer.renderer = { ... }` works cleanly in React `useEffect`
75
-
76
- ```typescript
77
- // Use 'as const' or 'satisfies' to keep discriminated unions narrow
78
- const renderer = {
79
- type: "simple",
80
- symbol: {
81
- type: "simple-marker",
82
- color: [226, 119, 40],
83
- size: 8
84
- }
85
- } as const;
86
-
87
- // Or with satisfies for better type inference
88
- import type { SimpleRenderer } from "@arcgis/core/renderers/SimpleRenderer.js";
89
-
90
- const renderer = {
91
- type: "simple",
92
- symbol: {
93
- type: "simple-marker",
94
- color: [226, 119, 40],
95
- size: 8
96
- }
97
- } satisfies __esri.SimpleRendererProperties;
98
- ```
99
-
100
- ### TypeScript Best Practices
101
-
102
- The real TypeScript concern is keeping discriminated unions narrow:
103
-
104
- ```typescript
105
- // ❌ BAD - type widens to string
106
- const symbol = { type: "simple-marker", color: "red" };
107
-
108
- // ✅ GOOD - type stays literal
109
- const symbol = { type: "simple-marker", color: "red" } as const;
110
-
111
- // ✅ GOOD - explicit type annotation
112
- const symbol: __esri.SimpleMarkerSymbolProperties = {
113
- type: "simple-marker",
114
- color: "red"
115
- };
116
- ```
117
-
118
- ### Recommended Default
119
-
120
- - **Autocast for configuration** (renderers, symbols, popups, labels)
121
- - **Explicit classes for behavior** (when you need methods or instanceof)
122
- - **Use `as const` or `satisfies`** to maintain type safety with autocasting
123
-
124
- ## Two Approaches
125
-
126
- ### 1. Map Components (Modern - Recommended)
127
- Web components approach using `<arcgis-map>` and `<arcgis-scene>`.
128
-
129
- ### 2. Core API
130
- Traditional JavaScript approach using `Map`, `MapView`, and `SceneView` classes.
131
-
132
- ## CDN Setup
133
-
134
- ### Map Components Approach
135
- ```html
136
- <!DOCTYPE html>
137
- <html lang="en">
138
- <head>
139
- <meta charset="utf-8" />
140
- <meta name="viewport" content="width=device-width, initial-scale=1" />
141
- <title>ArcGIS Map</title>
142
- <style>
143
- html, body { height: 100%; margin: 0; }
144
- </style>
145
- <!-- Load Calcite components -->
146
- <script type="module" src="https://js.arcgis.com/calcite-components/3.3.3/calcite.esm.js"></script>
147
- <!-- Load ArcGIS Maps SDK -->
148
- <script src="https://js.arcgis.com/4.34/"></script>
149
- <!-- Load Map components -->
150
- <script type="module" src="https://js.arcgis.com/4.34/map-components/"></script>
151
- </head>
152
- <body>
153
- <arcgis-map basemap="topo-vector" center="-118.24,34.05" zoom="12">
154
- <arcgis-zoom slot="top-left"></arcgis-zoom>
155
- </arcgis-map>
156
- </body>
157
- </html>
158
- ```
159
-
160
- ### Core API Approach
161
- ```html
162
- <!DOCTYPE html>
163
- <html lang="en">
164
- <head>
165
- <meta charset="utf-8" />
166
- <meta name="viewport" content="width=device-width, initial-scale=1" />
167
- <title>ArcGIS Map</title>
168
- <style>
169
- html, body, #viewDiv { height: 100%; margin: 0; }
170
- </style>
171
- <!-- REQUIRED: main.css for Core API -->
172
- <link rel="stylesheet" href="https://js.arcgis.com/4.34/esri/themes/light/main.css" />
173
- <script src="https://js.arcgis.com/4.34/"></script>
174
- </head>
175
- <body>
176
- <div id="viewDiv"></div>
177
- <script type="module">
178
- import Map from "@arcgis/core/Map.js";
179
- import MapView from "@arcgis/core/views/MapView.js";
180
-
181
- const map = new Map({ basemap: "topo-vector" });
182
- const view = new MapView({
183
- container: "viewDiv",
184
- map: map,
185
- center: [-118.24, 34.05], // [longitude, latitude]
186
- zoom: 12
187
- });
188
- </script>
189
- </body>
190
- </html>
191
- ```
192
-
193
- ## 2D Maps
194
-
195
- ### Map Components
196
- ```html
197
- <arcgis-map basemap="topo-vector" center="-118.24,34.05" zoom="12">
198
- <arcgis-zoom slot="top-left"></arcgis-zoom>
199
- <arcgis-compass slot="top-left"></arcgis-compass>
200
- <arcgis-home slot="top-left"></arcgis-home>
201
- <arcgis-locate slot="top-left"></arcgis-locate>
202
- </arcgis-map>
203
-
204
- <script type="module">
205
- const mapElement = document.querySelector("arcgis-map");
206
- await mapElement.viewOnReady(); // Wait for view to be ready
207
- const view = mapElement.view; // Access the MapView
208
- const map = mapElement.map; // Access the Map
209
- </script>
210
- ```
211
-
212
- ### Core API
213
- ```javascript
214
- import Map from "@arcgis/core/Map.js";
215
- import MapView from "@arcgis/core/views/MapView.js";
216
-
217
- const map = new Map({ basemap: "streets-vector" });
218
-
219
- const view = new MapView({
220
- container: "viewDiv",
221
- map: map,
222
- center: [-118.24, 34.05],
223
- zoom: 12,
224
- // Optional constraints
225
- constraints: {
226
- minZoom: 5,
227
- maxZoom: 18,
228
- rotationEnabled: false
229
- }
230
- });
231
- ```
232
-
233
- ## 3D Scenes
234
-
235
- ### Map Components
236
- ```html
237
- <arcgis-scene basemap="topo-3d" ground="world-elevation">
238
- <arcgis-zoom slot="top-left"></arcgis-zoom>
239
- <arcgis-navigation-toggle slot="top-left"></arcgis-navigation-toggle>
240
- </arcgis-scene>
241
-
242
- <script type="module">
243
- const sceneElement = document.querySelector("arcgis-scene");
244
- await sceneElement.viewOnReady();
245
- const view = sceneElement.view; // SceneView
246
- </script>
247
- ```
248
-
249
- ### Core API
250
- ```javascript
251
- import Map from "@arcgis/core/Map.js";
252
- import SceneView from "@arcgis/core/views/SceneView.js";
253
-
254
- const map = new Map({
255
- basemap: "topo-3d",
256
- ground: "world-elevation"
257
- });
258
-
259
- const view = new SceneView({
260
- container: "viewDiv",
261
- map: map,
262
- camera: {
263
- position: {
264
- longitude: -118.24,
265
- latitude: 34.05,
266
- z: 25000 // altitude in meters
267
- },
268
- heading: 0, // compass direction
269
- tilt: 45 // 0 = straight down, 90 = horizon
270
- }
271
- });
272
- ```
273
-
274
- ## Loading WebMaps and WebScenes
275
-
276
- ### WebMap (2D)
277
- ```html
278
- <!-- Map Components -->
279
- <arcgis-map item-id="f2e9b762544945f390ca4ac3671cfa72">
280
- <arcgis-zoom slot="top-left"></arcgis-zoom>
281
- </arcgis-map>
282
- ```
283
-
284
- ```javascript
285
- // Core API
286
- import MapView from "@arcgis/core/views/MapView.js";
287
- import WebMap from "@arcgis/core/WebMap.js";
288
-
289
- const webmap = new WebMap({
290
- portalItem: { id: "f2e9b762544945f390ca4ac3671cfa72" }
291
- });
292
-
293
- const view = new MapView({
294
- map: webmap,
295
- container: "viewDiv"
296
- });
297
- ```
298
-
299
- ### WebScene (3D)
300
- ```html
301
- <!-- Map Components -->
302
- <arcgis-scene item-id="YOUR_WEBSCENE_ID">
303
- <arcgis-zoom slot="top-left"></arcgis-zoom>
304
- </arcgis-scene>
305
- ```
306
-
307
- ```javascript
308
- // Core API
309
- import SceneView from "@arcgis/core/views/SceneView.js";
310
- import WebScene from "@arcgis/core/WebScene.js";
311
-
312
- const webscene = new WebScene({
313
- portalItem: { id: "YOUR_WEBSCENE_ID" }
314
- });
315
-
316
- const view = new SceneView({
317
- map: webscene,
318
- container: "viewDiv"
319
- });
320
- ```
321
-
322
- ## Navigation Components
323
-
324
- | Component | Purpose |
325
- |-----------|---------|
326
- | `arcgis-zoom` | Zoom in/out buttons |
327
- | `arcgis-compass` | Orientation indicator, click to reset north |
328
- | `arcgis-home` | Return to initial extent |
329
- | `arcgis-locate` | Find user's location |
330
- | `arcgis-navigation-toggle` | Switch between pan/rotate modes (3D) |
331
- | `arcgis-fullscreen` | Toggle fullscreen mode |
332
- | `arcgis-scale-bar` | Display map scale |
333
-
334
- ### Slot Positions
335
- ```html
336
- <arcgis-map basemap="streets-vector">
337
- <arcgis-zoom slot="top-left"></arcgis-zoom>
338
- <arcgis-home slot="top-left"></arcgis-home>
339
- <arcgis-search slot="top-right"></arcgis-search>
340
- <arcgis-legend slot="bottom-left"></arcgis-legend>
341
- <arcgis-scale-bar slot="bottom-right"></arcgis-scale-bar>
342
- </arcgis-map>
343
- ```
344
-
345
- Available slots: `top-left`, `top-right`, `bottom-left`, `bottom-right`, `manual`
346
-
347
- ## View Configuration
348
-
349
- ### Setting Initial Extent
350
- ```javascript
351
- // By center and zoom
352
- const view = new MapView({
353
- container: "viewDiv",
354
- map: map,
355
- center: [-118.24, 34.05],
356
- zoom: 12
357
- });
358
-
359
- // By scale
360
- const view = new MapView({
361
- container: "viewDiv",
362
- map: map,
363
- center: [-118.24, 34.05],
364
- scale: 50000 // 1:50,000
365
- });
366
-
367
- // By extent
368
- const view = new MapView({
369
- container: "viewDiv",
370
- map: map,
371
- extent: {
372
- xmin: -118.5,
373
- ymin: 33.8,
374
- xmax: -117.9,
375
- ymax: 34.3,
376
- spatialReference: { wkid: 4326 }
377
- }
378
- });
379
- ```
380
-
381
- ### Programmatic Navigation
382
- ```javascript
383
- // Go to location
384
- await view.goTo({
385
- center: [-118.24, 34.05],
386
- zoom: 15
387
- });
388
-
389
- // Animated navigation
390
- await view.goTo(
391
- { center: [-118.24, 34.05], zoom: 15 },
392
- { duration: 2000, easing: "ease-in-out" }
393
- );
394
-
395
- // Go to extent
396
- await view.goTo(layer.fullExtent);
397
-
398
- // Go to features
399
- await view.goTo(featureSet.features);
400
- ```
401
-
402
- ### View Constraints
403
- ```javascript
404
- // Constrain zoom levels
405
- view.constraints = {
406
- minZoom: 5,
407
- maxZoom: 18
408
- };
409
-
410
- // Constrain to area
411
- view.constraints = {
412
- geometry: layer.fullExtent,
413
- minScale: 500000
414
- };
415
-
416
- // Disable rotation
417
- view.constraints = {
418
- rotationEnabled: false
419
- };
420
- ```
421
-
422
- ## Event Handling
423
-
424
- ```javascript
425
- // View ready
426
- view.when(() => {
427
- console.log("View is ready");
428
- });
429
-
430
- // Click event
431
- view.on("click", (event) => {
432
- console.log("Clicked at:", event.mapPoint);
433
- });
434
-
435
- // Pointer move
436
- view.on("pointer-move", (event) => {
437
- const point = view.toMap(event);
438
- console.log("Mouse at:", point.longitude, point.latitude);
439
- });
440
-
441
- // Extent change
442
- view.watch("extent", (extent) => {
443
- console.log("Extent changed:", extent);
444
- });
445
-
446
- // Stationary (after pan/zoom completes)
447
- view.watch("stationary", (isStationary) => {
448
- if (isStationary) {
449
- console.log("Navigation complete");
450
- }
451
- });
452
- ```
453
-
454
- ## Module Imports
455
-
456
- ```javascript
457
- // Single import
458
- import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
459
-
460
- // Multiple imports
461
- import Map from "@arcgis/core/Map.js";
462
- import MapView from "@arcgis/core/views/MapView.js";
463
- import Graphic from "@arcgis/core/Graphic.js";
464
- ```
465
-
466
- ## Common Basemaps
467
-
468
- | Basemap ID | Description |
469
- |------------|-------------|
470
- | `streets-vector` | Street map |
471
- | `topo-vector` | Topographic |
472
- | `satellite` | Satellite imagery |
473
- | `hybrid` | Satellite with labels |
474
- | `dark-gray-vector` | Dark gray canvas |
475
- | `gray-vector` | Light gray canvas |
476
- | `osm` | OpenStreetMap |
477
- | `topo-3d` | 3D topographic (SceneView) |
478
-
479
- ## esriRequest (HTTP Requests)
480
-
481
- ### Basic Request
482
- ```javascript
483
- import esriRequest from "@arcgis/core/request.js";
484
-
485
- // GET request with JSON response
486
- const response = await esriRequest(url, {
487
- query: { f: "json" },
488
- responseType: "json"
489
- });
490
-
491
- console.log("Status:", response.httpStatus);
492
- console.log("Data:", response.data);
493
- ```
494
-
495
- ### Request with Options
496
- ```javascript
497
- const response = await esriRequest(url, {
498
- query: {
499
- f: "json",
500
- param1: "value1"
501
- },
502
- responseType: "json", // "json", "text", "array-buffer", "blob", "image"
503
- method: "post", // "auto", "get", "post"
504
- body: formData, // For POST requests
505
- timeout: 30000, // Timeout in ms
506
- headers: {
507
- "X-Custom-Header": "value"
508
- }
509
- });
510
- ```
511
-
512
- ### Download Binary Data
513
- ```javascript
514
- // Image response
515
- const imageResponse = await esriRequest(imageUrl, {
516
- responseType: "image"
517
- });
518
- const imageElement = imageResponse.data;
519
-
520
- // Binary data
521
- const binaryResponse = await esriRequest(fileUrl, {
522
- responseType: "array-buffer"
523
- });
524
- const arrayBuffer = binaryResponse.data;
525
- ```
526
-
527
- ## Planetary Visualization (Mars)
528
-
529
- ### Mars Scene
530
- ```html
531
- <arcgis-scene>
532
- <arcgis-zoom slot="top-left"></arcgis-zoom>
533
- <arcgis-navigation-toggle slot="top-left"></arcgis-navigation-toggle>
534
- </arcgis-scene>
535
-
536
- <script type="module">
537
- import ElevationLayer from "@arcgis/core/layers/ElevationLayer.js";
538
- import TileLayer from "@arcgis/core/layers/TileLayer.js";
539
- import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
540
-
541
- const viewElement = document.querySelector("arcgis-scene");
542
-
543
- // Set Mars spatial reference
544
- viewElement.spatialReference = { wkid: 104971 }; // Mars 2000
545
-
546
- // Configure camera for Mars
547
- viewElement.camera = {
548
- position: {
549
- x: 27.63423,
550
- y: -6.34466,
551
- z: 1281525,
552
- spatialReference: { wkid: 104971 }
553
- },
554
- heading: 332,
555
- tilt: 37
556
- };
557
-
558
- await viewElement.viewOnReady();
559
-
560
- // Mars elevation
561
- const marsElevation = new ElevationLayer({
562
- url: "https://astro.arcgis.com/arcgis/rest/services/OnMars/MDEM200M/ImageServer"
563
- });
564
- viewElement.ground = { layers: [marsElevation] };
565
-
566
- // Mars imagery
567
- const marsImagery = new TileLayer({
568
- url: "https://astro.arcgis.com/arcgis/rest/services/OnMars/MDIM/MapServer",
569
- title: "Mars Imagery"
570
- });
571
- viewElement.map.add(marsImagery);
572
- </script>
573
- ```
574
-
575
- ## Overview Map (Synchronized Views)
576
-
577
- ### Overview Map with Scene
578
- ```html
579
- <arcgis-scene basemap="hybrid" ground="world-elevation">
580
- <arcgis-zoom slot="top-left"></arcgis-zoom>
581
- <!-- Embed overview map inside scene -->
582
- <arcgis-map basemap="topo-vector" id="overviewDiv" slot="top-right"></arcgis-map>
583
- </arcgis-scene>
584
-
585
- <style>
586
- #overviewDiv { width: 300px; height: 200px; border: 1px solid black; }
587
- </style>
588
-
589
- <script type="module">
590
- import Graphic from "@arcgis/core/Graphic.js";
591
- import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";
592
-
593
- const sceneElement = document.querySelector("arcgis-scene");
594
- const overviewElement = document.querySelector("arcgis-map");
595
-
596
- await sceneElement.viewOnReady();
597
- await overviewElement.viewOnReady();
598
-
599
- // Disable rotation on overview
600
- overviewElement.constraints.rotationEnabled = false;
601
- overviewElement.view.ui.components = [];
602
-
603
- // Add visible area graphic
604
- const visibleAreaGraphic = new Graphic({
605
- symbol: {
606
- type: "simple-fill",
607
- color: [0, 0, 0, 0.5],
608
- outline: null
609
- }
610
- });
611
- overviewElement.graphics.add(visibleAreaGraphic);
612
-
613
- // Sync overview with main scene
614
- reactiveUtils.watch(
615
- () => sceneElement.visibleArea,
616
- async (visibleArea) => {
617
- visibleAreaGraphic.geometry = visibleArea;
618
- await overviewElement.goTo(visibleArea);
619
- },
620
- { initial: true }
621
- );
622
- </script>
623
- ```
624
-
625
- ## promiseUtils (Async Utilities)
626
-
627
- ### Debounce
628
- ```javascript
629
- import promiseUtils from "@arcgis/core/core/promiseUtils.js";
630
-
631
- // Create debounced function
632
- const debouncedUpdate = promiseUtils.debounce(async () => {
633
- // This only runs after 300ms of no calls
634
- await updateFeatures();
635
- });
636
-
637
- view.on("pointer-move", () => {
638
- debouncedUpdate();
639
- });
640
- ```
641
-
642
- ### Abort Error Handling
643
- ```javascript
644
- import promiseUtils from "@arcgis/core/core/promiseUtils.js";
645
-
646
- const abortController = new AbortController();
647
-
648
- try {
649
- await someAsyncOperation({ signal: abortController.signal });
650
- } catch (error) {
651
- if (promiseUtils.isAbortError(error)) {
652
- // Operation was intentionally cancelled
653
- console.log("Operation cancelled");
654
- } else {
655
- // Real error
656
- throw error;
657
- }
658
- }
659
-
660
- // Cancel the operation
661
- abortController.abort();
662
- ```
663
-
664
- ### Create Resolver
665
- ```javascript
666
- import promiseUtils from "@arcgis/core/core/promiseUtils.js";
667
-
668
- // Create a promise that can be resolved/rejected externally
669
- const { promise, resolve, reject } = promiseUtils.createResolver();
670
-
671
- // Later, resolve or reject
672
- resolve(result);
673
- // or
674
- reject(error);
675
-
676
- // Use the promise
677
- const result = await promise;
678
- ```
679
-
680
- ## reactiveUtils (Property Watching)
681
-
682
- ### Watch Properties
683
- ```javascript
684
- import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";
685
-
686
- // Watch single property
687
- reactiveUtils.watch(
688
- () => view.scale,
689
- (scale) => console.log("Scale:", scale)
690
- );
691
-
692
- // Watch with initial value
693
- reactiveUtils.watch(
694
- () => view.extent,
695
- (extent) => console.log("Extent:", extent),
696
- { initial: true }
697
- );
698
-
699
- // Watch once
700
- reactiveUtils.once(
701
- () => view.stationary === true
702
- ).then(() => {
703
- console.log("View became stationary");
704
- });
705
-
706
- // When condition becomes true
707
- reactiveUtils.when(
708
- () => layer.loaded,
709
- () => console.log("Layer loaded")
710
- );
711
- ```
712
-
713
- ## Common Pitfalls
714
-
715
- 1. **Missing CSS for Core API**: The Core API requires `main.css`:
716
- ```html
717
- <link rel="stylesheet" href="https://js.arcgis.com/4.34/esri/themes/light/main.css" />
718
- ```
719
-
720
- 2. **Not awaiting viewOnReady()**: Always wait for the view before accessing properties:
721
- ```javascript
722
- await mapElement.viewOnReady();
723
- const view = mapElement.view; // Safe to access now
724
- ```
725
-
726
- 3. **Coordinate order**: ArcGIS uses `[longitude, latitude]`, not `[latitude, longitude]`
727
-
728
- 4. **Missing viewDiv height**: Ensure the container has height:
729
- ```css
730
- html, body, #viewDiv { height: 100%; margin: 0; }
731
- ```
732
-
733
- 5. **Script type**: Use `type="module"` for async/await support:
734
- ```html
735
- <script type="module">
736
- // async/await works here
737
- </script>
738
- ```
739
-
1
+ ---
2
+ name: arcgis-core-maps
3
+ description: Create 2D and 3D maps using ArcGIS Maps SDK for JavaScript. Use for initializing maps, scenes, views, and navigation. Supports both Map Components (web components) and Core API approaches.
4
+ ---
5
+
6
+ # ArcGIS Core Maps
7
+
8
+ Use this skill when creating 2D maps (MapView) or 3D scenes (SceneView) with the ArcGIS Maps SDK for JavaScript.
9
+
10
+ ## Import Patterns
11
+
12
+ ### Direct ESM Imports (Recommended for Build Tools)
13
+ Use with Vite, webpack, Rollup, or other build tools:
14
+ ```javascript
15
+ import Map from "@arcgis/core/Map.js";
16
+ import MapView from "@arcgis/core/views/MapView.js";
17
+ import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
18
+ ```
19
+ - Tree-shakeable
20
+ - Standard JavaScript modules
21
+ - Best for production applications
22
+
23
+ ### Dynamic Imports (CDN / No Build Tools)
24
+ Use with CDN script tags when no build step is available:
25
+ ```javascript
26
+ const Map = await $arcgis.import("@arcgis/core/Map.js");
27
+ const MapView = await $arcgis.import("@arcgis/core/views/MapView.js");
28
+
29
+ // Multiple imports
30
+ const [FeatureLayer, Graphic] = await $arcgis.import([
31
+ "@arcgis/core/layers/FeatureLayer.js",
32
+ "@arcgis/core/Graphic.js"
33
+ ]);
34
+ ```
35
+ - Works with Map Components (web components)
36
+ - No build step required
37
+ - Good for quick prototypes and demos
38
+ - Requires `<script src="https://js.arcgis.com/4.34/"></script>` in HTML
39
+
40
+ > **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")`.
41
+
42
+ ## Autocasting vs Explicit Classes (TypeScript)
43
+
44
+ The ArcGIS SDK supports [autocasting](https://developers.arcgis.com/javascript/latest/autocasting/) - passing plain objects instead of class instances. Understanding when to use each approach is important for TypeScript projects.
45
+
46
+ ### When to Use Explicit Classes (Non-Autocast)
47
+
48
+ Use `new SimpleRenderer()`, `new Point()`, etc. when:
49
+
50
+ - **You need instance methods or `instanceof` checks**
51
+ - **Building shared internal libraries** - constructor APIs surface breaking changes at compile time
52
+ - **You want strong editor discoverability** - `new SimpleRenderer({ ... })` exposes properties clearly
53
+ - **You mutate objects incrementally** - long-lived instances are clearer as real classes
54
+
55
+ ```typescript
56
+ import SimpleRenderer from "@arcgis/core/renderers/SimpleRenderer.js";
57
+ import SimpleMarkerSymbol from "@arcgis/core/symbols/SimpleMarkerSymbol.js";
58
+
59
+ const renderer = new SimpleRenderer({
60
+ symbol: new SimpleMarkerSymbol({
61
+ color: [226, 119, 40],
62
+ size: 8
63
+ })
64
+ });
65
+ ```
66
+
67
+ ### When to Use Autocasting
68
+
69
+ Use plain objects with `type` property when:
70
+
71
+ - **Configuration-heavy code** - renderers, symbols, popups are usually data, not behavior
72
+ - **UI-driven configuration** - React state → plain objects → SDK properties is simpler
73
+ - **Serialization and reuse matter** - configs can be stored, diffed, tested, reused
74
+ - **Property updates after creation** - `layer.renderer = { ... }` works cleanly in React `useEffect`
75
+
76
+ ```typescript
77
+ // Use 'as const' or 'satisfies' to keep discriminated unions narrow
78
+ const renderer = {
79
+ type: "simple",
80
+ symbol: {
81
+ type: "simple-marker",
82
+ color: [226, 119, 40],
83
+ size: 8
84
+ }
85
+ } as const;
86
+
87
+ // Or with satisfies for better type inference
88
+ import type { SimpleRenderer } from "@arcgis/core/renderers/SimpleRenderer.js";
89
+
90
+ const renderer = {
91
+ type: "simple",
92
+ symbol: {
93
+ type: "simple-marker",
94
+ color: [226, 119, 40],
95
+ size: 8
96
+ }
97
+ } satisfies __esri.SimpleRendererProperties;
98
+ ```
99
+
100
+ ### TypeScript Best Practices
101
+
102
+ The real TypeScript concern is keeping discriminated unions narrow:
103
+
104
+ ```typescript
105
+ // ❌ BAD - type widens to string
106
+ const symbol = { type: "simple-marker", color: "red" };
107
+
108
+ // ✅ GOOD - type stays literal
109
+ const symbol = { type: "simple-marker", color: "red" } as const;
110
+
111
+ // ✅ GOOD - explicit type annotation
112
+ const symbol: __esri.SimpleMarkerSymbolProperties = {
113
+ type: "simple-marker",
114
+ color: "red"
115
+ };
116
+ ```
117
+
118
+ ### Recommended Default
119
+
120
+ - **Autocast for configuration** (renderers, symbols, popups, labels)
121
+ - **Explicit classes for behavior** (when you need methods or instanceof)
122
+ - **Use `as const` or `satisfies`** to maintain type safety with autocasting
123
+
124
+ ## Two Approaches
125
+
126
+ ### 1. Map Components (Modern - Recommended)
127
+ Web components approach using `<arcgis-map>` and `<arcgis-scene>`.
128
+
129
+ ### 2. Core API
130
+ Traditional JavaScript approach using `Map`, `MapView`, and `SceneView` classes.
131
+
132
+ ## CDN Setup
133
+
134
+ ### Map Components Approach
135
+ ```html
136
+ <!DOCTYPE html>
137
+ <html lang="en">
138
+ <head>
139
+ <meta charset="utf-8" />
140
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
141
+ <title>ArcGIS Map</title>
142
+ <style>
143
+ html, body { height: 100%; margin: 0; }
144
+ </style>
145
+ <!-- Load Calcite components -->
146
+ <script type="module" src="https://js.arcgis.com/calcite-components/3.3.3/calcite.esm.js"></script>
147
+ <!-- Load ArcGIS Maps SDK -->
148
+ <script src="https://js.arcgis.com/4.34/"></script>
149
+ <!-- Load Map components -->
150
+ <script type="module" src="https://js.arcgis.com/4.34/map-components/"></script>
151
+ </head>
152
+ <body>
153
+ <arcgis-map basemap="topo-vector" center="-118.24,34.05" zoom="12">
154
+ <arcgis-zoom slot="top-left"></arcgis-zoom>
155
+ </arcgis-map>
156
+ </body>
157
+ </html>
158
+ ```
159
+
160
+ ### Core API Approach
161
+ ```html
162
+ <!DOCTYPE html>
163
+ <html lang="en">
164
+ <head>
165
+ <meta charset="utf-8" />
166
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
167
+ <title>ArcGIS Map</title>
168
+ <style>
169
+ html, body, #viewDiv { height: 100%; margin: 0; }
170
+ </style>
171
+ <!-- REQUIRED: main.css for Core API -->
172
+ <link rel="stylesheet" href="https://js.arcgis.com/4.34/esri/themes/light/main.css" />
173
+ <script src="https://js.arcgis.com/4.34/"></script>
174
+ </head>
175
+ <body>
176
+ <div id="viewDiv"></div>
177
+ <script type="module">
178
+ import Map from "@arcgis/core/Map.js";
179
+ import MapView from "@arcgis/core/views/MapView.js";
180
+
181
+ const map = new Map({ basemap: "topo-vector" });
182
+ const view = new MapView({
183
+ container: "viewDiv",
184
+ map: map,
185
+ center: [-118.24, 34.05], // [longitude, latitude]
186
+ zoom: 12
187
+ });
188
+ </script>
189
+ </body>
190
+ </html>
191
+ ```
192
+
193
+ ## 2D Maps
194
+
195
+ ### Map Components
196
+ ```html
197
+ <arcgis-map basemap="topo-vector" center="-118.24,34.05" zoom="12">
198
+ <arcgis-zoom slot="top-left"></arcgis-zoom>
199
+ <arcgis-compass slot="top-left"></arcgis-compass>
200
+ <arcgis-home slot="top-left"></arcgis-home>
201
+ <arcgis-locate slot="top-left"></arcgis-locate>
202
+ </arcgis-map>
203
+
204
+ <script type="module">
205
+ const mapElement = document.querySelector("arcgis-map");
206
+ await mapElement.viewOnReady(); // Wait for view to be ready
207
+ const view = mapElement.view; // Access the MapView
208
+ const map = mapElement.map; // Access the Map
209
+ </script>
210
+ ```
211
+
212
+ ### Core API
213
+ ```javascript
214
+ import Map from "@arcgis/core/Map.js";
215
+ import MapView from "@arcgis/core/views/MapView.js";
216
+
217
+ const map = new Map({ basemap: "streets-vector" });
218
+
219
+ const view = new MapView({
220
+ container: "viewDiv",
221
+ map: map,
222
+ center: [-118.24, 34.05],
223
+ zoom: 12,
224
+ // Optional constraints
225
+ constraints: {
226
+ minZoom: 5,
227
+ maxZoom: 18,
228
+ rotationEnabled: false
229
+ }
230
+ });
231
+ ```
232
+
233
+ ## 3D Scenes
234
+
235
+ ### Map Components
236
+ ```html
237
+ <arcgis-scene basemap="topo-3d" ground="world-elevation">
238
+ <arcgis-zoom slot="top-left"></arcgis-zoom>
239
+ <arcgis-navigation-toggle slot="top-left"></arcgis-navigation-toggle>
240
+ </arcgis-scene>
241
+
242
+ <script type="module">
243
+ const sceneElement = document.querySelector("arcgis-scene");
244
+ await sceneElement.viewOnReady();
245
+ const view = sceneElement.view; // SceneView
246
+ </script>
247
+ ```
248
+
249
+ ### Core API
250
+ ```javascript
251
+ import Map from "@arcgis/core/Map.js";
252
+ import SceneView from "@arcgis/core/views/SceneView.js";
253
+
254
+ const map = new Map({
255
+ basemap: "topo-3d",
256
+ ground: "world-elevation"
257
+ });
258
+
259
+ const view = new SceneView({
260
+ container: "viewDiv",
261
+ map: map,
262
+ camera: {
263
+ position: {
264
+ longitude: -118.24,
265
+ latitude: 34.05,
266
+ z: 25000 // altitude in meters
267
+ },
268
+ heading: 0, // compass direction
269
+ tilt: 45 // 0 = straight down, 90 = horizon
270
+ }
271
+ });
272
+ ```
273
+
274
+ ## Loading WebMaps and WebScenes
275
+
276
+ ### WebMap (2D)
277
+ ```html
278
+ <!-- Map Components -->
279
+ <arcgis-map item-id="f2e9b762544945f390ca4ac3671cfa72">
280
+ <arcgis-zoom slot="top-left"></arcgis-zoom>
281
+ </arcgis-map>
282
+ ```
283
+
284
+ ```javascript
285
+ // Core API
286
+ import MapView from "@arcgis/core/views/MapView.js";
287
+ import WebMap from "@arcgis/core/WebMap.js";
288
+
289
+ const webmap = new WebMap({
290
+ portalItem: { id: "f2e9b762544945f390ca4ac3671cfa72" }
291
+ });
292
+
293
+ const view = new MapView({
294
+ map: webmap,
295
+ container: "viewDiv"
296
+ });
297
+ ```
298
+
299
+ ### WebScene (3D)
300
+ ```html
301
+ <!-- Map Components -->
302
+ <arcgis-scene item-id="YOUR_WEBSCENE_ID">
303
+ <arcgis-zoom slot="top-left"></arcgis-zoom>
304
+ </arcgis-scene>
305
+ ```
306
+
307
+ ```javascript
308
+ // Core API
309
+ import SceneView from "@arcgis/core/views/SceneView.js";
310
+ import WebScene from "@arcgis/core/WebScene.js";
311
+
312
+ const webscene = new WebScene({
313
+ portalItem: { id: "YOUR_WEBSCENE_ID" }
314
+ });
315
+
316
+ const view = new SceneView({
317
+ map: webscene,
318
+ container: "viewDiv"
319
+ });
320
+ ```
321
+
322
+ ## Navigation Components
323
+
324
+ | Component | Purpose |
325
+ |-----------|---------|
326
+ | `arcgis-zoom` | Zoom in/out buttons |
327
+ | `arcgis-compass` | Orientation indicator, click to reset north |
328
+ | `arcgis-home` | Return to initial extent |
329
+ | `arcgis-locate` | Find user's location |
330
+ | `arcgis-navigation-toggle` | Switch between pan/rotate modes (3D) |
331
+ | `arcgis-fullscreen` | Toggle fullscreen mode |
332
+ | `arcgis-scale-bar` | Display map scale |
333
+
334
+ ### Slot Positions
335
+ ```html
336
+ <arcgis-map basemap="streets-vector">
337
+ <arcgis-zoom slot="top-left"></arcgis-zoom>
338
+ <arcgis-home slot="top-left"></arcgis-home>
339
+ <arcgis-search slot="top-right"></arcgis-search>
340
+ <arcgis-legend slot="bottom-left"></arcgis-legend>
341
+ <arcgis-scale-bar slot="bottom-right"></arcgis-scale-bar>
342
+ </arcgis-map>
343
+ ```
344
+
345
+ Available slots: `top-left`, `top-right`, `bottom-left`, `bottom-right`, `manual`
346
+
347
+ ## View Configuration
348
+
349
+ ### Setting Initial Extent
350
+ ```javascript
351
+ // By center and zoom
352
+ const view = new MapView({
353
+ container: "viewDiv",
354
+ map: map,
355
+ center: [-118.24, 34.05],
356
+ zoom: 12
357
+ });
358
+
359
+ // By scale
360
+ const view = new MapView({
361
+ container: "viewDiv",
362
+ map: map,
363
+ center: [-118.24, 34.05],
364
+ scale: 50000 // 1:50,000
365
+ });
366
+
367
+ // By extent
368
+ const view = new MapView({
369
+ container: "viewDiv",
370
+ map: map,
371
+ extent: {
372
+ xmin: -118.5,
373
+ ymin: 33.8,
374
+ xmax: -117.9,
375
+ ymax: 34.3,
376
+ spatialReference: { wkid: 4326 }
377
+ }
378
+ });
379
+ ```
380
+
381
+ ### Programmatic Navigation
382
+ ```javascript
383
+ // Go to location
384
+ await view.goTo({
385
+ center: [-118.24, 34.05],
386
+ zoom: 15
387
+ });
388
+
389
+ // Animated navigation
390
+ await view.goTo(
391
+ { center: [-118.24, 34.05], zoom: 15 },
392
+ { duration: 2000, easing: "ease-in-out" }
393
+ );
394
+
395
+ // Go to extent
396
+ await view.goTo(layer.fullExtent);
397
+
398
+ // Go to features
399
+ await view.goTo(featureSet.features);
400
+ ```
401
+
402
+ ### View Constraints
403
+ ```javascript
404
+ // Constrain zoom levels
405
+ view.constraints = {
406
+ minZoom: 5,
407
+ maxZoom: 18
408
+ };
409
+
410
+ // Constrain to area
411
+ view.constraints = {
412
+ geometry: layer.fullExtent,
413
+ minScale: 500000
414
+ };
415
+
416
+ // Disable rotation
417
+ view.constraints = {
418
+ rotationEnabled: false
419
+ };
420
+ ```
421
+
422
+ ## Event Handling
423
+
424
+ ```javascript
425
+ // View ready
426
+ view.when(() => {
427
+ console.log("View is ready");
428
+ });
429
+
430
+ // Click event
431
+ view.on("click", (event) => {
432
+ console.log("Clicked at:", event.mapPoint);
433
+ });
434
+
435
+ // Pointer move
436
+ view.on("pointer-move", (event) => {
437
+ const point = view.toMap(event);
438
+ console.log("Mouse at:", point.longitude, point.latitude);
439
+ });
440
+
441
+ // Extent change
442
+ view.watch("extent", (extent) => {
443
+ console.log("Extent changed:", extent);
444
+ });
445
+
446
+ // Stationary (after pan/zoom completes)
447
+ view.watch("stationary", (isStationary) => {
448
+ if (isStationary) {
449
+ console.log("Navigation complete");
450
+ }
451
+ });
452
+ ```
453
+
454
+ ## Module Imports
455
+
456
+ ```javascript
457
+ // Single import
458
+ import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
459
+
460
+ // Multiple imports
461
+ import Map from "@arcgis/core/Map.js";
462
+ import MapView from "@arcgis/core/views/MapView.js";
463
+ import Graphic from "@arcgis/core/Graphic.js";
464
+ ```
465
+
466
+ ## Common Basemaps
467
+
468
+ | Basemap ID | Description |
469
+ |------------|-------------|
470
+ | `streets-vector` | Street map |
471
+ | `topo-vector` | Topographic |
472
+ | `satellite` | Satellite imagery |
473
+ | `hybrid` | Satellite with labels |
474
+ | `dark-gray-vector` | Dark gray canvas |
475
+ | `gray-vector` | Light gray canvas |
476
+ | `osm` | OpenStreetMap |
477
+ | `topo-3d` | 3D topographic (SceneView) |
478
+
479
+ ## esriRequest (HTTP Requests)
480
+
481
+ ### Basic Request
482
+ ```javascript
483
+ import esriRequest from "@arcgis/core/request.js";
484
+
485
+ // GET request with JSON response
486
+ const response = await esriRequest(url, {
487
+ query: { f: "json" },
488
+ responseType: "json"
489
+ });
490
+
491
+ console.log("Status:", response.httpStatus);
492
+ console.log("Data:", response.data);
493
+ ```
494
+
495
+ ### Request with Options
496
+ ```javascript
497
+ const response = await esriRequest(url, {
498
+ query: {
499
+ f: "json",
500
+ param1: "value1"
501
+ },
502
+ responseType: "json", // "json", "text", "array-buffer", "blob", "image"
503
+ method: "post", // "auto", "get", "post"
504
+ body: formData, // For POST requests
505
+ timeout: 30000, // Timeout in ms
506
+ headers: {
507
+ "X-Custom-Header": "value"
508
+ }
509
+ });
510
+ ```
511
+
512
+ ### Download Binary Data
513
+ ```javascript
514
+ // Image response
515
+ const imageResponse = await esriRequest(imageUrl, {
516
+ responseType: "image"
517
+ });
518
+ const imageElement = imageResponse.data;
519
+
520
+ // Binary data
521
+ const binaryResponse = await esriRequest(fileUrl, {
522
+ responseType: "array-buffer"
523
+ });
524
+ const arrayBuffer = binaryResponse.data;
525
+ ```
526
+
527
+ ## Planetary Visualization (Mars)
528
+
529
+ ### Mars Scene
530
+ ```html
531
+ <arcgis-scene>
532
+ <arcgis-zoom slot="top-left"></arcgis-zoom>
533
+ <arcgis-navigation-toggle slot="top-left"></arcgis-navigation-toggle>
534
+ </arcgis-scene>
535
+
536
+ <script type="module">
537
+ import ElevationLayer from "@arcgis/core/layers/ElevationLayer.js";
538
+ import TileLayer from "@arcgis/core/layers/TileLayer.js";
539
+ import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
540
+
541
+ const viewElement = document.querySelector("arcgis-scene");
542
+
543
+ // Set Mars spatial reference
544
+ viewElement.spatialReference = { wkid: 104971 }; // Mars 2000
545
+
546
+ // Configure camera for Mars
547
+ viewElement.camera = {
548
+ position: {
549
+ x: 27.63423,
550
+ y: -6.34466,
551
+ z: 1281525,
552
+ spatialReference: { wkid: 104971 }
553
+ },
554
+ heading: 332,
555
+ tilt: 37
556
+ };
557
+
558
+ await viewElement.viewOnReady();
559
+
560
+ // Mars elevation
561
+ const marsElevation = new ElevationLayer({
562
+ url: "https://astro.arcgis.com/arcgis/rest/services/OnMars/MDEM200M/ImageServer"
563
+ });
564
+ viewElement.ground = { layers: [marsElevation] };
565
+
566
+ // Mars imagery
567
+ const marsImagery = new TileLayer({
568
+ url: "https://astro.arcgis.com/arcgis/rest/services/OnMars/MDIM/MapServer",
569
+ title: "Mars Imagery"
570
+ });
571
+ viewElement.map.add(marsImagery);
572
+ </script>
573
+ ```
574
+
575
+ ## Overview Map (Synchronized Views)
576
+
577
+ ### Overview Map with Scene
578
+ ```html
579
+ <arcgis-scene basemap="hybrid" ground="world-elevation">
580
+ <arcgis-zoom slot="top-left"></arcgis-zoom>
581
+ <!-- Embed overview map inside scene -->
582
+ <arcgis-map basemap="topo-vector" id="overviewDiv" slot="top-right"></arcgis-map>
583
+ </arcgis-scene>
584
+
585
+ <style>
586
+ #overviewDiv { width: 300px; height: 200px; border: 1px solid black; }
587
+ </style>
588
+
589
+ <script type="module">
590
+ import Graphic from "@arcgis/core/Graphic.js";
591
+ import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";
592
+
593
+ const sceneElement = document.querySelector("arcgis-scene");
594
+ const overviewElement = document.querySelector("arcgis-map");
595
+
596
+ await sceneElement.viewOnReady();
597
+ await overviewElement.viewOnReady();
598
+
599
+ // Disable rotation on overview
600
+ overviewElement.constraints.rotationEnabled = false;
601
+ overviewElement.view.ui.components = [];
602
+
603
+ // Add visible area graphic
604
+ const visibleAreaGraphic = new Graphic({
605
+ symbol: {
606
+ type: "simple-fill",
607
+ color: [0, 0, 0, 0.5],
608
+ outline: null
609
+ }
610
+ });
611
+ overviewElement.graphics.add(visibleAreaGraphic);
612
+
613
+ // Sync overview with main scene
614
+ reactiveUtils.watch(
615
+ () => sceneElement.visibleArea,
616
+ async (visibleArea) => {
617
+ visibleAreaGraphic.geometry = visibleArea;
618
+ await overviewElement.goTo(visibleArea);
619
+ },
620
+ { initial: true }
621
+ );
622
+ </script>
623
+ ```
624
+
625
+ ## promiseUtils (Async Utilities)
626
+
627
+ ### Debounce
628
+ ```javascript
629
+ import promiseUtils from "@arcgis/core/core/promiseUtils.js";
630
+
631
+ // Create debounced function
632
+ const debouncedUpdate = promiseUtils.debounce(async () => {
633
+ // This only runs after 300ms of no calls
634
+ await updateFeatures();
635
+ });
636
+
637
+ view.on("pointer-move", () => {
638
+ debouncedUpdate();
639
+ });
640
+ ```
641
+
642
+ ### Abort Error Handling
643
+ ```javascript
644
+ import promiseUtils from "@arcgis/core/core/promiseUtils.js";
645
+
646
+ const abortController = new AbortController();
647
+
648
+ try {
649
+ await someAsyncOperation({ signal: abortController.signal });
650
+ } catch (error) {
651
+ if (promiseUtils.isAbortError(error)) {
652
+ // Operation was intentionally cancelled
653
+ console.log("Operation cancelled");
654
+ } else {
655
+ // Real error
656
+ throw error;
657
+ }
658
+ }
659
+
660
+ // Cancel the operation
661
+ abortController.abort();
662
+ ```
663
+
664
+ ### Create Resolver
665
+ ```javascript
666
+ import promiseUtils from "@arcgis/core/core/promiseUtils.js";
667
+
668
+ // Create a promise that can be resolved/rejected externally
669
+ const { promise, resolve, reject } = promiseUtils.createResolver();
670
+
671
+ // Later, resolve or reject
672
+ resolve(result);
673
+ // or
674
+ reject(error);
675
+
676
+ // Use the promise
677
+ const result = await promise;
678
+ ```
679
+
680
+ ## reactiveUtils (Property Watching)
681
+
682
+ ### Watch Properties
683
+ ```javascript
684
+ import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";
685
+
686
+ // Watch single property
687
+ reactiveUtils.watch(
688
+ () => view.scale,
689
+ (scale) => console.log("Scale:", scale)
690
+ );
691
+
692
+ // Watch with initial value
693
+ reactiveUtils.watch(
694
+ () => view.extent,
695
+ (extent) => console.log("Extent:", extent),
696
+ { initial: true }
697
+ );
698
+
699
+ // Watch once
700
+ reactiveUtils.once(
701
+ () => view.stationary === true
702
+ ).then(() => {
703
+ console.log("View became stationary");
704
+ });
705
+
706
+ // When condition becomes true
707
+ reactiveUtils.when(
708
+ () => layer.loaded,
709
+ () => console.log("Layer loaded")
710
+ );
711
+ ```
712
+
713
+ ## Common Pitfalls
714
+
715
+ 1. **Missing CSS for Core API**: The Core API requires `main.css`:
716
+ ```html
717
+ <link rel="stylesheet" href="https://js.arcgis.com/4.34/esri/themes/light/main.css" />
718
+ ```
719
+
720
+ 2. **Not awaiting viewOnReady()**: Always wait for the view before accessing properties:
721
+ ```javascript
722
+ await mapElement.viewOnReady();
723
+ const view = mapElement.view; // Safe to access now
724
+ ```
725
+
726
+ 3. **Coordinate order**: ArcGIS uses `[longitude, latitude]`, not `[latitude, longitude]`
727
+
728
+ 4. **Missing viewDiv height**: Ensure the container has height:
729
+ ```css
730
+ html, body, #viewDiv { height: 100%; margin: 0; }
731
+ ```
732
+
733
+ 5. **Script type**: Use `type="module"` for async/await support:
734
+ ```html
735
+ <script type="module">
736
+ // async/await works here
737
+ </script>
738
+ ```
739
+