【Esri Community】
はじめに
これまで Calcite Design System の使用方法として、Calcite Design System のチュートリアルを2回連載しました。本記事では第3回として、チュートリアルの Apply core concepts を紹介します。
第1回:地図アプリの作成
第2回:テーマ スイッチャーの作成
第3回:コアコンセプトの適用 ←本記事
スロット、イベント、属性などの主要なWebコンポーネントの概念を使用して、Calcite Components と、ArcGIS API for JavaScript によって提供されるデータを使用したインターフェイスを構築します。
このチュートリアルでは、Calcite Component と Web コンポーネントの概念を説明します。
・calcite-shell および関連コンポーネントでインターフェイスの雛型とします
・コンテンツを含むフィーチャ レイヤーを使用します
・Calcite Components を使用して、queryTopFeatures() メソッドによって提供されるデータを表示します
・イベントと属性の概念を使用して、マップとデータにインタラクティブ性を追加します
・Colors and themes を使用して、見た目をカスタマイズします
このチュートリアルでは通常の JavaScript を使用しますが、これらの概念と相互作用はフレームワーク全体に適用できます。
前提条件
ArcGIS 開発者アカウント
このチュートリアルで使用するサービスにアクセスするには、無料の または ArcGIS Online の組織に関連付けられたアカウントが必要です。
ステップ
新しいペンの作成
1.CodePen にアクセスして、マッピング アプリケーション用の新しいペンを作成します。
HTML を追加
1.CodePen > HTML で、HTML と CSS を追加して、地図を表示する 要素を含むページを作成します。地図がブラウザのウィンドウの幅と高さいっぱいに表示されるようにします。
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Calcite Components: Core concepts</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="viewDiv"></div>
</body>
<script>
</script>
</html>
2.<head>要素に、Calcite Components と ArcGIS JavaScript APIへの参照を追加します。
<script type="module" src="https://js.arcgis.com/calcite-components/1.0.0-beta.95/calcite.esm.js"></script>
<link rel="stylesheet" type="text/css" href="https://js.arcgis.com/calcite-components/1.0.0-beta.95/calcite.css" />
<script src="https://js.arcgis.com/4.23/"></script>
<link rel="stylesheet" href="https://js.arcgis.com/4.23/esri/themes/light/main.css" />
モジュールのインポート
1.<script>要素で、このアプリケーションで使用する ArcGIS JavaScript API モジュールをインポートします。
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/symbols/WebStyleSymbol",
"esri/Basemap",
"esri/rest/support/TopFeaturesQuery",
"esri/rest/support/TopFilter",
"esri/widgets/Home"
], (Map, MapView, FeatureLayer, WebStyleSymbol, Basemap, TopFeaturesQuery, TopFilter, Home) => (async () => {
})());
</script>
APIキーの使用
開発者アカウントを使用している場合、ArcGIS サービスにアクセスするために API キーが必要です。ArcGIS Online の組織に関連付けられたアカウントをお持ちの場合は、この手順を省略することができます。
1.開発者用ダッシュボードで、APIキーを取得します。
2.CodePen> <script> に戻り、esriConfig クラスをインポートします。
3.apiKey プロパティを設定します。
"esri/widgets/Home",
"esri/config"
], function (Map, MapView, FeatureLayer, WebStyleSymbol, Basemap, TopFeaturesQuery, TopFilter, Home, esriConfig) => (async () => {
esriConfig.apiKey = "YOUR_API_KEY";
アプリケーションの雛型
Calcite Components を追加して、アプリケーションの雛型にします。
1.calcite-shell コンポーネントは、アプリケーションのフレームとして機能します。さらに、calcite-shell-panel と calcite-panel コンポーネントが追加されていることを確認してください。
これらのレイアウト コンポーネントは、コンテンツや他のコンポーネントを整理するために役立ち、多くの必要なレイアウトやユースケースに対応するように構成できます。
<body>
<calcite-shell>
<calcite-shell-panel slot="panel-start">
<calcite-panel heading="National Park Visitation">
</calcite-panel>
</calcite-shell-panel>
<div id="viewDiv"></div>
</calcite-shell>
</body>
2.アプリケーションに追加したスニペットのWebコンポーネントの概念を理解します。
・calcite-shell-panel に追加された panel-start スロットは、スロット化されたコンテンツやコンポーネントにスタイルや位置を提供することができ、一般的なパターンを簡単に構築することができます。
・calcite-panel コンポーネントに heading 属性が追加され、アプリケーションの名前が取り込まれます。コンポーネント属性を使用してテキストを追加すると、コンテンツの配置やスタイルを統一することができます。
地図を表示
1.Query top features from a FeatureLayer のチュートリアルに基づき、ArcGIS API for JavaScript のコードを追加します。
"esri/widgets/Home"
], (Map, MapView, FeatureLayer, WebStyleSymbol, Basemap, TopFeaturesQuery, TopFilter, Home) => (async () => {
const layer = new FeatureLayer({
url:"https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/US_National_Parks_Annual_Visitation/FeatureServer/0",
outFields: ["*"],
renderer: await setRenderer(),
popupTemplate: createPopupTemplate()
});
const map = new Map({
basemap: "streets-navigation-vector",
layers: [layer]
});
const view = new MapView({
container: "viewDiv",
map: map,
center: [-120, 45],
zoom: 3
});
let homeWidget = new Home({
view: view
});
view.ui.add(homeWidget, "top-right");
view.ui.move("zoom", "top-right");
const layerView = await view.whenLayerView(layer);
async function setRenderer() {
const symbol = new WebStyleSymbol({
name: "park",
styleName: "Esri2DPointSymbolsStyle"
});
const cimSymbol = await symbol.fetchCIMSymbol();
cimSymbol.data.symbol.symbolLayers[0].size = 24;
cimSymbol.data.symbol.symbolLayers[1].size = 0;
return {
type: "simple",
symbol: cimSymbol
};
}
function createPopupTemplate() {
return {
title: "{Park}",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "TOTAL",
label: "Total visits",
format: { digitSeparator: true }
}, {
fieldName: "F2018",
label: "2018",
format: { digitSeparator: true }
}, {
fieldName: "F2019",
label: "2019",
format: { digitSeparator: true }
}, {
fieldName: "F2020",
label: "2020",
format: { digitSeparator: true }
}]
}]
};
}
この時点で、追加したcalcite-shell-panel の背景にマップが表示されます。マップのポイントの周りをクリックすると、ポップアップで表示されるデータを見ることができます。この構成は Calcite Components 固有のものではありません。詳細については、こちらのチュートリアルを参照してください。
2.地図上のデータをフィルターする関数を追加します。filterItems() 関数には queryTopFeatures() メソッドが含まれており、フィルター オプションのセットに基づいて結果を返します。後でアプリケーションで設定できるようにする変数に、いくつかデフォルト値が割り当たっていることを確認してください。
}
const countDefault = 1;
const orderByDefault = "DESC"
const yearDefault = "TOTAL"
let count = countDefault;
let orderBy = orderByDefault;
let year = yearDefault;
async function filterItems() {
const query = new TopFeaturesQuery({
topFilter: new TopFilter({
topCount: count,
groupByFields: ["State"],
orderByFields: `${year} ${orderBy}`
}),
orderByFields: `${year} ${orderBy}`,
outFields: ["State, TOTAL, F2018, F2019, F2020, Park"],
returnGeometry: true,
cacheHint: false
});
query.orderByFields = [""];
const objectIds = await layer.queryTopObjectIds(query);
layerView.filter = { objectIds };
}
filterItems();
結果リストを追加
ArcGIS API for JavaScript から返された結果を使用してリストを作成します。結果アイテムをクリックすると、マップ上に関連するポップアップが表示されます。
1.id 属性を持つ calcite-block を追加します。内部に、コンテンツの追加に使用される calcite-list を配置します。コンポーネントのカスタマイズに使用される collapsible と heading 属性に注意してください。
<calcite-shell-panel slot="panel-start">
<calcite-panel heading="National Park Visitation">
<calcite-block collapsible heading="Results" id="result-block">
<calcite-list id="result-list"></calcite-list>
</calcite-block>
</calcite-panel>
</calcite-shell-panel>
2.フィーチャ レイヤーに表示されている項目ごとに、calcite-list-item を作成するロジックを追加します。
cacheHint: false
});
document.getElementById("result-list").innerHTML = "";
document.getElementById("result-block").open = true;
const results = await layer.queryTopFeatures(query);
graphics = results.features;
graphics.forEach((result, index) => {
const attributes = result.attributes;
const item = document.createElement("calcite-list-item");
const chip = document.createElement("calcite-chip");
chip.value = attributes.State;
chip.slot = "content-end";
chip.scale = "s";
chip.innerText = attributes.State;
item.label = attributes.Park;
item.value = index;
item.description = `${attributes[yearDefault].toLocaleString()} visitors`;
item.addEventListener("click", () => resultClickHandler(result, index));
item.appendChild(chip);
document.getElementById("result-list").appendChild(item);
});
query.orderByFields = [""];
const objectIds = await layer.queryTopObjectIds(query);
各グラフィックについて、プログラムで calcite-list-item を作成し、表示をカスタマイズするためにプロパティ値を割り当て、すでに追加した結果リスト表示用のコンテナーに追加します。また、各結果の状態名で calcite-chip を作成し、スロットに配置します。
3.前のステップで作成した calcite-list-item それぞれにイベントリスナーが追加されました。ArcGIS API for JavaScript のポップアップを表示する resultClickHandler() 関数を作成します。
layerView.filter = { objectIds };
}
function resultClickHandler(result, index) {
const popup = graphics && graphics[parseInt(index, 10)];
if (popup) {
view.popup.open({
features: [popup],
location: result.geometry
});
view.goTo({ center: [result.geometry.longitude, result.geometry.latitude], zoom: 4 }, { duration: 400 });
}
}
フィルターを構築
1.calcite-block コンポーネントを追加します。内部に queryTopFeatures() クエリのパラメーターを調整するコントロールを配置します。各コントロールは、calcite-label でラップされます。
<calcite-panel heading="National Park Visitation">
<calcite-block heading="Filters" open>
<calcite-label>
Data type, per state
<calcite-radio-group id="control-visited-type-el" width="full">
<calcite-radio-group-item value="DESC" checked>Most visited</calcite-radio-group-item>
<calcite-radio-group-item value="ASC">Least visited</calcite-radio-group-item>
</calcite-radio-group>
</calcite-label>
<calcite-label>
Year data to display
<calcite-select id="control-year-el">
<calcite-option label="Total of all time" value="TOTAL"></calcite-option>
<calcite-option label="2018" value="F2018"></calcite-option>
<calcite-option label="2019" value="F2019"></calcite-option>
<calcite-option label="2020" value="F2020"></calcite-option>
</calcite-select>
</calcite-label>
<calcite-label>
Max parks per state
<calcite-slider id="control-count-per-state-el" label-ticks ticks="1" min="1" max="5"></calcite-slider>
</calcite-label>
</calcite-block>
<calcite-block collapsible heading="Results" id="result-block">
2.calcite-radio-group、cacite-select、calcite-slider にid属性が割り当てられていることを確認してください。これらを参照して、結果を更新するタイミングを決定するイベントリスナーを設定します。
};
}
const controlVisitedTypeEl = document.getElementById("control-visited-type-el");
const controlYearEl = document.getElementById("control-year-el");
const controlCountPerStateEl = document.getElementById("control-count-per-state-el");
controlVisitedTypeEl.addEventListener("calciteRadioGroupChange", async (event) => { orderBy = event.target.value, filterItems() });
controlYearEl.addEventListener("calciteSelectChange", async (event) => { year = event.target.value, filterItems() });
controlCountPerStateEl.addEventListener("calciteSliderChange", async (event) => { count = event.target.value, filterItems() });
const countDefault = 1;
const orderByDefault = "DESC"
各イベントリスナーは、カスタム Calcite Components イベントである calciteSelectChange、calciteSliderChange、calciteRadioGroupChange を参照していることを確認してください。
イベントが発生すると、関連するローカル変数を設定し、filterItems() 関数を実行します。実稼働環境では、パフォーマンスを向上させるために、より細かいフィルタリング関数を使用することができます。
リセット アクションを作成
デフォルトのフィルター パラメーターからビューを変更できるイベントを追加したので、オプションをリセットする方法を追加すると便利です。
1.スロットを使用して calcite-action と calcite-tooltip を追加します。
<calcite-block heading="Filters" open>
<div slot="control">
<calcite-action disabled icon="reset" id="control-reset-el"></calcite-action>
<calcite-tooltip reference-element="control-reset-el" position="bottom">
Reset to defaults
</calcite-tooltip>
</div>
<calcite-label>
前のチュートリアルのステップで使用したいくつかの概念に気づくかもしれません。calcite-action の icon 属性を確認してください。Calcite Componentsは、Calcite UI アイコンをロードするために手を貸してくれます。アイコン検索を使用して全アイコンを検索する
disabled 属性も設定されています。ユーザーが作成したパラメーターのセットがデフォルトと異なる場合、それを有効にします。
2.リセットアクションに参照とイベントリスナーを追加します。
const controlVisitedTypeEl = document.getElementById("control-visited-type-el");
const controlYearEl = document.getElementById("control-year-el");
const controlCountPerStateEl = document.getElementById("control-count-per-state-el");
const controlResetEl = document.getElementById("control-reset-el");
controlVisitedTypeEl.addEventListener("calciteRadioGroupChange", async (event) => { orderBy = event.target.value, filterItems() });
controlYearEl.addEventListener("calciteSelectChange", async (event) => { year = event.target.value, filterItems() });
controlCountPerStateEl.addEventListener("calciteSliderChange", async (event) => { count = event.target.value, filterItems() });
controlResetEl.addEventListener("click", async () => resetFilters());
3.determineResetActionState() および resetFilters() 関数を追加します。ここでは、リセット アクションの状態を決定し、ユーザーが要求したときにパラメーターをリセットします。resetFilters() 関数は、クエリのパラメーターをリセットし、コントロールを初期表示にリセットします。フィルター オプションのセットが初期値と一致する場合、またはユーザーが calcite-action を操作する場合、アクションは無効となります。
}
function determineResetActionState() {
if (count !== countDefault .. orderBy !== orderByDefault .. year !== yearDefault) {
controlResetEl.removeAttribute("disabled");
controlResetEl.indicator = true;
}
else {
controlResetEl.disabled = true;
controlResetEl.removeAttribute("indicator");
}
}
function resetFilters() {
count = countDefault;
orderBy = orderByDefault;
year = yearDefault;
const activeRadioGroupItem = document.querySelector(`calcite-radio-group-item[value=${orderByDefault}]`)
activeRadioGroupItem.checked = true;
controlYearEl.value = yearDefault;
controlCountPerStateEl.value = countDefault;
filterItems();
}
filterItems();
4.filterItems() 関数内で、determineResetActionState() 関数を呼び出します。
determineResetActionState();
}
アプリケーションのテーマ
ArcGIS API for JavaScript の機能と Calcite Components を組み合わせることで、リッチなインタラクティブ エクスペリエンスを作成できました。さらに一歩進んで、スタイルを追加して見た目をカスタマイズします。
1.calcite-shellにCSSクラスを追加します。
<calcite-shell class="calcite-tutorial">
2.カスタム スタイルを追加するには、個々のコンポーネントまたはセクションをターゲットにします。
・カスタム ブランドカラーを追加して、color and theming tokens を使用したユニークなエクスペリエンスを作成します。
・追加したカスタム カラーを使用して、スロット付き calcite-chip コンポーネントを目立たせます。
・スロットの calcite-chip コンポーネントに間隔を追加します。
<style>
.calcite-tutorial {
--calcite-ui-brand: #039851;
--calcite-ui-brand-hover: #008D52;
}
.calcite-tutorial calcite-chip {
--calcite-ui-foreground-2: var(--calcite-ui-brand);
--calcite-ui-text-1: white;
margin-inline-end: .75rem;
}
</style>
アプリを実行
CodePenで、マップを表示するコードを実行します。
まとめ
今回は、Calcite Design System を使用した Apply core concepts のサンプルを翻訳して紹介しました。次のステップとして Filter recent earthquakesのチュートリアルも併せて参照してください。
関連リンク
Calcite Design System チュートリアル集
・Tutorials | Calcite Design System | ArcGIS Developers
ArcGIS Developers
ArcGIS 開発リソース集