arcgis-map-tools について
arcgis-map-tools は、ArcGIS Maps SDK for JavaScript で地図 UI を構築するための開発スキルです。地図の操作、計測、ルート検索、エクスポートの実装例を扱います。
主な機能
- 01レイヤーのスワイプ比較
- 022D・3D の距離と面積の計測
- 03座標変換とブックマーク
- 04ルート案内とプログラムによる経路検索
- 05地図の印刷とスクリーンショット出力
- 06標高プロファイルとフィーチャの識別
活用シーン
- 01地図レイヤーをインタラクティブに比較
- 02地図に計測・座標ツールを追加
- 03ルート案内と地図フィーチャの確認
- 04レポートや共有用に地図を出力
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ saschabrunnerch/ arcgis-maps-sdk-js-ai-context --skill arcgis-map-toolsインストール後、Claude Code で/arcgis-map-toolsを入力して読み込まれたか確認します。
詳細
ArcGIS マップツール
スワイプ比較、計測ツール、座標変換、ブックマーク、印刷、ルート検索、フィーチャの識別にこのスキルを使用します。
インポートパターン
ESM の直接インポート
import Measurement from "@arcgis/core/widgets/Measurement.js";
import DistanceMeasurement2D from "@arcgis/core/widgets/DistanceMeasurement2D.js";
import AreaMeasurement2D from "@arcgis/core/widgets/AreaMeasurement2D.js";
import Print from "@arcgis/core/widgets/Print.js";
import Directions from "@arcgis/core/widgets/Directions.js";
import * as route from "@arcgis/core/rest/route.js";
import * as identify from "@arcgis/core/rest/identify.js";
import * as print from "@arcgis/core/rest/print.js";
動的インポート(CDN)
const Measurement = await $arcgis.import("@arcgis/core/widgets/Measurement.js");
const Print = await $arcgis.import("@arcgis/core/widgets/Print.js");
const [route, RouteParameters] = await $arcgis.import([
"@arcgis/core/rest/route.js",
"@arcgis/core/rest/support/RouteParameters.js",
]);
スワイプウィジェット
レイヤー間をスワイプして比較します。
スワイプコンポーネント
<arcgis-map zoom="15" center="-154.88, 19.46">
<arcgis-zoom slot="top-left"></arcgis-zoom>
<arcgis-swipe swipe-position="32"></arcgis-swipe>
</arcgis-map>
<script type="module">
import Map from "@arcgis/core/Map.js";
import TileLayer from "@arcgis/core/layers/TileLayer.js";
const viewElement = document.querySelector("arcgis-map");
const arcgisSwipe = document.querySelector("arcgis-swipe");
const layer1 = new TileLayer({ url: "..." });
const layer2 = new TileLayer({ url: "..." });
viewElement.map = new Map({
basemap: "satellite",
layers: [layer1, layer2],
});
// Configure swipe when ready
arcgisSwipe.addEventListener("arcgisPropertyChange", (e) => {
if (e.detail.name === "state" && arcgisSwipe.state === "ready") {
arcgisSwipe.leadingLayers.add(layer1);
arcgisSwipe.trailingLayers.add(layer2);
}
});
</script>
スワイプウィジェット(コア API)
import Swipe from "@arcgis/core/widgets/Swipe.js";
const swipe = new Swipe({
view: view,
leadingLayers: [layer1],
trailingLayers: [layer2],
position: 50,
direction: "horizontal", // or "vertical"
});
view.ui.add(swipe);
計測
計測コンポーネント
<arcgis-map>
<arcgis-distance-measurement-2d
slot="top-right"
></arcgis-distance-measurement-2d>
<arcgis-area-measurement-2d slot="top-right"></arcgis-area-measurement-2d>
</arcgis-map>
<arcgis-scene>
<arcgis-direct-line-measurement-3d
slot="top-right"
></arcgis-direct-line-measurement-3d>
<arcgis-area-measurement-3d slot="top-right"></arcgis-area-measurement-3d>
</arcgis-scene>
計測ウィジェット(コア API)
import Measurement from "@arcgis/core/widgets/Measurement.js";
const measurement = new Measurement({ view: view });
view.ui.add(measurement, "bottom-right");
// Activate distance measurement
measurement.activeTool = view.type === "2d" ? "distance" : "direct-line";
// Activate area measurement
measurement.activeTool = "area";
// Clear measurements
measurement.clear();
2D 計測ウィジェット(コア API)
import DistanceMeasurement2D from "@arcgis/core/widgets/DistanceMeasurement2D.js";
import AreaMeasurement2D from "@arcgis/core/widgets/AreaMeasurement2D.js";
const distanceWidget = new DistanceMeasurement2D({
view: view,
unit: "kilometers",
});
view.ui.add(distanceWidget, "top-right");
const areaWidget = new AreaMeasurement2D({
view: view,
unit: "square-kilometers",
});
view.ui.add(areaWidget, "top-right");
3D 計測ウィジェット(コア API)
import DirectLineMeasurement3D from "@arcgis/core/widgets/DirectLineMeasurement3D.js";
import AreaMeasurement3D from "@arcgis/core/widgets/AreaMeasurement3D.js";
const lineWidget = new DirectLineMeasurement3D({
view: sceneView,
unit: "meters",
});
const areaWidget = new AreaMeasurement3D({
view: sceneView,
unit: "square-meters",
});
座標変換
座標変換コンポーネント
<arcgis-map basemap="satellite" center="-117.195, 34.057" zoom="13">
<arcgis-coordinate-conversion
slot="bottom-left"
></arcgis-coordinate-conversion>
</arcgis-map>
座標変換ウィジェット(コア API)
import CoordinateConversion from "@arcgis/core/widgets/CoordinateConversion.js";
const ccWidget = new CoordinateConversion({ view: view });
view.ui.add(ccWidget, "bottom-left");
ブックマーク
ブックマークコンポーネント
<arcgis-map item-id="YOUR_WEBMAP_ID">
<arcgis-expand slot="top-right" expand-tooltip="Bookmarks">
<arcgis-bookmarks></arcgis-bookmarks>
</arcgis-expand>
</arcgis-map>
ブックマークウィジェット(コア API)
import Bookmarks from "@arcgis/core/widgets/Bookmarks.js";
const bookmarks = new Bookmarks({
view: view,
editingEnabled: true,
visibleElements: {
addBookmarkButton: true,
editBookmarkButton: true,
},
});
view.ui.add(bookmarks, "top-right");
ルート案内ウィジェット
ルート案内コンポーネント
<arcgis-map>
<arcgis-directions slot="top-right"></arcgis-directions>
</arcgis-map>
ルート案内ウィジェット(コア API)
import Directions from "@arcgis/core/widgets/Directions.js";
const directions = new Directions({
view: view,
});
view.ui.add(directions, "top-right");
ルート検索(プログラムによる実行)
基本的なルート
import * as route from "@arcgis/core/rest/route.js";
import RouteParameters from "@arcgis/core/rest/support/RouteParameters.js";
import FeatureSet from "@arcgis/core/rest/support/FeatureSet.js";
import Graphic from "@arcgis/core/Graphic.js";
import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer.js";
const routeUrl =
"https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World";
const routeLayer = new GraphicsLayer();
map.add(routeLayer);
const routeParams = new RouteParameters({
apiKey: "YOUR_API_KEY",
stops: new FeatureSet(),
outSpatialReference: { wkid: 3857 },
});
// Add stop on click
view.on("click", async (event) => {
const stop = new Graphic({
geometry: event.mapPoint,
symbol: {
type: "simple-marker",
style: "cross",
size: 15,
},
});
routeLayer.add(stop);
routeParams.stops.features.push(stop);
if (routeParams.stops.features.length >= 2) {
const result = await route.solve(routeUrl, routeParams);
const routeResult = result.routeResults[0].route;
routeResult.symbol = {
type: "simple-line",
color: [0, 0, 255, 0.5],
width: 5,
};
routeLayer.add(routeResult);
}
});
ルート案内付きのルート
const routeParams = new RouteParameters({
apiKey: "YOUR_API_KEY",
stops: new FeatureSet({ features: stopGraphics }),
returnDirections: true,
directionsLanguage: "en",
returnRoutes: true,
returnStops: true,
impedanceAttribute: "TravelTime",
outSpatialReference: { wkid: 4326 },
});
const result = await route.solve(routeUrl, routeParams);
const directions = result.routeResults[0].directions;
directions.features.forEach((feature) => {
console.log(feature.attributes.text);
});
印刷
印刷コンポーネント
<arcgis-map item-id="YOUR_WEBMAP_ID">
<arcgis-expand slot="top-right" expand-tooltip="Print">
<arcgis-print></arcgis-print>
</arcgis-expand>
</arcgis-map>
印刷ウィジェット(コア API)
import Print from "@arcgis/core/widgets/Print.js";
const print = new Print({
view: view,
printServiceUrl:
"https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task",
allowedFormats: ["pdf", "png32", "jpg"],
allowedLayouts: ["a4-landscape", "a4-portrait", "letter-ansi-a-landscape"],
templateOptions: {
title: "Default Map Title",
author: "Default Author",
},
});
view.ui.add(print, "top-right");
印刷サービス(プログラムによる実行)
import * as print from "@arcgis/core/rest/print.js";
import PrintTemplate from "@arcgis/core/rest/support/PrintTemplate.js";
import PrintParameters from "@arcgis/core/rest/support/PrintParameters.js";
const printUrl =
"https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task";
const template = new PrintTemplate({
format: "pdf", // pdf, png32, png8, jpg, gif, eps, svg, svgz
layout: "a4-landscape", // Or custom layout name
exportOptions: { dpi: 300 },
layoutOptions: {
titleText: "My Map",
authorText: "Author Name",
copyrightText: "Copyright 2025",
scalebarUnit: "Kilometers",
},
});
const params = new PrintParameters({
view: view,
template: template,
});
const result = await print.execute(printUrl, params);
console.log("PDF URL:", result.url);
印刷形式
| 形式 | 説明 |
|---|---|
pdf | Adobe PDF |
png32 | 透明度付き PNG(32 ビット) |
png8 | PNG 8 ビット |
jpg | JPEG |
gif | GIF |
eps | Encapsulated PostScript |
svg | Scalable Vector Graphics |
svgz | 圧縮 SVG |
マップのみのエクスポート(レイアウトなし)
const template = new PrintTemplate({
format: "png32",
layout: "map-only",
exportOptions: {
width: 1920,
height: 1080,
dpi: 96,
},
});
代替手段としてのスクリーンショット
印刷サービスを使わずにすばやくエクスポートするには:
const screenshot = await view.takeScreenshot({
format: "png",
width: 1920,
height: 1080,
quality: 90,
});
// Download
const link = document.createElement("a");
link.download = "map-screenshot.png";
link.href = screenshot.dataUrl;
link.click();
標高プロファイル
標高プロファイルコンポーネント
<arcgis-scene>
<arcgis-elevation-profile slot="top-right"></arcgis-elevation-profile>
</arcgis-scene>
標高プロファイルウィジェット(コア API)
import ElevationProfile from "@arcgis/core/widgets/ElevationProfile.js";
const elevationProfile = new ElevationProfile({
view: view,
profiles: [{ type: "ground" }, { type: "view" }],
});
view.ui.add(elevationProfile, "top-right");
識別
MapImageLayer 上での識別
import * as identify from "@arcgis/core/rest/identify.js";
import IdentifyParameters from "@arcgis/core/rest/support/IdentifyParameters.js";
const identifyURL =
"https://sampleserver6.arcgisonline.com/arcgis/rest/services/MtBaldy_BaseMap/MapServer";
const params = new IdentifyParameters({
tolerance: 3,
layerIds: [0, 1, 2, 3, 4],
layerOption: "top", // "top", "visible", "all"
width: view.width,
height: view.height,
});
view.on("click", async (event) => {
params.geometry = event.mapPoint;
params.mapExtent = view.extent;
const response = await identify.identify(identifyURL, params);
const features = response.results.map((result) => {
const feature = result.feature;
feature.attributes.layerName = result.layerName;
feature.popupTemplate = {
title: result.layerName,
content: "{*}",
};
return feature;
});
if (features.length > 0) {
view.openPopup({
features: features,
location: event.mapPoint,
});
}
});
検索
検索サービス
import * as find from "@arcgis/core/rest/find.js";
import FindParameters from "@arcgis/core/rest/support/FindParameters.js";
const findUrl =
"https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";
const params = new FindParameters({
searchText: "California",
layerIds: [0, 1, 2],
searchFields: ["STATE_NAME", "NAME"],
returnGeometry: true,
});
const result = await find.find(findUrl, params);
result.results.forEach((r) => {
console.log(r.feature.attributes);
});
参考サンプル
widgets-measurement- 距離と面積の計測ツールwidgets-measurement-3d- 3D 計測ツールwidgets-print- マップのエクスポート用印刷ウィジェットwidgets-directions- ルート検索用ルート案内ウィジェットswipe- レイヤー比較用スワイプウィジェットcoordinate-conversion- 座標変換ユーティリティbookmarks- ブックマークナビゲーションelevation-profile- 標高プロファイルウィジェット
よくある落とし穴
-
ルート検索の API キー:ルートサービスには、有効な API キーまたは認証済みユーザーが必要です。
-
識別の許容値:ズームレベルに応じて適切な許容値を設定してください。ズームレベルが高いときに許容値が低いと、フィーチャを見逃す場合があります。
-
スワイプレイヤーの順序:先行レイヤーと後続レイヤーは、スワイプウィジェットに割り当てる前にマップのレイヤーコレクションに含める必要があります。
-
計測単位:2D ビューと 3D ビューでは、異なる計測ウィジェットを使用してください。統合された
Measurementウィジェットは、view.typeに基づいて自動的に選択します。 -
印刷サービスの URL:デフォルトの Esri 印刷サービス URL には認証が必要な場合があります。カスタム印刷サービスでは、独自の URL を設定する必要があります。
-
マップ内の座標変換:スロットを指定して
<arcgis-map>の子として配置するか、外部に配置する場合はreference-elementを使用する必要があります。
関連スキル
- 基本的な UI ウィジェットと Calcite レイアウトについては、
arcgis-widgets-uiを参照してください - 専門的なウィジェットについては、
arcgis-widgets-advancedを参照してください - REST API のクエリおよび解析ツールについては、
arcgis-rest-servicesを参照してください - サーバー側の解析操作については、
arcgis-spatial-analysisを参照してください
コメント
Markdown 対応