NAVITIME_APIは、公式ドキュメントに各機能の詳しい説明はあるものの、とりあえず使ってみたいという方や、自分のような初心者が、ある程度使えるようにするためのものがなかったので、自分にとっての備忘録も兼ねて、今回の記事で紹介させていただきます。今回はNAVITIME_APIの/route_transitについて扱います。
NAVITIME_API/route_transitとは?
公式の説明を確認すると、
公共交通手段+徒歩で、ドアtoドアの最適な移動経路・料金を算出します。駅の出入り口情報なども合わせて取得できます
という説明が書かれています。
この説明はかなり簡潔になっており、実際には移動にかかる時間や経由地、電車の出発、発着時間等様々な情報を取得できます。また、この値を追加することでAPIのみで地図上にルートを表記することも可能です。
注意点
今回紹介する、RapidApiを経由してAPIキーを取得する方法では、バスは検索できず、電車も実際の時刻表に則った時間ではなく、平均時間で表示されます。これらの制限を解除して使うには《NAVITIME》 APIサービスのページから申請してAPIキーを取得する必要があるようです。また、ルートを取得できる回数には限りがあり、無料分は500回と少ないので気をつけた方がいいです。(自分は制限に達してしまい、開発が止まりました。)導入方法
使用するためにはまず、先述した通り、APIキーを取得する必要があります。今回は先述した通り、RapidApiを経由してAPIキーを取得します。
1.RapidApiにログイン、登録
https://rapidapi.com/hubに飛んで画面上部にある、Sign Upをクリックして画面通りに登録を進めます。すでにRapidApiのアカウントがある人はSign Inからログインしてください。
2.RapidApi内で検索
上部検索バーでnavitimeと検索し、一番上に出てきた、NAVITIME Route(totalnavi)を選択します。
3.APIキー取得
右上のSubscribe to Testをクリックし、Basicプランを選択した後、前のページに戻ってX-RapidAPI-Keyの欄に記載のあるAPIキーを取得します。
ルート検索方法
ここまでこれば後は値を入力するだけです。ルート検索に必須になる要素はスタート地点とゴール地点の緯度と経度、出発時間もしくは到着時間です。
必要な値
・スタート地点とゴール地点
緯度と経度を並べるだけです。
例:38,136 (緯度38、経度136)
・出発時間もしくは到着時間
YYYY-MM-DDTHH:MMの形式での時間の入力が必要となります。inputのtype="datetime-local"で取得できる値がこの形式となっています。
実際に取得
・URL
先ほど紹介した必須要素を組み込みます。
//start、goalの値を東京駅と大阪駅、出発時刻を2024年1月1日10:00に指定
let requestUrl = "https://navitime-route-totalnavi.p.rapidapi.com/route_transit?start=35.681236,139.767125&goal=34.702485,135.495951&start_time=2024-01-01T10:00:00"
・requestUrlを使用して検索
fetch関数を使い、requestUrl に対してGETリクエストを送信する関数します。また、その際にはリクエストに付加される情報(HTTPメソッドやヘッダー)を定義して組み込む必要があります。
//APIにデータを取得するリクエスト(GETリクエスト)を送信することを指定し、
//Navitime APIを利用するための認証にAPIキーを入力
const options = {
method: 'GET',
headers: {
'x-rapidapi-key': 'your_api_key',
'x-rapidapi-host': 'navitime-route-totalnavi.p.rapidapi.com'
}
};
//GETリクエストを送信
fetch(requestUrl, options)
.then(response => {
return response.json();
})
.then(data => {
// 検索結果取得完了
console.log(data.items);
});
今回はconsole.log(data.items);で検索結果を呼び出しています。console.log(data);で実行するとdata.unitという値も取得することができますが、こちらは検索方法、表示方法(単位等)についての記述となっています。
検索結果
上の検索で取得できるルートの数は5つとなっており、itemsという配列に含まれています。itemsの下にはsectionsとsummaryというアイテムがあります。
summary
スタート地点とゴール地点、ルート全体でかかる時間、料金、発着時間に付いての情報が得られます。以下に取得できるデータの一例を示します。
summary:
goal:
coord: {lat: 34.702485, lon: 135.495951}
name : "goal"
type: "point"
[[Prototype]]: Object
move:
distance: 556903
fare: {unit_1: 4960, unit_2: 5810, unit_0: 8910, unit_3: 10680}
from_time: "2024-01-01T10:00:00+09:00"
move_type : (3) ['local_train', 'superexpress_train', 'walk']
time: 190
to_time: "2024-01-01T13:10:00+09:00"
transit_count: 1
type: "move"
walk_distance: 503
[[Prototype]]: Object
no: "1"
start:
coord: {lat: 35.681236, lon: 139.767125}
name: "start"
type: "point"
sections
sectionsには、typeの指定がpointのものとmoveのものが交互に入っており、pointには地点情報が、moveにはpoint間をつなぐ移動方法が含まれています。
・point
type = "point"から得られる情報は緯度経度、地点名、駅等に入る入口などです。以下に取得できるデータの一例を示します。
coord: {lat: 35.680576, lon: 139.76861}
gateway: "八重洲中央口"
name: "東京"
node_id: "00006668"
node_types: ['station']
type: "point"
node_typesは配列で複数の値が返ってくることもあります。
・move
以下にtype = "move"から得られる情報は距離、移動方法、発着時間などです。以下に取得できるデータの一例を示します。
distance: 3800
from_time: "2024-01-01T13:00:00+09:00"
line_name: "JR京都線・JR神戸線各停"
move: "local_train"
time: 6
to_time: "2024-01-01T13:06:00+09:00"
transport: {fare: {…}, getoff: '中', name: 'JR京都線・JR神戸線各停', fare_season: 'normal', …}
type: "move"
transportは公共交通期間を使用した際に得られる、その路線に関する料金等の様々な情報が含まれています。以下に取得できるデータの一例を示します。
transport:
company: {id: '00000002', name: 'JR西日本'}
fare : {unit_0: 8910, unit_254: 0}
fare_break: {unit_0: true, unit_254: true}
fare_detail: (2) [{…}, {…}]
fare_season: "normal"
getoff: "中"
id: "00000352"
links:
Array(1)
0: {id: '00000085', name: 'JR東海道本線(米原-神戸)', direction: 'down', destination: {…}, from: {…}, …}
length: 1
[[Prototype]] : Array(0)
name: "JR京都線・JR神戸線各停"
type: "普通"
実際に表示してみる
紹介してきた要素からわかりやすくルート情報を取り出してみます。
<body>
<div id = "result"></div>
</body>
document.addEventListener('DOMContentLoaded', function() {
//startを東京駅、goalを大阪駅、出発時刻を2024年1月1日10:00に指定
let requestUrl = "https://navitime-route-totalnavi.p.rapidapi.com/route_transit?start=35.681236,139.767125&goal=34.702485,135.495951&start_time=2024-01-01T10:00:00"
//APIにデータを取得するリクエスト(GETリクエスト)を送信することを指定し、
//Navitime APIを利用するための認証にAPIキーを入力
const options = {
method: 'GET',
headers: {
'x-rapidapi-key': 'your_api_key',
'x-rapidapi-host': 'navitime-route-totalnavi.p.rapidapi.com'
}
};
fetch(requestUrl,options)
.then(response =>{
return response.json();
})
.then(data => {
//データを入れ込む値を作成
let resultHTML = "";
//今回は1つ目のルートデータのみを使用
let route = data.items[0];
// 出発・到着時刻
resultHTML += `<h3>${route.summary.move.from_time}➡${route.summary.move.to_time}<h3>`;
// summaryからの抜き出し
if(route.summary){
let totalTime = route.summary.move.time; // 合計でかかる時間
resultHTML += `<h4>(${totalTime}分)</h4>`;
if(route.summary.move && route.summary.move.fare && route.summary.move.fare.unit_0){
resultHTML += `<h4>¥${route.summary.move.fare.unit_0}</h4>`; // 合計の運賃
}
}
resultHTML +=`<hr>`;
// section要素をループさせる
route.sections.forEach(function(section) {
let type = section.type;
//type === "move"の処理
if(type === "move"){
//出発時刻
resultHTML += `<h4>${section.from_time}発</h4>`;
//移動手段
if(section.move === "superexpress_train"){
resultHTML += `<h4>新幹線(${section.line_name})</h4>`;
}else if(section.move === "local_train"||section.move === "rapid_train"){
resultHTML += `<h4>電車(${section.line_name})</h4>`;
}else{
//移動方法
resultHTML += `<h4>${section.line_name}</h4>`;
}
//電車を使用していた場合の料金表記
if(section.move === "superexpress_train" || section.move === "local_train"||section.move === "rapid_train"){
if(section.transport.fare){
if(section.transport.fare.unit_0){
resultHTML += `<h4>${section.time}分 ${section.transport.fare.unit_0}円</h4>`;
}else if(section.transport.fare.unit_1){
resultHTML += `<h4>${section.time}分 ${section.transport.fare.unit_1}円</h4>`;
}
}
}else{
resultHTML += `<h4>${section.time}分</h4>`;
}
//到達時刻
resultHTML += `<h4>${section.to_time}着</h4>`;
//type === "point"の処理
} else if(type === "point"){
resultHTML += `<h3> ${section.name}</h3>`;
}
resultHTML += "<hr>";
})
//HTMLのid = "result"に結果を表示
document.getElementById("result").innerHTML = resultHTML;
})
.catch(error => {
console.error('エラーが発生しました:', error);
document.getElementById('result').innerHTML = '<p>経路情報の取得に失敗しました。</p>';
});
});
これをそのまま実行した結果が以下になります。
東京駅から大阪駅までのルートを取得することができました!
地図上にルートを表示させる方法
ルート情報はAPIのリクエストURLに"shape=true"を入れるだけでデータを取得することができます。
let requestUrl = "https://navitime-route-totalnavi.p.rapidapi.com/route_transit?start=35.681236,139.767125&goal=34.702485,135.495951&start_time=2024-01-01T10:00:00&shape=true"
こうすることで、取得できる情報に上で紹介したsummaryとsectionsの他に、shapesが追加されます。このデータはGeoJSON形式となっており、適当な地図に取り込ませれば自動的にルートを形成してくれます。今回はGoogleMapを使ってルートを表示してみます。
<body>
<!--マップ表示エリアを指定-->
<div id="mapArea" style="width:800px; height:400px;"></div>
</html>
<script src="https://maps.googleapis.com/maps/api/js?key=your_api_key&callback=initMap" defer></script>
<script>
//グローバルスコープでmapを定義
let map;
//コールバックでマップを読み込む
function initMap(){
//マップ読み込み
map = new google.maps.Map(document.getElementById("mapArea"), {
zoom: 5,
center: new google.maps.LatLng(36,138),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
}
document.addEventListener('DOMContentLoaded', function() {
//start、goalの値を東京駅と大阪駅、出発時刻を2024年1月1日10:00に指定
let requestUrl = "https://navitime-route-totalnavi.p.rapidapi.com/route_transit?start=35.681236,139.767125&goal=34.702485,135.495951&start_time=2024-01-01T10:00:00&shape=true"
//APIにデータを取得するリクエスト(GETリクエスト)を送信することを指定し、
//Navitime APIを利用するための認証にAPIキーを入力
const options = {
method: 'GET',
headers: {
'x-rapidapi-key': 'your_api_key',
'x-rapidapi-host': 'navitime-route-totalnavi.p.rapidapi.com'
}
};
fetch(requestUrl,options)
.then(response =>{
return response.json();
})
.then(data => {
//データを地図に追加
map.data.addGeoJson(data.items[0].shapes);
})
.catch(error => {
console.error('エラーが発生しました:', error);
document.getElementById('result').innerHTML = '<p>経路情報の取得に失敗しました。</p>';
});
});
</script>
今回追加した要素は、最初にマップを読み込む操作と、
//データを地図に追加
map.data.addGeoJson(data.items[0].shapes);
のみです。飾り気はありませんが、ルート表示だけならこれだけで実現可能です。
指定できる値の紹介
指定できる要素は非常に多いため、今回は個人的におすすめする2つを紹介します。すべて見たい場合は仕様書をチェックしてみてください。
via
経由地を指定できます。最大、10箇所まで指定できます。形式は以下の通りです。
let via = [{"lat":35,"lon":139},{"lat":36,"lon":138}];
配列で、latで緯度を、lonで経度を指定します。これに加えて、stay-timeで滞在時間を指定することもできます。これを発着時点等と同様にリクエストUrlに組み込むのですが、その際にはJSON形式に変更した上でエンコードする必要があります。
//stay-timeも組み込んだ例
let requestUrl = `https://navitime-route-totalnavi.p.rapidapi.com/route_transit?start=35.681236,139.767125&goal=34.702485,135.495951&start_time=2024-01-01T10:00:00&shape=true&via=${encodeURIComponent(JSON.stringify([{"lat":35,"lon":139,"stay-tyme":'5'},{"lat":36,"lon":138}]))}`;
viaの指定時に "" の代わりに '' を使ったり、各パラメータの間に空白を入れたりするとエラーが発生するので気をつけましょう。また、デフォルトだとviaの配列順でルートが検索されますが、クエリにvia_type=optimalを組み込むと最適な順番に並び替えた検索結果を取得できます。
shape_color
マップに表示したルート情報に路線ごとの色等の装飾をつけることができます。リクエストURLにshape_color=railway_lineを組み込むことでデータを取得できます。
//shape_colorを適用するためのルート情報も取得する
let requestUrl = "https://navitime-route-totalnavi.p.rapidapi.com/route_transit?start=35.681236,139.767125&goal=34.702485,135.495951&start_time=2024-01-01T10:00:00&shape=true&shape_color=railway_line"
この結果得られる情報は、shapes.feature.inlineと、shapes.feature.outlineに入っています。今回はとりあえずinlineの方だけを使って装飾してみます。
// スタイルの設定
map.data.setStyle(function(feature){
const inline = feature.getProperty('inline');
return {
strokeColor: inline.color,
strokeWeight: inline.width,
strokeOpacity: inline.opacity,
strokeLineCap: inline.strokelinecap,
strokeLineJoin: inline.strokelinejoin,
};
});
取得するデータは地図上でルートを表示しているfeatureを自動的に参照してくれます。「地図上でルートを表示させる方法」で紹介したコードに上のコードを組み込んで実行した結果が以下になります。
視覚的にわかりやすくなりましたね。
まとめ
NAVITIME APIは取得できる情報が多く、カスタマイズ性があるAPIになっています。地理情報を扱うAPIとしてはGoogleMap APIが有名ですが、NAVITIME APIは今回ルート表示でやったようにGoogleMap APIと組み合わせて使用することも可能です。
長文になってしまいましたが、最後まで読んでいただきありがとうございました。