Webやネイティブアプリで地図表示・操作をしたいときのライブラリ選定、使用で考えたいこと
技術スタック Javascriptネイティブアプリ

Webやネイティブアプリで地図表示・操作をしたいときのライブラリ選定、使用で考えたいこと

2024.08.31

こんにちはjunです。私は個人開発でRouteShareとよばれる地図を用いた地理情報・アクティビティ共有型webサービスを運営・開発しています。そのサービスではGoogle Map APIを使用して地図を表示したり、ユーザーが任意にピンをおいたりラインを引いたり、地図上から検索できるといった機能を持たせています。このように地図を表示したり、何かしら地図上で編集する機能などをサービスに加えたい時にGoogle Map APIやMapbxのSDKを使用することが多いと思います。しかし課金の体系がわからなかったり、意外と価格がすることもあります。

今回の記事では

  • 地図ライブラリに必要なこと
  • いかにしてwebなどで地図を表示するのか
  • 最低限の構成で低コストで運用する方法
  • メジャーライブラリの課金体系

という4点について詳細な内容をお伝えしたいとおもいます。主にこれから地図を利用したアプリケーションを開発、運営したいと思う技術者向けの内容です。

地図を表示して操作するということ

Google MapやMapboxなどの地図ライブラリを使用して地図を表示し、操作できることは当たり前のように感じるかもしれませんが、その裏側には複雑な仕組みが存在します。ここでは、その仕組みをわかりやすく解説します。

様々な操作に応じて指定した地図を表示する

地図アプリを使う際、ユーザーはズームイン・ズームアウト、パン(スワイプ)などの操作を行います。この時、地図ライブラリはその操作に応じて、表示する地図データを動的に更新します。例えば、ズームインすると、現在の中央緯度経度を基点に、より詳細な地図データを読み込み、表示範囲を狭めることで、より詳細な情報を表示します。

地図を表示するためにはタイル画像を読み込んでいる

地図データは大きな一枚の画像ではなく、「タイル」と呼ばれる小さな画像に分割されています。これにより、地図を表示する際には、ユーザーの画面に表示される部分だけを効率的に読み込むことができます。例えば、ズームインしたり、パンしたりするたびに、必要な範囲のタイル画像が新たに読み込まれ、表示されます。Googleのネットワークを見てみるとこのようにタイルごとの画像をリクエストされているのがわかります。

どこを表示しているのかをJSなどで制御し、必要なタイルをリクエストする

地図ライブラリはJavaScriptなどを使って、現在の表示範囲やズームレベルを管理し、それに基づいて必要なタイル画像をサーバーにリクエストします。これにより、無駄なデータの読み込みを避け、効率的に地図を表示することができます。例えば、ユーザーが画面を移動させた際、表示範囲が変わったことを検知し、その範囲に対応するタイル画像を新たに取得して表示します。

球体の地球を平面で問題なく表示できるようにするための工夫

地球は球体ですが、地図は平面に表示されます。この変換には「メルカトル図法」などの投影法が使われています。メルカトル図法は、経緯度を一定の間隔で平面に投影することで、球体の地球を平面の地図として表示することができます。ただし、この方法では緯度が高いほど形が歪むため、特に高緯度地方では地図のスケールが大きくなります。

地図をスクラッチで開発する場合の考慮点

もし、地図表示機能をスクラッチで開発しようと考えると、いくつか非常に重要な技術や知識が必要となります。まず、地球は球体であるため、それを平面の地図として正確に表現するためには、地理計算技術や地学に関する深い知識が不可欠です。例えば、メルカトル図法などの投影法を用いて、経緯度を正確に平面に変換する必要があります。

さらに、ユーザーがズームイン・ズームアウト、パンなどの操作を行うたびに、その表示位置を正確に計算し、適切な地図データを表示するためのアルゴリズムが求められます。このような技術を実装するには、数学的な計算だけでなく、地理情報システム(GIS)に関する知識も必要です。

また、実際に地図を表示するためには、膨大な数のタイル画像を効率的に管理し、提供するためのタイルサーバも不可欠です。これを自前で構築するとなると、莫大なデータ容量を持つサーバと、それを高速に処理・配信するためのインフラが必要となります。例えば、地球全体をカバーするタイル画像をすべて用意した場合、その総データサイズは数百GBから数TBに達することがあります。

タイルサーバの必要枚数の計算 地球全体をカバーするためのタイル画像の総枚数は、ズームレベルに依存します。タイルの総枚数は、ズームレベルz に対して次の式で計算されます:

タイル枚数 = 2^(2z)

例えば、ズームレベル0では1枚、ズームレベル1では4枚、ズームレベル2では16枚のタイルが必要です。ズームレベルが上がるごとに、必要なタイル枚数は指数関数的に増加します。ズームレベル10の場合、約1,048,576枚、ズームレベル15では約1,073,741,824枚ものタイルが必要となります。まして言語ごとに表示を変えるとならにさらに必要となります。

これらを保存し、ユーザーに迅速に提供するためには、高性能かつ大容量のストレージが必要となり、その運用コストも無視できません。静的でないサーバーサイドレンダリングでもサーバーパワーとキャッシュを工夫する知識が必要です。

特に、Web上で地図を描画する際には、CanvasやWebGLなどの描画技術が使われます。これにより、地図データをピクセル単位で描画し、ユーザーの操作に応じてリアルタイムで更新することが可能です。しかし、このような技術を一から実装することは非常に手間がかかり、パフォーマンスの最適化やブラウザ間の互換性を考慮する必要があります。

さらに、Google Mapを例にとると、短く・狭い範囲での2点は直線ですが広い範囲では曲線になります。実際は球面に沿ったまっすぐな線を引いていますが、それを平面に表した結果です。

このように、広範囲での地図表示には特有の課題があり、それらを解決するための技術が必要となります。

メジャーライブラリ・タイルサーバの仕組みと課金体系

地図表示ライブラリやタイルサーバは、地図アプリケーションの開発において重要な要素です。ここでは、代表的なライブラリとタイルサーバの紹介とともに、それぞれのメリット、デメリット、制限事項、そして課金体系について解説します。なお2024年8月現在の内容です。

地図表示ライブラリ

Google Map SDK

メリット:世界中で広く使用され、信頼性が高い。多機能で詳細な地図データやストリートビューなど豊富なAPIを提供。ドキュメントが充実し、コミュニティサポートも豊富。SDK以外にも地理計算ライブラリが含まれており、高度なカスタマイズが可能。

デメリット:課金体系が比較的高額で、使用量が増えるとコストが急増する可能性がある。特定のデータや機能に制約がある場合がある。

制限事項:無料使用枠があるが、一定のリクエスト数を超えると課金が発生する。Googleの著作表示が必要。

課金体系:web・ネイティブ共に月間のSDKリクエスト数に基づく従量課金制。SDKのインスタンス作成時に課金され、料金はAPIごとに異なり、使用する機能によって変動する。

Mapbox SDK

メリット:新興のプラットフォームで、Google Mapよりオープンかつデベロッパーフレンドリー。高度にカスタマイズ可能で、地図のデザインやデータ表示を柔軟にコントロールできる。料金体系がGoogle Mapより安価で、小規模なプロジェクトやスタートアップに適している。

デメリット:Google Mapに比べてコミュニティ規模が小さく、サポートリソースが限られる場合がある。人気が出た場合、Google Mapに近い価格になる可能性がある。

制限事項:商用利用時に無料枠を超えると従量課金が発生する。Mapboxの著作表示が必要。

課金体系:web版はSDKのインスタンス作成時をSDKリクエストとして課金、ネイティブ版はアクセストークンから計測されるアクティブユーザー数に基づく。

Leaflet.js

メリット:軽量でシンプルなオープンソースライブラリでカスタマイズ性が高い。大規模な地図アプリケーションだけでなく、軽量な地図表示にも適しており、無料で使用可能。

デメリット:標準機能は少なく、複雑な機能や高度なカスタマイズには他のプラグインやライブラリが必要。自前でタイルサーバを用意する必要がある場合がある。

制限事項:オープンソースのため、サポートはコミュニティに依存する部分が大きい。

課金体系:Leaflet.js自体は無料。ただし、タイルサーバ利用には別途コストが発生する場合がある。

タイルサーバ

MapTiler

メリット:高品質な地図タイルを提供し、世界中の地図データにアクセス可能。カスタマイズが容易で商用利用もサポート。

デメリット:高度な機能や大規模な使用にはそれ相応のコストがかかる。

制限事項:商用利用には有料プランが必要。

課金体系:利用量に応じた従量課金制で、使用するタイル数やアクセス頻度に基づいて料金が決まる。

OpenStreetMap

メリット:オープンソースプロジェクトであり、無料で利用可能。世界中のユーザーがデータを提供し、地図データが豊富。主にテスト時や地図を印刷する際に使用される。

デメリット:商用利用は基本的に不可能で使用には制限がある。データの正確性や一貫性にバラつきがある場合がある。アクセスしすぎるとブロックされる。

制限事項:大規模な商用プロジェクトでの利用は推奨されない。

課金体系:無料で使用可能だが、商用利用時には著作表示が必要。

Mapbox Tile Server

メリット:高品質な地図タイルを提供し、Mapbox SDKとの統合が容易。高度にカスタマイズ可能で、デザインや機能を自由に変更できる。

デメリット:使用量に応じてコストがかかるため、大規模なプロジェクトでは費用が高くなる可能性がある。

制限事項:無料使用枠があるが、商用利用には有料プランが必要。

課金体系:使用するタイル数やユーザー数に応じた従量課金制。

Google Map Tile

メリット:信頼性が高く、Googleの地図データを利用可能。多機能で、他のGoogleサービスとの連携が容易。

デメリット:料金が高めで、使用量が増えるとコストが急増する可能性がある。

制限事項:一定の無料枠を超えると課金が発生する。

課金体系:タイルのリクエスト数に基づいた従量課金制。

webでの最小の構成

Webアプリケーションで地図を表示する際、コストを抑えつつシンプルに構成するためには、軽量な地図ライブラリと信頼性の高いタイルサーバを選ぶことが重要です。ここでは、Leaflet.jsとMapboxのタイルサーバを使用した最小構成について説明します。

1. Leaflet.jsの導入

Leaflet.jsは、軽量でシンプルなオープンソースのJavaScriptライブラリです。基本的な地図表示機能を備えており、軽量でありながら高いカスタマイズ性を持っています。まずは、Leaflet.jsをプロジェクトに導入します。

<!DOCTYPE html>
<html>
<head>
    <title>Leaflet Map</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
</head>
<body>
    <div id="map" style="width: 600px; height: 400px;"></div>
    <script>
        var map = L.map('map').setView([51.505, -0.09], 13);

        L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=YOUR_MAPBOX_ACCESS_TOKEN', {
            maxZoom: 18,
            id: 'mapbox/streets-v11',
            tileSize: 512,
            zoomOffset: -1,
            accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN'
        }).addTo(map);
    </script>
</body>
</html>

2. Mapboxタイルサーバの契約と設定

Leaflet.js自体は無料で利用できますが、タイル画像を提供するサーバが必要です。ここでは、Mapboxのタイルサーバを契約します。Mapboxは信頼性が高く、カスタマイズ性に優れたタイルサーバを提供しています。また無料枠内であればタイルも無料で利用できます。

  1. Mapboxの公式サイトでアカウントを作成します。
  2. タイルを作成し、アクセストークンを取得し、上記のLeaflet.jsのコードにある YOUR_MAPBOX_ACCESS_TOKEN の部分に取得したアクセストークンを入力します。
  3. 必要に応じて、地図のスタイルやズームレベルをカスタマイズできます。

3. 最小構成のメリットと注意点

この最小構成では、Leaflet.jsの軽量なコードとMapboxの高品質なタイルサーバを組み合わせて、低コストでシンプルな地図表示を実現できます。ただし、商用利用の場合は、Mapboxの料金体系に注意し、利用量に応じたプランを選択する必要があります。 また、シンプルな構成であるため、複雑なカスタマイズや高負荷のユースケースには向いていない場合があります。プロジェクトの規模や要件に応じて、適切なライブラリやサーバ構成を検討することが重要です。

部分的な仕様の場合

特定の地域や用途に限定した地図表示を行う場合、全世界をカバーする必要がないため、タイルアクセスを最適化することが可能です。ここでは、部分的な仕様における地図表示の方法について説明します。

1. エリア制限によるタイルアクセスの節約

特定の地域のみを対象とする場合、表示できるエリアを緯度経度範囲とズームレベルで制限することで、無駄なタイルアクセスを減らし、コストを節約できます。例えば、都市単位での地図表示や、特定の観光地を中心にしたアプリケーションの場合、必要最小限のエリアだけを表示するよう設定することで、効率的なタイルアクセスが可能です。

var map = L.map('map', {
    center: [35.6895, 139.6917], // 東京の緯度経度
    zoom: 12,
    maxBounds: [
        [35.0, 138.0], // 南西端
        [36.0, 140.0]  // 北東端
    ]
});

2. Webでの利用:Leaflet.jsの活用

Webアプリケーションにおいて、軽量でカスタマイズ性の高いLeaflet.jsを利用することは有効です。Leaflet.jsは、シンプルな実装で特定エリアの地図表示を行うことができ、タイルサーバへのアクセスを最小限に抑えることができます。

3. 日本国内のみの利用:国土地理院のタイルサーバ

日本国内のみを対象とする場合、国土地理院が提供するタイルサーバを利用することも一つの選択肢です。国土地理院のタイルは無料で利用可能で、日本の詳細な地図データを提供しています。Leaflet.jsと組み合わせることで、日本国内での特定エリアを効率的に表示することが可能です。

L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
    maxZoom: 18,
    attribution: '© 国土地理院'
}).addTo(map);

このように、部分的な仕様の場合には、地図表示エリアを限定することで、コストを抑えつつ必要な情報を提供することが可能です。利用する地域や用途に応じて、最適な構成を選択してください。

結論

とりあえず内容はこの通りです。記述した通り、地図表示というのはそれなりのサーバコストやライブラリの開発コストが高いため、ある意味一部のサービスの寡占状態になっています。しかし地図表示は非常にわかりやすく需要が多いためgoogle mapが高くても使わざる得ないような状態になっています。ですが、google map SDK以外にも上記の最小構成などである程度コストを節約することができるので、小さいサービスや自治体が地図を使用したいときなどに利用できます。ちなみにネイティブの場合はSDKに当たるものにleaflet.jsのようなものがないので難しいです。私もreact nativeで探したのですが見当たらない様子です。この辺は調べてまた見つかったら更新しようと思います。

参考

Copyright © 2021 jun. All rights reserved.