mcpField
A
arcgis-popup-templates

arcgis-popup-templates

github.com/saschabrunnerchデザイン・UI2383 回インストール29 週間前に更新
リポジトリ

arcgis-popup-templates について

arcgis-popup-templatesは、ArcGISのポップアップを作成・カスタマイズする開発者向けのエージェントスキルです。コンテンツ形式、式、アクション、動的コンテンツ、設定時の注意点を扱います。

主な機能

  1. 01複数のポップアップコンテンツ形式
  2. 02フィールドの書式設定と置換
  3. 03Arcade式のサポート
  4. 04カスタムポップアップアクション
  5. 05動的および非同期コンテンツ
  6. 06設定上の注意点と例

活用シーン

  1. 01フィーチャーポップアップで属性を表示
  2. 02チャート、画像、添付ファイルの追加
  3. 03Arcadeによるポップアップ値の計算
  4. 04マップポップアップ用のカスタムアクション作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/saschabrunnerch/arcgis-maps-sdk-js-ai-context --skill arcgis-popup-templates

インストール後、Claude Code で/arcgis-popup-templatesを入力して読み込まれたか確認します。

詳細

ArcGIS ポップアップテンプレート

さまざまなコンテンツタイプを使ったポップアップテンプレートの作成とカスタマイズには、このスキルを使用します。

インポートパターン

ESM の直接インポート
import PopupTemplate from "@arcgis/core/PopupTemplate.js";
import CustomContent from "@arcgis/core/popup/content/CustomContent.js";
動的インポート(CDN)
const PopupTemplate = await $arcgis.import("@arcgis/core/PopupTemplate.js");
const CustomContent = await $arcgis.import(
  "@arcgis/core/popup/content/CustomContent.js",
);

注: このスキルの例では、ESM の直接インポートを使用しています。CDN を使用する場合は、import X from "path" を const X = await $arcgis.import("path") に置き換えてください。

PopupTemplate の概要

コンテンツタイプ用途
TextContentHTML またはプレーンテキスト
FieldsContent属性テーブル
MediaContentチャートと画像
AttachmentsContentファイル添付
ExpressionContentArcade 式の結果
CustomContentカスタム HTML/JavaScript
RelationshipContent関連レコード
PopupTemplate のプロパティ
プロパティ型説明
titlestring | Function | objectフィールド置換({fieldName})を使ったタイトル
contentstring | Array | Function | Promiseコンテンツ定義
fieldInfosFieldInfo[]デフォルトのフィールド書式設定
expressionInfosExpressionInfo[]Arcade 式の定義
outFieldsstring[]ポップアップで取得するフィールド
actionsActionButton[] | ActionToggle[]カスタムアクションボタン
overwriteActionsbooleanデフォルトのポップアップアクションを置き換える
returnGeometrybooleanポップアップ結果にジオメトリを含める

基本的な PopupTemplate

layer.popupTemplate = {
  title: "{name}",
  content: "Population: {population}<br>Area: {area} sq mi",
};
フィールド置換を使用する
layer.popupTemplate = {
  title: "{city_name}, {state}",
  content: `
    <h3>Demographics</h3>
    <p>Population: {population:NumberFormat(places: 0)}</p>
    <p>Median Income: {median_income:NumberFormat(digitSeparator: true, places: 0)}</p>
    <p>Founded: {founded_date:DateFormat(selector: 'date', datePattern: 'MMMM d, yyyy')}</p>
  `,
};

コンテンツ配列(複数のコンテンツタイプ)

layer.popupTemplate = {
  title: "{name}",
  content: [
    {
      type: "text",
      text: "<b>Overview</b><br>{description}",
    },
    {
      type: "fields",
      fieldInfos: [
        { fieldName: "population", label: "Population" },
        { fieldName: "area", label: "Area (sq mi)" },
      ],
    },
    {
      type: "media",
      mediaInfos: [
        {
          type: "pie-chart",
          title: "Demographics",
          value: {
            fields: ["white", "black", "asian", "other"],
          },
        },
      ],
    },
  ],
};

コンテンツタイプ

TextContent
{
  type: "text",
  text: `
    <div style="padding: 10px;">
      <h2>{name}</h2>
      <p>{description}</p>
      <a href="{website}" target="_blank">Visit Website</a>
    </div>
  `
}
FieldsContent
{
  type: "fields",
  fieldInfos: [
    {
      fieldName: "name",
      label: "Name"
    },
    {
      fieldName: "population",
      label: "Population",
      format: {
        digitSeparator: true,
        places: 0
      }
    },
    {
      fieldName: "date_created",
      label: "Created",
      format: {
        dateFormat: "short-date"
      }
    }
  ]
}
日付形式
  • short-date - 12/30/2024
  • short-date-short-time - 12/30/2024, 3:30 PM
  • short-date-long-time - 12/30/2024, 3:30:45 PM
  • long-month-day-year - December 30, 2024
  • day-short-month-year - 30 Dec 2024
  • year - 2024
MediaContent
{
  type: "media",
  mediaInfos: [
    {
      title: "Sales by Quarter",
      type: "column-chart",  // bar-chart, pie-chart, line-chart, column-chart, image
      value: {
        fields: ["q1_sales", "q2_sales", "q3_sales", "q4_sales"],
        normalizeField: "total_sales"  // Optional
      }
    }
  ]
}
チャートタイプ
タイプ用途
bar-chartカテゴリ別比較のための横棒グラフ
pie-chart比例分布
line-chart系列ごとの傾向
column-chart比較のための縦棒グラフ
imageURL フィールドの画像を表示

Image MediaInfo:

{
  type: "image",
  title: "Property Photo",
  value: {
    sourceURL: "{image_url}",
    linkURL: "{detail_page_url}"
  }
}
AttachmentsContent
{
  type: "attachments",
  displayType: "preview",  // preview, list, auto
  title: "Photos"
}
ExpressionContent
layer.popupTemplate = {
  expressionInfos: [
    {
      name: "population-density",
      title: "Population Density",
      expression: "Round($feature.population / $feature.area, 2)",
    },
    {
      name: "age-category",
      title: "Age Category",
      expression: `
        var age = $feature.building_age;
        if (age < 25) return "New";
        if (age < 50) return "Moderate";
        return "Historic";
      `,
    },
  ],
  content: [
    {
      type: "expression",
      expressionInfo: {
        name: "population-density",
      },
    },
  ],
};
CustomContent
import CustomContent from "@arcgis/core/popup/content/CustomContent.js";

const customContent = new CustomContent({
  outFields: ["*"],
  creator: (event) => {
    const div = document.createElement("div");
    const graphic = event.graphic;

    div.innerHTML = `
      <div class="custom-popup">
        <h3>${graphic.attributes.name}</h3>
        <canvas id="chart-${graphic.attributes.OBJECTID}"></canvas>
      </div>
    `;

    return div;
  },
});

layer.popupTemplate = {
  title: "{name}",
  content: [customContent],
};
RelationshipContent
{
  type: "relationship",
  relationshipId: 0,
  title: "Related Inspections",
  displayCount: 5,
  orderByFields: [
    {
      field: "inspection_date",
      order: "desc"
    }
  ]
}

ポップアップコンポーネント

<arcgis-popup> コンポーネントは、ポップアップの表示を制御します。

主なプロパティ:

プロパティ型説明
actionsCollectionカスタムアクションボタン
contentstring | Node | Widgetポップアップのコンテンツ
dock-optionsobjectドッキング動作の設定
featuresGraphic[]表示するフィーチャ
headingstringポップアップの見出しテキスト
heading-levelnumber見出しレベル(1~6)
include-default-actions-disabledbooleanデフォルトのズームアクションを無効化
initial-display-modestring初期表示モード
locationPointポップアップのアンカー位置
openbooleanポップアップが開いているかどうか
selected-featureGraphic現在選択されているフィーチャ
selected-feature-indexnumber選択したフィーチャのインデックス

主なイベント:

イベント説明
arcgisTriggerActionカスタムアクションがクリックされると発生します

アクション

ポップアップにカスタムボタンを追加します。

layer.popupTemplate = {
  title: "{name}",
  content: "...",
  actions: [
    {
      id: "zoom-to",
      title: "Zoom To",
      className: "esri-icon-zoom-in-magnifying-glass",
    },
    {
      id: "edit",
      title: "Edit",
      className: "esri-icon-edit",
    },
  ],
};

// Handle action clicks using reactiveUtils
import * as reactiveUtils from "@arcgis/core/core/reactiveUtils.js";

reactiveUtils.on(
  () => view.popup,
  "trigger-action",
  (event) => {
    if (event.action.id === "zoom-to") {
      view.goTo(view.popup.selectedFeature);
    } else if (event.action.id === "edit") {
      startEditing(view.popup.selectedFeature);
    }
  },
);
アクションボタンの種類
// Icon button
{ id: "info", title: "More Info", className: "esri-icon-description" }

// Toggle button
{ id: "highlight", title: "Highlight", type: "toggle", value: false }

関数による動的コンテンツ

関数としてのコンテンツ
layer.popupTemplate = {
  title: "{name}",
  outFields: ["*"],
  content: (feature) => {
    const attributes = feature.graphic.attributes;

    if (attributes.type === "residential") {
      return `
        <h3>Residential Property</h3>
        <p>Bedrooms: ${attributes.bedrooms}</p>
        <p>Bathrooms: ${attributes.bathrooms}</p>
      `;
    } else {
      return `
        <h3>Commercial Property</h3>
        <p>Square Footage: ${attributes.sqft}</p>
      `;
    }
  },
};
非同期コンテンツ関数
layer.popupTemplate = {
  title: "{name}",
  outFields: ["*"],
  content: async (feature) => {
    const id = feature.graphic.attributes.OBJECTID;
    const response = await fetch(`/api/details/${id}`);
    const data = await response.json();

    return `
      <h3>${data.title}</h3>
      <p>${data.description}</p>
    `;
  },
};

Arcade 式

タイトル内
layer.popupTemplate = {
  title: {
    expression: `
      var name = $feature.name;
      var status = $feature.status;
      return name + " (" + status + ")";
    `,
  },
  content: "...",
};
フィールド内の式情報
layer.popupTemplate = {
  expressionInfos: [
    {
      name: "formatted-date",
      title: "Formatted Date",
      expression: 'Text($feature.created_date, "MMMM D, YYYY")',
    },
    {
      name: "calculated-field",
      title: "Density",
      expression:
        "Round($feature.population / AreaGeodetic($feature, 'square-miles'), 1)",
    },
  ],
  content: [
    {
      type: "fields",
      fieldInfos: [
        { fieldName: "expression/formatted-date", label: "Created" },
        {
          fieldName: "expression/calculated-field",
          label: "Population Density",
        },
      ],
    },
  ],
};

OutFields

layer.popupTemplate = {
  title: "{name}",
  content: "...",
  outFields: ["name", "population", "area", "created_date"],
};

// All fields
layer.popupTemplate = {
  title: "{name}",
  content: "...",
  outFields: ["*"],
};

クラスタリングのポップアップ

layer.featureReduction = {
  type: "cluster",
  clusterRadius: 80,
  popupTemplate: {
    title: "Cluster of {cluster_count} features",
    content: [
      {
        type: "fields",
        fieldInfos: [
          {
            fieldName: "cluster_count",
            label: "Features in cluster",
          },
          {
            fieldName: "cluster_avg_population",
            label: "Average Population",
            format: { digitSeparator: true, places: 0 },
          },
        ],
      },
    ],
  },
  fields: [
    {
      name: "cluster_avg_population",
      alias: "Average Population",
      onStatisticField: "population",
      statisticType: "avg",
    },
  ],
};

完全な例:マップコンポーネント

<!DOCTYPE html>
<html>
  <head>
    <script src="https://js.arcgis.com/5.0/"></script>
    <script
      type="module"
      src="https://js.arcgis.com/5.0/map-components/"
    ></script>
    <style>
      html,
      body {
        height: 100%;
        margin: 0;
      }
    </style>
  </head>
  <body>
    <arcgis-map basemap="gray-vector" center="-73.95,40.70" zoom="11">
      <arcgis-zoom slot="top-left"></arcgis-zoom>
      <arcgis-legend slot="bottom-left"></arcgis-legend>
    </arcgis-map>

    <script type="module">
      const FeatureLayer = await $arcgis.import(
        "@arcgis/core/layers/FeatureLayer.js",
      );

      const mapElement = document.querySelector("arcgis-map");
      const view = await mapElement.view;
      await view.when();

      const template = {
        title: "Marriage in {NAME} Census Tract {TRACT}",
        content: [
          {
            type: "fields",
            fieldInfos: [
              {
                fieldName: "B12001_calc_pctMarriedE",
                label: "Married %",
                format: { digitSeparator: true, places: 1 },
              },
              {
                fieldName: "B12001_calc_pctNeverE",
                label: "Never Married %",
                format: { digitSeparator: true, places: 1 },
              },
            ],
          },
        ],
      };

      const featureLayer = new FeatureLayer({
        url: "https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/ACS_Marital_Status_Boundaries/FeatureServer/2",
        popupTemplate: template,
      });
      mapElement.map.add(featureLayer);
    </script>
  </body>
</html>

リファレンスサンプル

  • intro-popuptemplate - PopupTemplate の基本設定
  • get-started-popuptemplate - PopupTemplate の使い始め方
  • popup-actions - ポップアップへのカスタムアクションの追加
  • popup-custom-action - ジオメトリ演算子を使ったカスタムポップアップアクション
  • popup-customcontent - カスタムポップアップコンテンツ要素
  • popuptemplate-arcade - ポップアップでの Arcade 式の使用
  • popuptemplate-arcade-expression-content - Arcade 式のコンテンツ
  • popup-multipleelements - ポップアップ内の複数のコンテンツ要素
  • popuptemplate-function - 関数ベースのポップアップコンテンツ
  • popuptemplate-promise - Promise ベースのポップアップコンテンツ
  • popuptemplate-browse-related-records - ポップアップ内の関連レコード

よくある落とし穴

  1. フィールド名の大文字と小文字は区別されます:フィールド名は完全に一致させる必要があります。

    // If field is "Population" (capital P)
    content: "{Population}"; // Correct
    content: "{population}"; // Wrong - shows literal {population}
    
  2. OutFields が必要です:関数コンテンツを使用する場合、ポップアップで使用するフィールドは outFields に含める必要があります。

    popupTemplate: {
      title: "{name}",
      outFields: ["name", "description"],  // Required for function content
      content: (feature) => {
        return feature.graphic.attributes.description;
      }
    }
    
  3. 式の参照:fieldInfos 内の Arcade 式には expression/ プレフィックスを使用します。

    fieldInfos: [{ fieldName: "expression/my-expression", label: "Calculated" }];
    
  4. 非同期コンテンツは値を返す必要があります:関数コンテンツは値または Promise を返す必要があります。

    // Wrong - no return
    content: (feature) => {
      const div = document.createElement("div");
    };
    
    // Correct
    content: (feature) => {
      const div = document.createElement("div");
      return div;
    };
    
  5. GeoJSON のフィールドパス:GeoJSON では、フィールド名に properties/ プレフィックスが必要です。

    // GeoJSON
    title: "{properties/name}";
    // Regular FeatureLayer
    title: "{name}";
    

関連スキル

  • ヒットテストとイベント処理については arcgis-interaction を参照してください。
  • フィーチャ編集のワークフローについては arcgis-editing を参照してください。
  • Arcade 式の構文の詳細については arcgis-arcade を参照してください。

コメント