Amazon Location SDKとAPIキーでルート検索機能を構築
これまで、Amazon Location Serviceを利用するには、手動で設定をおこなうか、Amplify Geoで設定(ルート検索機能は未対応)という選択肢がありました。昨年、Amazon Location SDKとAPIキー機能が発表され、選択肢がさらに広がりました。今回は、この新機能を利用したルート検索機能について紹介します。
GitHubで作成した環境を公開しています。ぜひご利用ください。
事前準備
Amazon Location ServiceのAPIキー作成
実行環境
- node v20.0.0
- npm v9.6.4
MapLibre GL JS & Amazon Location Service スターター
はじめに、既存のスターターで環境構築をします。ローカル環境にforkまたはダウンロードし動作確認をします。
maplibregljs-amazon-location-service-starter
全体構成
.env
事前準備で作成したリージョン・マップAPIキー・マップ名をenvファイルに設定します。
VITE_REGION = xxxxx
VITE_MAP_API_KEY = v1.public.xxxxx
VITE_MAP_NAME = xxxxx
パッケージをインストールします。
npm install
ローカルサーバーを起動します。
npm run dev
Amazon Location SDKのインストール
次に、Amazon Location SDKの必要なライブラリをインストールします。インストールすることで、APIの認証やMapLibre GL JSとの組み合わせが手軽になります。
client-location
AWS SDKをインストールします。"client-location"はAmazon Location Serviceを操作できるSDKです。
npm install @aws-sdk/client-location
amazon-location-utilities-auth-helper
"amazon-location-utilities-auth-helper"をインストールします。Amazon Location ServiceのAPIキーとCognitoの認証が手軽になるライブラリです。
npm install @aws/amazon-location-utilities-auth-helper
amazon-location-utilities-datatypes
"amazon-location-utilities-datatypes"をインストールします。Amazon Location ServiceのレスポンスをGeoJSON形式に変換してくれるライブラリです。
npm install @aws/amazon-location-utilities-datatypes
"amazon-location-utilities-datatypes"について、MapLibre GL JSと組み合わせると一部利用しにくかったため、先日オプション機能を追加するコントリビュートをしました。
ルート検索機能の構築
最後に、実際にルート検索機能を構築します。スターターから一部のファイル変更をします。
package.json
{
"name": "maplibregljs-amazon-location-service-route-calculators-starter",
"version": "4.0.2",
"description": "",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"keywords": [],
"author": "MapLibre User Group Japan",
"license": "ISC",
"devDependencies": {
"typescript": "^5.3.3",
"vite": "^5.1.4"
},
"dependencies": {
"@aws-sdk/client-location": "^3.521.0",
"@aws/amazon-location-utilities-auth-helper": "^1.0.4",
"@aws/amazon-location-utilities-datatypes": "^1.0.5",
"maplibre-gl": "^4.0.2"
}
}
.env
事前準備で作成したリージョン・マップAPIキー・マップ名・ルーティングAPIキー・ルーティング名をenvファイルに設定します。
VITE_REGION = xxxxx
VITE_MAP_API_KEY = v1.public.xxxxx
VITE_MAP_NAME = xxxxx
VITE_ROUTE_API_KEY = v1.public.xxxxx
VITE_ROUTE_NAME = xxxxx
main.ts
import './style.css'
import 'maplibre-gl/dist/maplibre-gl.css';
import maplibregl from 'maplibre-gl';
import { LocationClient, CalculateRouteCommand } from "@aws-sdk/client-location";
import { routeToFeatureCollection } from '@aws/amazon-location-utilities-datatypes';
import { withAPIKey } from '@aws/amazon-location-utilities-auth-helper';
const region = import.meta.env.VITE_REGION;
const mapApiKey = import.meta.env.VITE_MAP_API_KEY;
const mapName = import.meta.env.VITE_MAP_NAME;
const routeApiKey = import.meta.env.VITE_ROUTE_API_KEY;
const routeName = import.meta.env.VITE_ROUTE_NAME;
async function initialize() {
const authHelper = await withAPIKey(routeApiKey);
const client = new LocationClient({
region: region,
...authHelper.getLocationClientConfig()
});
const input = {
CalculatorName: routeName,
DeparturePosition: [139.7558, 35.6767],
DestinationPosition: [139.8160, 35.6830],
IncludeLegGeometry: true,
};
const command = new CalculateRouteCommand(input);
const response = await client.send(command);
const featureCollection = routeToFeatureCollection(response, {
flattenProperties: true
});
const map = new maplibregl.Map({
container: 'map',
style: `https://maps.geo.${region}.amazonaws.com/maps/v0/maps/${mapName}/style-descriptor?key=${mapApiKey}`,
center: [139.767, 35.681],
zoom: 11,
});
map.addControl(
new maplibregl.NavigationControl({
visualizePitch: true,
})
);
map.on('load', function () {
map.addSource("route-result", {
type: "geojson",
data: featureCollection
});
map.addLayer({
'id': "route-result",
'type': 'line',
'source': 'route-result',
'layout': {
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': '#FF0000',
'line-width': 10,
'line-opacity': 0.5
}
});
map.on('click', 'route-result', (e) => {
const coordinates = e.lngLat;
const description = `${e.features?.[0]?.properties['Distance'] ?? ''}km`;
new maplibregl.Popup()
.setLngLat(coordinates)
.setHTML(description)
.addTo(map);
});
map.on('mouseenter', 'route-result', () => {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'route-result', () => {
map.getCanvas().style.cursor = '';
});
});
}
initialize();
Amazon Location SDKを定義します。
import { LocationClient, CalculateRouteCommand } from "@aws-sdk/client-location";
import { routeToFeatureCollection } from '@aws/amazon-location-utilities-datatypes';
import { withAPIKey } from '@aws/amazon-location-utilities-auth-helper';
APIキーの認証設定をします。
const authHelper = await withAPIKey(routeApiKey);
const client = new LocationClient({
region: region,
...authHelper.getLocationClientConfig()
});
指定位置でルート検索をします。
const input = {
CalculatorName: routeName,
DeparturePosition: [139.7558, 35.6767],
DestinationPosition: [139.8160, 35.6830],
IncludeLegGeometry: true,
};
const command = new CalculateRouteCommand(input);
const response = await client.send(command);
ルーティングのレスポンスをGeoJSONに変換します。
const featureCollection = routeToFeatureCollection(response, {
flattenProperties: true
});
ローカルサーバーで確認
npm run dev
Discussion