駅奪取エンジニアのid:dorapon2000です。駅奪取では11月にゲーム内の地図のリプレースを行いました。地図そのもののスタイルも変わりましたが、地図の表示に使うライブラリも変更しています。今回は、アプリに地図を埋め込むだけであれば、ほんの少しのコードだけで実現できるということを紹介したいと思います。
記事の前半で地図表示の仕組みを簡単に説明して、後半で具体的なコードをお見せします。
地図表示の仕組み
地図を表示するためにはサーバ側とクライアント側の2つの仕組みが必要です。また、サーバとクライアントは地図をタイルという形式で送受信します。
- 地図タイルサーバ
- 地図タイルを配信する
- 自前でホストすることもできるが、いずれかのサービスのタイルAPIを利用すると楽
- 地図クライアント
- 地図タイルの受信と表示をする
- 地図の上にピンや吹き出しを置くこともできる
タイルにはベクトルタイルとラスタタイルの2種類があり、地図を座標情報として受け取るか、画像として受け取るかという違いがあります。ちょうど画像の.svgと.pngの関係に近いです。例えば、ラスタタイルで配信されている場合は、地図クライアントもラスタタイルに対応している必要があります。
本記事のサンプルコードでは、タイルAPIを利用し、ラスタタイルで地図を表示します。
地図タイルAPI
地図タイルAPIを提供しているサービスはいくつかあります。
- OpenStreetMapのタイルAPI
- 無料で商用利用可能なものとそうでないものがある
- MapboxのタイルAPI
- 登録をすることで、一定まで無料で利用可能1
- 地理院タイル
- Webサイトの一部として地図を表示する場合、利用申請不要2
サンプルコードではクレジットを入れることで無償利用可能な「OpenStreetMap's Standard tile layer(リンク先テーブルの一番上)」を利用します。
地図クライアントライブラリ
地図クライアントライブラリもいくつかあります。
- Leaflet
- ラスタタイル対応
- 無償利用可能3
- Mapbox GL JS
- ベクトルタイル対応
- 登録してアクセストークンを取得することで、一定まで無料で利用可能4
- MapLibre GL JS
- ベクトルタイル対応
- Mapbox GL JS v1のフォークプロジェクトで、登録不要で無償利用可能5
サンプルコードでは地図クライアントライブラリとして真っ先に選択肢になるであろうLeafletを利用します。昔から親しまれているライブラリで、個人的に初期学習コストも大きくないと思います。
OpenStreetMap + Leaflet
本題です。地図タイルサーバとして「OpenStreetMapのAPI」を、地図クライアントライブラリとして「Leaflet」を利用します。タイルの形式はラスタです。
https://codepen.io/dorapon2000/pen/xxXqzgM
<head> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/> <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script> </head> <body> <div id="mapid"></div> </body>
const mymap = L.map('mapid').setView([35.6810,139.7670], 14); L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: "<a href='https://www.openstreetmap.org/copyright' target='_blank'>© OpenStreetMap contributors</a>" }).addTo(mymap);
たったこれだけで地図が表示できてしまいます!
htmlでしていることは、LeafletのCSSとJSの読み込みと地図を表示するdivの定義だけです。LeafletのJSを読み込むと、LeafletモジュールがL
というグローバル変数として登録されます。javascript側では、div#mapid
に地図を表示しています。setViewの引数の3つの数字は、前から緯度・経度・ズームレベルを表します。tileLayerでOpenStreetMapのAPIを叩いて地図を取得します。
最後に、LeafletとOpenStreetMapの地図データを利用していることを忘れずクレジットします。
ここへ少しコードを付け加えることで、ピンを立てたり、吹き出しをつけたり、ラインを引いたりすることができるようになります。Leaflet公式が提供するサンプルコードも充実しているため、まずは目的のコードに近いサンプルを探すのが良いと思います。