スキル一覧に戻る
SaschaBrunnerCH

arcgis-interaction

by SaschaBrunnerCH

Install AI assistant context files for ArcGIS Maps SDK for JavaScript development. Supports Claude skills and GitHub Copilot instructions.

1🍴 0📅 2026年1月9日
GitHubで見るManusで実行

SKILL.md


name: arcgis-interaction 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.

ArcGIS Interaction

Use this skill when implementing user interactions like popups, editing, sketching, hit testing, and event handling.

Popups

Basic PopupTemplate

const layer = new FeatureLayer({
  url: "...",
  popupTemplate: {
    title: "{name}",
    content: "Population: {population}"
  }
});

PopupTemplate with Field Formatting

const popupTemplate = {
  title: "Feature: {name}",
  content: [{
    type: "fields",
    fieldInfos: [
      {
        fieldName: "population",
        label: "Population",
        format: {
          digitSeparator: true,
          places: 0
        }
      },
      {
        fieldName: "date_created",
        label: "Created",
        format: {
          dateFormat: "short-date"
        }
      },
      {
        fieldName: "area_sqkm",
        label: "Area (km²)",
        format: {
          places: 2
        }
      }
    ]
  }]
};

Multiple Content Elements

const popupTemplate = {
  title: "{name}",
  content: [
    {
      type: "text",
      text: "<b>Description:</b> {description}"
    },
    {
      type: "fields",
      fieldInfos: [...]
    },
    {
      type: "media",
      mediaInfos: [{
        type: "image",
        value: {
          sourceURL: "{image_url}"
        }
      }]
    },
    {
      type: "attachments"
    }
  ]
};

Custom Content Function

const popupTemplate = {
  title: "{name}",
  content: (feature) => {
    const div = document.createElement("div");
    div.innerHTML = `
      <p>Custom content for ${feature.graphic.attributes.name}</p>
      <button id="customBtn">Click me</button>
    `;
    return div;
  }
};

Arcade Expressions in Popups

const popupTemplate = {
  title: "{name}",
  expressionInfos: [{
    name: "density",
    title: "Population Density",
    expression: "Round($feature.population / $feature.area_sqkm, 2)"
  }],
  content: "Population Density: {expression/density} people/km²"
};
const measureAction = {
  title: "Measure Length",
  id: "measure-this",
  icon: "measure"
};

const popupTemplate = {
  title: "{name}",
  content: "{description}",
  actions: [measureAction]
};

// Listen for action clicks
import reactiveUtils from "@arcgis/core/core/reactiveUtils.js";

reactiveUtils.on(
  () => view.popup,
  "trigger-action",
  (event) => {
    if (event.action.id === "measure-this") {
      const geometry = view.popup.selectedFeature.geometry;
      // Do something with the geometry
    }
  }
);

Programmatic Popup Control

// Open popup at location
view.openPopup({
  title: "Custom Popup",
  content: "Hello World",
  location: view.center
});

// Open popup with features
view.openPopup({
  features: [graphic1, graphic2],
  location: mapPoint
});

// Close popup
view.closePopup();

// Access popup properties
const selectedFeature = view.popup.selectedFeature;
const isVisible = view.popup.visible;
<arcgis-map basemap="streets-vector">
  <arcgis-popup slot="popup"></arcgis-popup>
</arcgis-map>

Hit Testing

Basic Hit Test

view.on("click", async (event) => {
  const response = await view.hitTest(event);

  if (response.results.length > 0) {
    const graphic = response.results[0].graphic;
    console.log("Clicked feature:", graphic.attributes);
  }
});

Hit Test with Layer Filter

view.on("click", async (event) => {
  const response = await view.hitTest(event, {
    include: [featureLayer] // Only test this layer
  });

  // Or exclude layers
  const response2 = await view.hitTest(event, {
    exclude: [graphicsLayer]
  });
});

Pointer Move Hit Test

view.on("pointer-move", async (event) => {
  const response = await view.hitTest(event, {
    include: featureLayer
  });

  if (response.results.length > 0) {
    document.body.style.cursor = "pointer";
  } else {
    document.body.style.cursor = "default";
  }
});

Highlighting

Highlight Features

const layerView = await view.whenLayerView(featureLayer);

// Highlight a single feature
const highlight = layerView.highlight(graphic);

// Highlight multiple features
const highlight = layerView.highlight([graphic1, graphic2]);

// Highlight by object IDs
const highlight = layerView.highlight([1, 2, 3]);

// Remove highlight
highlight.remove();

Highlight on Click

let highlightHandle;

view.on("click", async (event) => {
  // Remove previous highlight
  if (highlightHandle) {
    highlightHandle.remove();
  }

  const response = await view.hitTest(event, { include: featureLayer });

  if (response.results.length > 0) {
    const graphic = response.results[0].graphic;
    const layerView = await view.whenLayerView(featureLayer);
    highlightHandle = layerView.highlight(graphic);
  }
});

Highlight Options

// Set highlight options on the layer view
layerView.highlightOptions = {
  color: [255, 255, 0, 1],
  haloOpacity: 0.9,
  fillOpacity: 0.2
};

Editing

Editor Component (Simplest)

<arcgis-map item-id="YOUR_WEBMAP_ID">
  <arcgis-editor slot="top-right"></arcgis-editor>
</arcgis-map>

Editor Widget

import Editor from "@arcgis/core/widgets/Editor.js";

const editor = new Editor({
  view: view,
  layerInfos: [{
    layer: featureLayer,
    formTemplate: {
      elements: [
        { type: "field", fieldName: "name" },
        { type: "field", fieldName: "description" }
      ]
    }
  }]
});

view.ui.add(editor, "top-right");

FeatureForm

import FeatureForm from "@arcgis/core/widgets/FeatureForm.js";

const featureForm = new FeatureForm({
  container: "formDiv",
  layer: featureLayer,
  formTemplate: {
    title: "Edit Feature",
    elements: [
      {
        type: "field",
        fieldName: "name",
        label: "Name"
      },
      {
        type: "field",
        fieldName: "type",
        label: "Type"
      }
    ]
  }
});

// Set feature to edit
featureForm.feature = graphic;

// Listen for submit
featureForm.on("submit", () => {
  const values = featureForm.getValues();
  // Update feature attributes
  Object.keys(values).forEach(key => {
    graphic.attributes[key] = values[key];
  });
});

// Submit programmatically
featureForm.submit();

applyEdits API

// Add features
const edits = {
  addFeatures: [newGraphic]
};
const result = await featureLayer.applyEdits(edits);
console.log("Added:", result.addFeatureResults);

// Update features
const edits = {
  updateFeatures: [updatedGraphic]
};
const result = await featureLayer.applyEdits(edits);

// Delete features
const edits = {
  deleteFeatures: [graphicToDelete]
};
const result = await featureLayer.applyEdits(edits);

// Combined edits
const edits = {
  addFeatures: [newGraphic1, newGraphic2],
  updateFeatures: [updatedGraphic],
  deleteFeatures: [deleteGraphic]
};
const result = await featureLayer.applyEdits(edits);

Sketching

Sketch Component (Simplest)

<arcgis-map basemap="topo-vector">
  <arcgis-sketch slot="top-right" creation-mode="update"></arcgis-sketch>
</arcgis-map>

Sketch Widget

import Sketch from "@arcgis/core/widgets/Sketch.js";
import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer.js";

const graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);

const sketch = new Sketch({
  view: view,
  layer: graphicsLayer,
  creationMode: "update" // or "single", "continuous"
});

view.ui.add(sketch, "top-right");

// Listen for events
sketch.on("create", (event) => {
  if (event.state === "complete") {
    console.log("Created:", event.graphic);
  }
});

sketch.on("update", (event) => {
  if (event.state === "complete") {
    console.log("Updated:", event.graphics);
  }
});

sketch.on("delete", (event) => {
  console.log("Deleted:", event.graphics);
});

Draw Tool (Low-level)

import Draw from "@arcgis/core/views/draw/Draw.js";

const draw = new Draw({ view: view });

// Create a polygon
const action = draw.create("polygon");

action.on("vertex-add", (event) => {
  console.log("Vertex added:", event.vertices);
});

action.on("draw-complete", (event) => {
  const polygon = {
    type: "polygon",
    rings: event.vertices,
    spatialReference: view.spatialReference
  };
  // Create graphic with polygon
});

Event Handling

View Events

// Click
view.on("click", (event) => {
  console.log("Map point:", event.mapPoint);
  console.log("Screen point:", event.x, event.y);
});

// Double-click
view.on("double-click", (event) => {
  event.stopPropagation(); // Prevent default zoom
});

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

// Drag
view.on("drag", (event) => {
  if (event.action === "start") { }
  if (event.action === "update") { }
  if (event.action === "end") { }
});

// Key events
view.on("key-down", (event) => {
  if (event.key === "Escape") {
    // Cancel operation
  }
});

Property Watching

// Watch single property
view.watch("zoom", (newZoom) => {
  console.log("Zoom changed to:", newZoom);
});

// Watch multiple properties
view.watch(["center", "zoom"], ([center, zoom]) => {
  console.log("View changed:", center, zoom);
});

// Watch stationary (after navigation completes)
view.watch("stationary", (isStationary) => {
  if (isStationary) {
    console.log("Navigation complete");
  }
});

// One-time watch
import { when } from "@arcgis/core/core/reactiveUtils.js";

await when(() => view.stationary === true);
console.log("View is now stationary");

Layer Events

// Layer view updating
const layerView = await view.whenLayerView(featureLayer);

layerView.watch("updating", (updating) => {
  if (updating) {
    console.log("Layer is updating...");
  } else {
    console.log("Layer update complete");
  }
});

Widget Events

// Search widget
searchWidget.on("select-result", (event) => {
  console.log("Selected:", event.result);
});

// Sketch widget
sketchWidget.on("create", (event) => {
  if (event.state === "complete") {
    console.log("Sketch complete");
  }
});

Coordinate Conversion

// Screen to map coordinates
const mapPoint = view.toMap({ x: screenX, y: screenY });

// Map to screen coordinates
const screenPoint = view.toScreen(mapPoint);

TypeScript Usage

Popup and symbol configurations use autocasting with type properties. For TypeScript safety, use as const:

// Use 'as const' for popup content types
layer.popupTemplate = {
  title: "{name}",
  content: [{
    type: "fields",
    fieldInfos: [
      { fieldName: "name", label: "Name" }
    ]
  }]
} as const;

// Use 'as const' for symbol configurations
const graphic = new Graphic({
  geometry: point,
  symbol: {
    type: "simple-marker",
    color: "red",
    size: 12
  } as const
});

Tip: See arcgis-core-maps skill for detailed guidance on autocasting vs explicit classes.

Common Pitfalls

  1. Popup not showing: Ensure layer has popupEnabled: true (default)

  2. Hit test returns nothing: Check if layers are included/excluded correctly

  3. Highlight not visible: Make sure to store the highlight handle and call remove() before creating new highlights

  4. applyEdits fails: Ensure layer is editable and user has edit permissions

  5. Events fire multiple times: Remove event handlers when no longer needed

スコア

総合スコア

70/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です