@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.
- package/README.md +163 -201
- package/bin/cli.js +157 -173
- package/contexts/4.34/{claude → skills}/arcgis-3d-advanced/SKILL.md +586 -586
- package/contexts/4.34/{claude → skills}/arcgis-advanced-layers/SKILL.md +431 -431
- package/contexts/4.34/{claude → skills}/arcgis-analysis-services/SKILL.md +607 -607
- package/contexts/4.34/{claude → skills}/arcgis-authentication/SKILL.md +301 -301
- package/contexts/4.34/{claude → skills}/arcgis-cim-symbols/SKILL.md +486 -486
- package/contexts/4.34/{claude → skills}/arcgis-coordinates-projection/SKILL.md +406 -406
- package/contexts/4.34/{claude → skills}/arcgis-core-maps/SKILL.md +739 -739
- package/contexts/4.34/{claude → skills}/arcgis-core-utilities/SKILL.md +732 -732
- package/contexts/4.34/{claude → skills}/arcgis-custom-rendering/SKILL.md +445 -445
- package/contexts/4.34/{claude → skills}/arcgis-editing-advanced/SKILL.md +702 -702
- package/contexts/4.34/{claude → skills}/arcgis-feature-effects/SKILL.md +393 -393
- package/contexts/4.34/{claude → skills}/arcgis-geometry-operations/SKILL.md +489 -489
- package/contexts/4.34/{claude → skills}/arcgis-imagery/SKILL.md +307 -307
- package/contexts/4.34/{claude → skills}/arcgis-interaction/SKILL.md +572 -572
- package/contexts/4.34/{claude → skills}/arcgis-knowledge-graphs/SKILL.md +582 -582
- package/contexts/4.34/{claude → skills}/arcgis-layers/SKILL.md +601 -601
- package/contexts/4.34/{claude → skills}/arcgis-map-tools/SKILL.md +668 -668
- package/contexts/4.34/{claude → skills}/arcgis-media-layers/SKILL.md +290 -290
- package/contexts/4.34/{claude → skills}/arcgis-portal-content/SKILL.md +679 -679
- package/contexts/4.34/{claude → skills}/arcgis-scene-effects/SKILL.md +512 -512
- package/contexts/4.34/{claude → skills}/arcgis-smart-mapping/SKILL.md +686 -686
- package/contexts/4.34/skills/arcgis-starter-app/SKILL.md +273 -0
- package/contexts/4.34/skills/arcgis-starter-app-extended/SKILL.md +649 -0
- package/contexts/4.34/{claude → skills}/arcgis-tables-forms/SKILL.md +877 -877
- package/contexts/4.34/{claude → skills}/arcgis-time-animation/SKILL.md +722 -722
- package/contexts/4.34/{claude → skills}/arcgis-utility-networks/SKILL.md +301 -301
- package/contexts/4.34/{claude → skills}/arcgis-visualization/SKILL.md +580 -580
- package/contexts/4.34/{claude → skills}/arcgis-widgets-ui/SKILL.md +574 -574
- package/lib/installer.js +294 -379
- package/package.json +45 -45
- package/contexts/4.34/copilot/arcgis-3d.instructions.md +0 -267
- package/contexts/4.34/copilot/arcgis-analysis.instructions.md +0 -294
- package/contexts/4.34/copilot/arcgis-arcade.instructions.md +0 -234
- package/contexts/4.34/copilot/arcgis-authentication.instructions.md +0 -187
- package/contexts/4.34/copilot/arcgis-cim-symbols.instructions.md +0 -177
- package/contexts/4.34/copilot/arcgis-core-maps.instructions.md +0 -246
- package/contexts/4.34/copilot/arcgis-core-utilities.instructions.md +0 -247
- package/contexts/4.34/copilot/arcgis-editing.instructions.md +0 -262
- package/contexts/4.34/copilot/arcgis-geometry.instructions.md +0 -225
- package/contexts/4.34/copilot/arcgis-layers.instructions.md +0 -278
- package/contexts/4.34/copilot/arcgis-popup-templates.instructions.md +0 -266
- package/contexts/4.34/copilot/arcgis-portal-advanced.instructions.md +0 -275
- package/contexts/4.34/copilot/arcgis-smart-mapping.instructions.md +0 -184
- package/contexts/4.34/copilot/arcgis-time-animation.instructions.md +0 -112
- package/contexts/4.34/copilot/arcgis-visualization.instructions.md +0 -321
- package/contexts/4.34/copilot/arcgis-widgets-ui.instructions.md +0 -277
- /package/contexts/4.34/{claude → skills}/arcgis-arcade/SKILL.md +0 -0
- /package/contexts/4.34/{claude → skills}/arcgis-popup-templates/SKILL.md +0 -0
|
@@ -1,572 +1,572 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: arcgis-interaction
|
|
3
|
-
description: Handle user interaction with map features including popups, editing, sketching, and event handling. Use for creating interactive map applications with feature selection, editing workflows, and custom interactions.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# ArcGIS Interaction
|
|
7
|
-
|
|
8
|
-
Use this skill when implementing user interactions like popups, editing, sketching, hit testing, and event handling.
|
|
9
|
-
|
|
10
|
-
## Popups
|
|
11
|
-
|
|
12
|
-
### Basic PopupTemplate
|
|
13
|
-
```javascript
|
|
14
|
-
const layer = new FeatureLayer({
|
|
15
|
-
url: "...",
|
|
16
|
-
popupTemplate: {
|
|
17
|
-
title: "{name}",
|
|
18
|
-
content: "Population: {population}"
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### PopupTemplate with Field Formatting
|
|
24
|
-
```javascript
|
|
25
|
-
const popupTemplate = {
|
|
26
|
-
title: "Feature: {name}",
|
|
27
|
-
content: [{
|
|
28
|
-
type: "fields",
|
|
29
|
-
fieldInfos: [
|
|
30
|
-
{
|
|
31
|
-
fieldName: "population",
|
|
32
|
-
label: "Population",
|
|
33
|
-
format: {
|
|
34
|
-
digitSeparator: true,
|
|
35
|
-
places: 0
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
fieldName: "date_created",
|
|
40
|
-
label: "Created",
|
|
41
|
-
format: {
|
|
42
|
-
dateFormat: "short-date"
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
fieldName: "area_sqkm",
|
|
47
|
-
label: "Area (km²)",
|
|
48
|
-
format: {
|
|
49
|
-
places: 2
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
]
|
|
53
|
-
}]
|
|
54
|
-
};
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Multiple Content Elements
|
|
58
|
-
```javascript
|
|
59
|
-
const popupTemplate = {
|
|
60
|
-
title: "{name}",
|
|
61
|
-
content: [
|
|
62
|
-
{
|
|
63
|
-
type: "text",
|
|
64
|
-
text: "<b>Description:</b> {description}"
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
type: "fields",
|
|
68
|
-
fieldInfos: [...]
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
type: "media",
|
|
72
|
-
mediaInfos: [{
|
|
73
|
-
type: "image",
|
|
74
|
-
value: {
|
|
75
|
-
sourceURL: "{image_url}"
|
|
76
|
-
}
|
|
77
|
-
}]
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
type: "attachments"
|
|
81
|
-
}
|
|
82
|
-
]
|
|
83
|
-
};
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Custom Content Function
|
|
87
|
-
```javascript
|
|
88
|
-
const popupTemplate = {
|
|
89
|
-
title: "{name}",
|
|
90
|
-
content: (feature) => {
|
|
91
|
-
const div = document.createElement("div");
|
|
92
|
-
div.innerHTML = `
|
|
93
|
-
<p>Custom content for ${feature.graphic.attributes.name}</p>
|
|
94
|
-
<button id="customBtn">Click me</button>
|
|
95
|
-
`;
|
|
96
|
-
return div;
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Arcade Expressions in Popups
|
|
102
|
-
```javascript
|
|
103
|
-
const popupTemplate = {
|
|
104
|
-
title: "{name}",
|
|
105
|
-
expressionInfos: [{
|
|
106
|
-
name: "density",
|
|
107
|
-
title: "Population Density",
|
|
108
|
-
expression: "Round($feature.population / $feature.area_sqkm, 2)"
|
|
109
|
-
}],
|
|
110
|
-
content: "Population Density: {expression/density} people/km²"
|
|
111
|
-
};
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Popup Actions
|
|
115
|
-
```javascript
|
|
116
|
-
const measureAction = {
|
|
117
|
-
title: "Measure Length",
|
|
118
|
-
id: "measure-this",
|
|
119
|
-
icon: "measure"
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const popupTemplate = {
|
|
123
|
-
title: "{name}",
|
|
124
|
-
content: "{description}",
|
|
125
|
-
actions: [measureAction]
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
// Listen for action clicks
|
|
129
|
-
import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";
|
|
130
|
-
|
|
131
|
-
reactiveUtils.on(
|
|
132
|
-
() => view.popup,
|
|
133
|
-
"trigger-action",
|
|
134
|
-
(event) => {
|
|
135
|
-
if (event.action.id === "measure-this") {
|
|
136
|
-
const geometry = view.popup.selectedFeature.geometry;
|
|
137
|
-
// Do something with the geometry
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
);
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Programmatic Popup Control
|
|
144
|
-
```javascript
|
|
145
|
-
// Open popup at location
|
|
146
|
-
view.openPopup({
|
|
147
|
-
title: "Custom Popup",
|
|
148
|
-
content: "Hello World",
|
|
149
|
-
location: view.center
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// Open popup with features
|
|
153
|
-
view.openPopup({
|
|
154
|
-
features: [graphic1, graphic2],
|
|
155
|
-
location: mapPoint
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
// Close popup
|
|
159
|
-
view.closePopup();
|
|
160
|
-
|
|
161
|
-
// Access popup properties
|
|
162
|
-
const selectedFeature = view.popup.selectedFeature;
|
|
163
|
-
const isVisible = view.popup.visible;
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Popup Component
|
|
167
|
-
```html
|
|
168
|
-
<arcgis-map basemap="streets-vector">
|
|
169
|
-
<arcgis-popup slot="popup"></arcgis-popup>
|
|
170
|
-
</arcgis-map>
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
## Hit Testing
|
|
174
|
-
|
|
175
|
-
### Basic Hit Test
|
|
176
|
-
```javascript
|
|
177
|
-
view.on("click", async (event) => {
|
|
178
|
-
const response = await view.hitTest(event);
|
|
179
|
-
|
|
180
|
-
if (response.results.length > 0) {
|
|
181
|
-
const graphic = response.results[0].graphic;
|
|
182
|
-
console.log("Clicked feature:", graphic.attributes);
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### Hit Test with Layer Filter
|
|
188
|
-
```javascript
|
|
189
|
-
view.on("click", async (event) => {
|
|
190
|
-
const response = await view.hitTest(event, {
|
|
191
|
-
include: [featureLayer] // Only test this layer
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// Or exclude layers
|
|
195
|
-
const response2 = await view.hitTest(event, {
|
|
196
|
-
exclude: [graphicsLayer]
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
### Pointer Move Hit Test
|
|
202
|
-
```javascript
|
|
203
|
-
view.on("pointer-move", async (event) => {
|
|
204
|
-
const response = await view.hitTest(event, {
|
|
205
|
-
include: featureLayer
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
if (response.results.length > 0) {
|
|
209
|
-
document.body.style.cursor = "pointer";
|
|
210
|
-
} else {
|
|
211
|
-
document.body.style.cursor = "default";
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## Highlighting
|
|
217
|
-
|
|
218
|
-
### Highlight Features
|
|
219
|
-
```javascript
|
|
220
|
-
const layerView = await view.whenLayerView(featureLayer);
|
|
221
|
-
|
|
222
|
-
// Highlight a single feature
|
|
223
|
-
const highlight = layerView.highlight(graphic);
|
|
224
|
-
|
|
225
|
-
// Highlight multiple features
|
|
226
|
-
const highlight = layerView.highlight([graphic1, graphic2]);
|
|
227
|
-
|
|
228
|
-
// Highlight by object IDs
|
|
229
|
-
const highlight = layerView.highlight([1, 2, 3]);
|
|
230
|
-
|
|
231
|
-
// Remove highlight
|
|
232
|
-
highlight.remove();
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
### Highlight on Click
|
|
236
|
-
```javascript
|
|
237
|
-
let highlightHandle;
|
|
238
|
-
|
|
239
|
-
view.on("click", async (event) => {
|
|
240
|
-
// Remove previous highlight
|
|
241
|
-
if (highlightHandle) {
|
|
242
|
-
highlightHandle.remove();
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const response = await view.hitTest(event, { include: featureLayer });
|
|
246
|
-
|
|
247
|
-
if (response.results.length > 0) {
|
|
248
|
-
const graphic = response.results[0].graphic;
|
|
249
|
-
const layerView = await view.whenLayerView(featureLayer);
|
|
250
|
-
highlightHandle = layerView.highlight(graphic);
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### Highlight Options
|
|
256
|
-
```javascript
|
|
257
|
-
// Set highlight options on the layer view
|
|
258
|
-
layerView.highlightOptions = {
|
|
259
|
-
color: [255, 255, 0, 1],
|
|
260
|
-
haloOpacity: 0.9,
|
|
261
|
-
fillOpacity: 0.2
|
|
262
|
-
};
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
## Editing
|
|
266
|
-
|
|
267
|
-
### Editor Component (Simplest)
|
|
268
|
-
```html
|
|
269
|
-
<arcgis-map item-id="YOUR_WEBMAP_ID">
|
|
270
|
-
<arcgis-editor slot="top-right"></arcgis-editor>
|
|
271
|
-
</arcgis-map>
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### Editor Widget
|
|
275
|
-
```javascript
|
|
276
|
-
import Editor from "@arcgis/core/widgets/Editor.js";
|
|
277
|
-
|
|
278
|
-
const editor = new Editor({
|
|
279
|
-
view: view,
|
|
280
|
-
layerInfos: [{
|
|
281
|
-
layer: featureLayer,
|
|
282
|
-
formTemplate: {
|
|
283
|
-
elements: [
|
|
284
|
-
{ type: "field", fieldName: "name" },
|
|
285
|
-
{ type: "field", fieldName: "description" }
|
|
286
|
-
]
|
|
287
|
-
}
|
|
288
|
-
}]
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
view.ui.add(editor, "top-right");
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
### FeatureForm
|
|
295
|
-
```javascript
|
|
296
|
-
import FeatureForm from "@arcgis/core/widgets/FeatureForm.js";
|
|
297
|
-
|
|
298
|
-
const featureForm = new FeatureForm({
|
|
299
|
-
container: "formDiv",
|
|
300
|
-
layer: featureLayer,
|
|
301
|
-
formTemplate: {
|
|
302
|
-
title: "Edit Feature",
|
|
303
|
-
elements: [
|
|
304
|
-
{
|
|
305
|
-
type: "field",
|
|
306
|
-
fieldName: "name",
|
|
307
|
-
label: "Name"
|
|
308
|
-
},
|
|
309
|
-
{
|
|
310
|
-
type: "field",
|
|
311
|
-
fieldName: "type",
|
|
312
|
-
label: "Type"
|
|
313
|
-
}
|
|
314
|
-
]
|
|
315
|
-
}
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
// Set feature to edit
|
|
319
|
-
featureForm.feature = graphic;
|
|
320
|
-
|
|
321
|
-
// Listen for submit
|
|
322
|
-
featureForm.on("submit", () => {
|
|
323
|
-
const values = featureForm.getValues();
|
|
324
|
-
// Update feature attributes
|
|
325
|
-
Object.keys(values).forEach(key => {
|
|
326
|
-
graphic.attributes[key] = values[key];
|
|
327
|
-
});
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
// Submit programmatically
|
|
331
|
-
featureForm.submit();
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
### applyEdits API
|
|
335
|
-
|
|
336
|
-
```javascript
|
|
337
|
-
// Add features
|
|
338
|
-
const edits = {
|
|
339
|
-
addFeatures: [newGraphic]
|
|
340
|
-
};
|
|
341
|
-
const result = await featureLayer.applyEdits(edits);
|
|
342
|
-
console.log("Added:", result.addFeatureResults);
|
|
343
|
-
|
|
344
|
-
// Update features
|
|
345
|
-
const edits = {
|
|
346
|
-
updateFeatures: [updatedGraphic]
|
|
347
|
-
};
|
|
348
|
-
const result = await featureLayer.applyEdits(edits);
|
|
349
|
-
|
|
350
|
-
// Delete features
|
|
351
|
-
const edits = {
|
|
352
|
-
deleteFeatures: [graphicToDelete]
|
|
353
|
-
};
|
|
354
|
-
const result = await featureLayer.applyEdits(edits);
|
|
355
|
-
|
|
356
|
-
// Combined edits
|
|
357
|
-
const edits = {
|
|
358
|
-
addFeatures: [newGraphic1, newGraphic2],
|
|
359
|
-
updateFeatures: [updatedGraphic],
|
|
360
|
-
deleteFeatures: [deleteGraphic]
|
|
361
|
-
};
|
|
362
|
-
const result = await featureLayer.applyEdits(edits);
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
## Sketching
|
|
366
|
-
|
|
367
|
-
### Sketch Component (Simplest)
|
|
368
|
-
```html
|
|
369
|
-
<arcgis-map basemap="topo-vector">
|
|
370
|
-
<arcgis-sketch slot="top-right" creation-mode="update"></arcgis-sketch>
|
|
371
|
-
</arcgis-map>
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
### Sketch Widget
|
|
375
|
-
```javascript
|
|
376
|
-
import Sketch from "@arcgis/core/widgets/Sketch.js";
|
|
377
|
-
import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer.js";
|
|
378
|
-
|
|
379
|
-
const graphicsLayer = new GraphicsLayer();
|
|
380
|
-
map.add(graphicsLayer);
|
|
381
|
-
|
|
382
|
-
const sketch = new Sketch({
|
|
383
|
-
view: view,
|
|
384
|
-
layer: graphicsLayer,
|
|
385
|
-
creationMode: "update" // or "single", "continuous"
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
view.ui.add(sketch, "top-right");
|
|
389
|
-
|
|
390
|
-
// Listen for events
|
|
391
|
-
sketch.on("create", (event) => {
|
|
392
|
-
if (event.state === "complete") {
|
|
393
|
-
console.log("Created:", event.graphic);
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
sketch.on("update", (event) => {
|
|
398
|
-
if (event.state === "complete") {
|
|
399
|
-
console.log("Updated:", event.graphics);
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
sketch.on("delete", (event) => {
|
|
404
|
-
console.log("Deleted:", event.graphics);
|
|
405
|
-
});
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
### Draw Tool (Low-level)
|
|
409
|
-
```javascript
|
|
410
|
-
import Draw from "@arcgis/core/views/draw/Draw.js";
|
|
411
|
-
|
|
412
|
-
const draw = new Draw({ view: view });
|
|
413
|
-
|
|
414
|
-
// Create a polygon
|
|
415
|
-
const action = draw.create("polygon");
|
|
416
|
-
|
|
417
|
-
action.on("vertex-add", (event) => {
|
|
418
|
-
console.log("Vertex added:", event.vertices);
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
action.on("draw-complete", (event) => {
|
|
422
|
-
const polygon = {
|
|
423
|
-
type: "polygon",
|
|
424
|
-
rings: event.vertices,
|
|
425
|
-
spatialReference: view.spatialReference
|
|
426
|
-
};
|
|
427
|
-
// Create graphic with polygon
|
|
428
|
-
});
|
|
429
|
-
```
|
|
430
|
-
|
|
431
|
-
## Event Handling
|
|
432
|
-
|
|
433
|
-
### View Events
|
|
434
|
-
```javascript
|
|
435
|
-
// Click
|
|
436
|
-
view.on("click", (event) => {
|
|
437
|
-
console.log("Map point:", event.mapPoint);
|
|
438
|
-
console.log("Screen point:", event.x, event.y);
|
|
439
|
-
});
|
|
440
|
-
|
|
441
|
-
// Double-click
|
|
442
|
-
view.on("double-click", (event) => {
|
|
443
|
-
event.stopPropagation(); // Prevent default zoom
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
// Pointer move
|
|
447
|
-
view.on("pointer-move", (event) => {
|
|
448
|
-
const point = view.toMap(event);
|
|
449
|
-
console.log("Coordinates:", point.longitude, point.latitude);
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
// Drag
|
|
453
|
-
view.on("drag", (event) => {
|
|
454
|
-
if (event.action === "start") { }
|
|
455
|
-
if (event.action === "update") { }
|
|
456
|
-
if (event.action === "end") { }
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
// Key events
|
|
460
|
-
view.on("key-down", (event) => {
|
|
461
|
-
if (event.key === "Escape") {
|
|
462
|
-
// Cancel operation
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
### Property Watching
|
|
468
|
-
```javascript
|
|
469
|
-
// Watch single property
|
|
470
|
-
view.watch("zoom", (newZoom) => {
|
|
471
|
-
console.log("Zoom changed to:", newZoom);
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
// Watch multiple properties
|
|
475
|
-
view.watch(["center", "zoom"], ([center, zoom]) => {
|
|
476
|
-
console.log("View changed:", center, zoom);
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
// Watch stationary (after navigation completes)
|
|
480
|
-
view.watch("stationary", (isStationary) => {
|
|
481
|
-
if (isStationary) {
|
|
482
|
-
console.log("Navigation complete");
|
|
483
|
-
}
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
// One-time watch
|
|
487
|
-
import { when } from "@arcgis/core/core/reactiveUtils.js";
|
|
488
|
-
|
|
489
|
-
await when(() => view.stationary === true);
|
|
490
|
-
console.log("View is now stationary");
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
### Layer Events
|
|
494
|
-
```javascript
|
|
495
|
-
// Layer view updating
|
|
496
|
-
const layerView = await view.whenLayerView(featureLayer);
|
|
497
|
-
|
|
498
|
-
layerView.watch("updating", (updating) => {
|
|
499
|
-
if (updating) {
|
|
500
|
-
console.log("Layer is updating...");
|
|
501
|
-
} else {
|
|
502
|
-
console.log("Layer update complete");
|
|
503
|
-
}
|
|
504
|
-
});
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
### Widget Events
|
|
508
|
-
```javascript
|
|
509
|
-
// Search widget
|
|
510
|
-
searchWidget.on("select-result", (event) => {
|
|
511
|
-
console.log("Selected:", event.result);
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
// Sketch widget
|
|
515
|
-
sketchWidget.on("create", (event) => {
|
|
516
|
-
if (event.state === "complete") {
|
|
517
|
-
console.log("Sketch complete");
|
|
518
|
-
}
|
|
519
|
-
});
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
## Coordinate Conversion
|
|
523
|
-
|
|
524
|
-
```javascript
|
|
525
|
-
// Screen to map coordinates
|
|
526
|
-
const mapPoint = view.toMap({ x: screenX, y: screenY });
|
|
527
|
-
|
|
528
|
-
// Map to screen coordinates
|
|
529
|
-
const screenPoint = view.toScreen(mapPoint);
|
|
530
|
-
```
|
|
531
|
-
|
|
532
|
-
## TypeScript Usage
|
|
533
|
-
|
|
534
|
-
Popup and symbol configurations use autocasting with `type` properties. For TypeScript safety, use `as const`:
|
|
535
|
-
|
|
536
|
-
```typescript
|
|
537
|
-
// Use 'as const' for popup content types
|
|
538
|
-
layer.popupTemplate = {
|
|
539
|
-
title: "{name}",
|
|
540
|
-
content: [{
|
|
541
|
-
type: "fields",
|
|
542
|
-
fieldInfos: [
|
|
543
|
-
{ fieldName: "name", label: "Name" }
|
|
544
|
-
]
|
|
545
|
-
}]
|
|
546
|
-
} as const;
|
|
547
|
-
|
|
548
|
-
// Use 'as const' for symbol configurations
|
|
549
|
-
const graphic = new Graphic({
|
|
550
|
-
geometry: point,
|
|
551
|
-
symbol: {
|
|
552
|
-
type: "simple-marker",
|
|
553
|
-
color: "red",
|
|
554
|
-
size: 12
|
|
555
|
-
} as const
|
|
556
|
-
});
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
> **Tip:** See [arcgis-core-maps skill](../arcgis-core-maps/SKILL.md) for detailed guidance on autocasting vs explicit classes.
|
|
560
|
-
|
|
561
|
-
## Common Pitfalls
|
|
562
|
-
|
|
563
|
-
1. **Popup not showing**: Ensure layer has `popupEnabled: true` (default)
|
|
564
|
-
|
|
565
|
-
2. **Hit test returns nothing**: Check if layers are included/excluded correctly
|
|
566
|
-
|
|
567
|
-
3. **Highlight not visible**: Make sure to store the highlight handle and call `remove()` before creating new highlights
|
|
568
|
-
|
|
569
|
-
4. **applyEdits fails**: Ensure layer is editable and user has edit permissions
|
|
570
|
-
|
|
571
|
-
5. **Events fire multiple times**: Remove event handlers when no longer needed
|
|
572
|
-
|
|
1
|
+
---
|
|
2
|
+
name: arcgis-interaction
|
|
3
|
+
description: Handle user interaction with map features including popups, editing, sketching, and event handling. Use for creating interactive map applications with feature selection, editing workflows, and custom interactions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ArcGIS Interaction
|
|
7
|
+
|
|
8
|
+
Use this skill when implementing user interactions like popups, editing, sketching, hit testing, and event handling.
|
|
9
|
+
|
|
10
|
+
## Popups
|
|
11
|
+
|
|
12
|
+
### Basic PopupTemplate
|
|
13
|
+
```javascript
|
|
14
|
+
const layer = new FeatureLayer({
|
|
15
|
+
url: "...",
|
|
16
|
+
popupTemplate: {
|
|
17
|
+
title: "{name}",
|
|
18
|
+
content: "Population: {population}"
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### PopupTemplate with Field Formatting
|
|
24
|
+
```javascript
|
|
25
|
+
const popupTemplate = {
|
|
26
|
+
title: "Feature: {name}",
|
|
27
|
+
content: [{
|
|
28
|
+
type: "fields",
|
|
29
|
+
fieldInfos: [
|
|
30
|
+
{
|
|
31
|
+
fieldName: "population",
|
|
32
|
+
label: "Population",
|
|
33
|
+
format: {
|
|
34
|
+
digitSeparator: true,
|
|
35
|
+
places: 0
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
fieldName: "date_created",
|
|
40
|
+
label: "Created",
|
|
41
|
+
format: {
|
|
42
|
+
dateFormat: "short-date"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
fieldName: "area_sqkm",
|
|
47
|
+
label: "Area (km²)",
|
|
48
|
+
format: {
|
|
49
|
+
places: 2
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}]
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Multiple Content Elements
|
|
58
|
+
```javascript
|
|
59
|
+
const popupTemplate = {
|
|
60
|
+
title: "{name}",
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
63
|
+
type: "text",
|
|
64
|
+
text: "<b>Description:</b> {description}"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: "fields",
|
|
68
|
+
fieldInfos: [...]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
type: "media",
|
|
72
|
+
mediaInfos: [{
|
|
73
|
+
type: "image",
|
|
74
|
+
value: {
|
|
75
|
+
sourceURL: "{image_url}"
|
|
76
|
+
}
|
|
77
|
+
}]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
type: "attachments"
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
};
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Custom Content Function
|
|
87
|
+
```javascript
|
|
88
|
+
const popupTemplate = {
|
|
89
|
+
title: "{name}",
|
|
90
|
+
content: (feature) => {
|
|
91
|
+
const div = document.createElement("div");
|
|
92
|
+
div.innerHTML = `
|
|
93
|
+
<p>Custom content for ${feature.graphic.attributes.name}</p>
|
|
94
|
+
<button id="customBtn">Click me</button>
|
|
95
|
+
`;
|
|
96
|
+
return div;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Arcade Expressions in Popups
|
|
102
|
+
```javascript
|
|
103
|
+
const popupTemplate = {
|
|
104
|
+
title: "{name}",
|
|
105
|
+
expressionInfos: [{
|
|
106
|
+
name: "density",
|
|
107
|
+
title: "Population Density",
|
|
108
|
+
expression: "Round($feature.population / $feature.area_sqkm, 2)"
|
|
109
|
+
}],
|
|
110
|
+
content: "Population Density: {expression/density} people/km²"
|
|
111
|
+
};
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Popup Actions
|
|
115
|
+
```javascript
|
|
116
|
+
const measureAction = {
|
|
117
|
+
title: "Measure Length",
|
|
118
|
+
id: "measure-this",
|
|
119
|
+
icon: "measure"
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const popupTemplate = {
|
|
123
|
+
title: "{name}",
|
|
124
|
+
content: "{description}",
|
|
125
|
+
actions: [measureAction]
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Listen for action clicks
|
|
129
|
+
import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";
|
|
130
|
+
|
|
131
|
+
reactiveUtils.on(
|
|
132
|
+
() => view.popup,
|
|
133
|
+
"trigger-action",
|
|
134
|
+
(event) => {
|
|
135
|
+
if (event.action.id === "measure-this") {
|
|
136
|
+
const geometry = view.popup.selectedFeature.geometry;
|
|
137
|
+
// Do something with the geometry
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Programmatic Popup Control
|
|
144
|
+
```javascript
|
|
145
|
+
// Open popup at location
|
|
146
|
+
view.openPopup({
|
|
147
|
+
title: "Custom Popup",
|
|
148
|
+
content: "Hello World",
|
|
149
|
+
location: view.center
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Open popup with features
|
|
153
|
+
view.openPopup({
|
|
154
|
+
features: [graphic1, graphic2],
|
|
155
|
+
location: mapPoint
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Close popup
|
|
159
|
+
view.closePopup();
|
|
160
|
+
|
|
161
|
+
// Access popup properties
|
|
162
|
+
const selectedFeature = view.popup.selectedFeature;
|
|
163
|
+
const isVisible = view.popup.visible;
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Popup Component
|
|
167
|
+
```html
|
|
168
|
+
<arcgis-map basemap="streets-vector">
|
|
169
|
+
<arcgis-popup slot="popup"></arcgis-popup>
|
|
170
|
+
</arcgis-map>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Hit Testing
|
|
174
|
+
|
|
175
|
+
### Basic Hit Test
|
|
176
|
+
```javascript
|
|
177
|
+
view.on("click", async (event) => {
|
|
178
|
+
const response = await view.hitTest(event);
|
|
179
|
+
|
|
180
|
+
if (response.results.length > 0) {
|
|
181
|
+
const graphic = response.results[0].graphic;
|
|
182
|
+
console.log("Clicked feature:", graphic.attributes);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Hit Test with Layer Filter
|
|
188
|
+
```javascript
|
|
189
|
+
view.on("click", async (event) => {
|
|
190
|
+
const response = await view.hitTest(event, {
|
|
191
|
+
include: [featureLayer] // Only test this layer
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Or exclude layers
|
|
195
|
+
const response2 = await view.hitTest(event, {
|
|
196
|
+
exclude: [graphicsLayer]
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Pointer Move Hit Test
|
|
202
|
+
```javascript
|
|
203
|
+
view.on("pointer-move", async (event) => {
|
|
204
|
+
const response = await view.hitTest(event, {
|
|
205
|
+
include: featureLayer
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
if (response.results.length > 0) {
|
|
209
|
+
document.body.style.cursor = "pointer";
|
|
210
|
+
} else {
|
|
211
|
+
document.body.style.cursor = "default";
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Highlighting
|
|
217
|
+
|
|
218
|
+
### Highlight Features
|
|
219
|
+
```javascript
|
|
220
|
+
const layerView = await view.whenLayerView(featureLayer);
|
|
221
|
+
|
|
222
|
+
// Highlight a single feature
|
|
223
|
+
const highlight = layerView.highlight(graphic);
|
|
224
|
+
|
|
225
|
+
// Highlight multiple features
|
|
226
|
+
const highlight = layerView.highlight([graphic1, graphic2]);
|
|
227
|
+
|
|
228
|
+
// Highlight by object IDs
|
|
229
|
+
const highlight = layerView.highlight([1, 2, 3]);
|
|
230
|
+
|
|
231
|
+
// Remove highlight
|
|
232
|
+
highlight.remove();
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Highlight on Click
|
|
236
|
+
```javascript
|
|
237
|
+
let highlightHandle;
|
|
238
|
+
|
|
239
|
+
view.on("click", async (event) => {
|
|
240
|
+
// Remove previous highlight
|
|
241
|
+
if (highlightHandle) {
|
|
242
|
+
highlightHandle.remove();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const response = await view.hitTest(event, { include: featureLayer });
|
|
246
|
+
|
|
247
|
+
if (response.results.length > 0) {
|
|
248
|
+
const graphic = response.results[0].graphic;
|
|
249
|
+
const layerView = await view.whenLayerView(featureLayer);
|
|
250
|
+
highlightHandle = layerView.highlight(graphic);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Highlight Options
|
|
256
|
+
```javascript
|
|
257
|
+
// Set highlight options on the layer view
|
|
258
|
+
layerView.highlightOptions = {
|
|
259
|
+
color: [255, 255, 0, 1],
|
|
260
|
+
haloOpacity: 0.9,
|
|
261
|
+
fillOpacity: 0.2
|
|
262
|
+
};
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Editing
|
|
266
|
+
|
|
267
|
+
### Editor Component (Simplest)
|
|
268
|
+
```html
|
|
269
|
+
<arcgis-map item-id="YOUR_WEBMAP_ID">
|
|
270
|
+
<arcgis-editor slot="top-right"></arcgis-editor>
|
|
271
|
+
</arcgis-map>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Editor Widget
|
|
275
|
+
```javascript
|
|
276
|
+
import Editor from "@arcgis/core/widgets/Editor.js";
|
|
277
|
+
|
|
278
|
+
const editor = new Editor({
|
|
279
|
+
view: view,
|
|
280
|
+
layerInfos: [{
|
|
281
|
+
layer: featureLayer,
|
|
282
|
+
formTemplate: {
|
|
283
|
+
elements: [
|
|
284
|
+
{ type: "field", fieldName: "name" },
|
|
285
|
+
{ type: "field", fieldName: "description" }
|
|
286
|
+
]
|
|
287
|
+
}
|
|
288
|
+
}]
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
view.ui.add(editor, "top-right");
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### FeatureForm
|
|
295
|
+
```javascript
|
|
296
|
+
import FeatureForm from "@arcgis/core/widgets/FeatureForm.js";
|
|
297
|
+
|
|
298
|
+
const featureForm = new FeatureForm({
|
|
299
|
+
container: "formDiv",
|
|
300
|
+
layer: featureLayer,
|
|
301
|
+
formTemplate: {
|
|
302
|
+
title: "Edit Feature",
|
|
303
|
+
elements: [
|
|
304
|
+
{
|
|
305
|
+
type: "field",
|
|
306
|
+
fieldName: "name",
|
|
307
|
+
label: "Name"
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
type: "field",
|
|
311
|
+
fieldName: "type",
|
|
312
|
+
label: "Type"
|
|
313
|
+
}
|
|
314
|
+
]
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// Set feature to edit
|
|
319
|
+
featureForm.feature = graphic;
|
|
320
|
+
|
|
321
|
+
// Listen for submit
|
|
322
|
+
featureForm.on("submit", () => {
|
|
323
|
+
const values = featureForm.getValues();
|
|
324
|
+
// Update feature attributes
|
|
325
|
+
Object.keys(values).forEach(key => {
|
|
326
|
+
graphic.attributes[key] = values[key];
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// Submit programmatically
|
|
331
|
+
featureForm.submit();
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### applyEdits API
|
|
335
|
+
|
|
336
|
+
```javascript
|
|
337
|
+
// Add features
|
|
338
|
+
const edits = {
|
|
339
|
+
addFeatures: [newGraphic]
|
|
340
|
+
};
|
|
341
|
+
const result = await featureLayer.applyEdits(edits);
|
|
342
|
+
console.log("Added:", result.addFeatureResults);
|
|
343
|
+
|
|
344
|
+
// Update features
|
|
345
|
+
const edits = {
|
|
346
|
+
updateFeatures: [updatedGraphic]
|
|
347
|
+
};
|
|
348
|
+
const result = await featureLayer.applyEdits(edits);
|
|
349
|
+
|
|
350
|
+
// Delete features
|
|
351
|
+
const edits = {
|
|
352
|
+
deleteFeatures: [graphicToDelete]
|
|
353
|
+
};
|
|
354
|
+
const result = await featureLayer.applyEdits(edits);
|
|
355
|
+
|
|
356
|
+
// Combined edits
|
|
357
|
+
const edits = {
|
|
358
|
+
addFeatures: [newGraphic1, newGraphic2],
|
|
359
|
+
updateFeatures: [updatedGraphic],
|
|
360
|
+
deleteFeatures: [deleteGraphic]
|
|
361
|
+
};
|
|
362
|
+
const result = await featureLayer.applyEdits(edits);
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Sketching
|
|
366
|
+
|
|
367
|
+
### Sketch Component (Simplest)
|
|
368
|
+
```html
|
|
369
|
+
<arcgis-map basemap="topo-vector">
|
|
370
|
+
<arcgis-sketch slot="top-right" creation-mode="update"></arcgis-sketch>
|
|
371
|
+
</arcgis-map>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Sketch Widget
|
|
375
|
+
```javascript
|
|
376
|
+
import Sketch from "@arcgis/core/widgets/Sketch.js";
|
|
377
|
+
import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer.js";
|
|
378
|
+
|
|
379
|
+
const graphicsLayer = new GraphicsLayer();
|
|
380
|
+
map.add(graphicsLayer);
|
|
381
|
+
|
|
382
|
+
const sketch = new Sketch({
|
|
383
|
+
view: view,
|
|
384
|
+
layer: graphicsLayer,
|
|
385
|
+
creationMode: "update" // or "single", "continuous"
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
view.ui.add(sketch, "top-right");
|
|
389
|
+
|
|
390
|
+
// Listen for events
|
|
391
|
+
sketch.on("create", (event) => {
|
|
392
|
+
if (event.state === "complete") {
|
|
393
|
+
console.log("Created:", event.graphic);
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
sketch.on("update", (event) => {
|
|
398
|
+
if (event.state === "complete") {
|
|
399
|
+
console.log("Updated:", event.graphics);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
sketch.on("delete", (event) => {
|
|
404
|
+
console.log("Deleted:", event.graphics);
|
|
405
|
+
});
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Draw Tool (Low-level)
|
|
409
|
+
```javascript
|
|
410
|
+
import Draw from "@arcgis/core/views/draw/Draw.js";
|
|
411
|
+
|
|
412
|
+
const draw = new Draw({ view: view });
|
|
413
|
+
|
|
414
|
+
// Create a polygon
|
|
415
|
+
const action = draw.create("polygon");
|
|
416
|
+
|
|
417
|
+
action.on("vertex-add", (event) => {
|
|
418
|
+
console.log("Vertex added:", event.vertices);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
action.on("draw-complete", (event) => {
|
|
422
|
+
const polygon = {
|
|
423
|
+
type: "polygon",
|
|
424
|
+
rings: event.vertices,
|
|
425
|
+
spatialReference: view.spatialReference
|
|
426
|
+
};
|
|
427
|
+
// Create graphic with polygon
|
|
428
|
+
});
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
## Event Handling
|
|
432
|
+
|
|
433
|
+
### View Events
|
|
434
|
+
```javascript
|
|
435
|
+
// Click
|
|
436
|
+
view.on("click", (event) => {
|
|
437
|
+
console.log("Map point:", event.mapPoint);
|
|
438
|
+
console.log("Screen point:", event.x, event.y);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// Double-click
|
|
442
|
+
view.on("double-click", (event) => {
|
|
443
|
+
event.stopPropagation(); // Prevent default zoom
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// Pointer move
|
|
447
|
+
view.on("pointer-move", (event) => {
|
|
448
|
+
const point = view.toMap(event);
|
|
449
|
+
console.log("Coordinates:", point.longitude, point.latitude);
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
// Drag
|
|
453
|
+
view.on("drag", (event) => {
|
|
454
|
+
if (event.action === "start") { }
|
|
455
|
+
if (event.action === "update") { }
|
|
456
|
+
if (event.action === "end") { }
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
// Key events
|
|
460
|
+
view.on("key-down", (event) => {
|
|
461
|
+
if (event.key === "Escape") {
|
|
462
|
+
// Cancel operation
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Property Watching
|
|
468
|
+
```javascript
|
|
469
|
+
// Watch single property
|
|
470
|
+
view.watch("zoom", (newZoom) => {
|
|
471
|
+
console.log("Zoom changed to:", newZoom);
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
// Watch multiple properties
|
|
475
|
+
view.watch(["center", "zoom"], ([center, zoom]) => {
|
|
476
|
+
console.log("View changed:", center, zoom);
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
// Watch stationary (after navigation completes)
|
|
480
|
+
view.watch("stationary", (isStationary) => {
|
|
481
|
+
if (isStationary) {
|
|
482
|
+
console.log("Navigation complete");
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
// One-time watch
|
|
487
|
+
import { when } from "@arcgis/core/core/reactiveUtils.js";
|
|
488
|
+
|
|
489
|
+
await when(() => view.stationary === true);
|
|
490
|
+
console.log("View is now stationary");
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### Layer Events
|
|
494
|
+
```javascript
|
|
495
|
+
// Layer view updating
|
|
496
|
+
const layerView = await view.whenLayerView(featureLayer);
|
|
497
|
+
|
|
498
|
+
layerView.watch("updating", (updating) => {
|
|
499
|
+
if (updating) {
|
|
500
|
+
console.log("Layer is updating...");
|
|
501
|
+
} else {
|
|
502
|
+
console.log("Layer update complete");
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### Widget Events
|
|
508
|
+
```javascript
|
|
509
|
+
// Search widget
|
|
510
|
+
searchWidget.on("select-result", (event) => {
|
|
511
|
+
console.log("Selected:", event.result);
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
// Sketch widget
|
|
515
|
+
sketchWidget.on("create", (event) => {
|
|
516
|
+
if (event.state === "complete") {
|
|
517
|
+
console.log("Sketch complete");
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
## Coordinate Conversion
|
|
523
|
+
|
|
524
|
+
```javascript
|
|
525
|
+
// Screen to map coordinates
|
|
526
|
+
const mapPoint = view.toMap({ x: screenX, y: screenY });
|
|
527
|
+
|
|
528
|
+
// Map to screen coordinates
|
|
529
|
+
const screenPoint = view.toScreen(mapPoint);
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
## TypeScript Usage
|
|
533
|
+
|
|
534
|
+
Popup and symbol configurations use autocasting with `type` properties. For TypeScript safety, use `as const`:
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
// Use 'as const' for popup content types
|
|
538
|
+
layer.popupTemplate = {
|
|
539
|
+
title: "{name}",
|
|
540
|
+
content: [{
|
|
541
|
+
type: "fields",
|
|
542
|
+
fieldInfos: [
|
|
543
|
+
{ fieldName: "name", label: "Name" }
|
|
544
|
+
]
|
|
545
|
+
}]
|
|
546
|
+
} as const;
|
|
547
|
+
|
|
548
|
+
// Use 'as const' for symbol configurations
|
|
549
|
+
const graphic = new Graphic({
|
|
550
|
+
geometry: point,
|
|
551
|
+
symbol: {
|
|
552
|
+
type: "simple-marker",
|
|
553
|
+
color: "red",
|
|
554
|
+
size: 12
|
|
555
|
+
} as const
|
|
556
|
+
});
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
> **Tip:** See [arcgis-core-maps skill](../arcgis-core-maps/SKILL.md) for detailed guidance on autocasting vs explicit classes.
|
|
560
|
+
|
|
561
|
+
## Common Pitfalls
|
|
562
|
+
|
|
563
|
+
1. **Popup not showing**: Ensure layer has `popupEnabled: true` (default)
|
|
564
|
+
|
|
565
|
+
2. **Hit test returns nothing**: Check if layers are included/excluded correctly
|
|
566
|
+
|
|
567
|
+
3. **Highlight not visible**: Make sure to store the highlight handle and call `remove()` before creating new highlights
|
|
568
|
+
|
|
569
|
+
4. **applyEdits fails**: Ensure layer is editable and user has edit permissions
|
|
570
|
+
|
|
571
|
+
5. **Events fire multiple times**: Remove event handlers when no longer needed
|
|
572
|
+
|