1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptでのNAVITIME_APIの利用方法

Last updated at Posted at 2024-10-06

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と組み合わせて使用することも可能です。
長文になってしまいましたが、最後まで読んでいただきありがとうございました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?