31
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SC(非公式)Advent Calendar 2019

Day 23

Vue.jsとMapbox GL JSでオリジナルの地図を表示してみよう ~Mapbox GL JSの機能を知る編~

Last updated at Posted at 2019-12-23

はじめに

Vue.jsとMapbox GL JSを使って、このような機能を実装していきます。

  • 地名検索
  • 国名・地名の日本語化
  • 位置情報表示

VueMapbox といったラッパーライブラリもありますが、
Mapbox GL JSの機能を知る編ということで、使わずに進めていきたいと思います。
結果として、Vue.jsの機能は全く使っていませんが・・・
次のステップとして、プラグイン化などしていけたらと思います:bow_tone1:

mapboxとは

mapboxは、地図を使用したアプリ開発者向けのプラットフォームです。 そのなかでMapbox GL JSは、Web GLを使用して地図を表示するJavaScriptライブラリです。 その他の地図サービス・APIに比べて、カスタマイズ性が高いとされています。

環境構築

Vue.jsのプロジェクト作成とMapbox GL JSのインストールを行います。

Vue CLIでプロジェクト作成

vue create mapbox-vue

今回はMapbox GL JSの機能を試したいので、
Vue RouterもVuexもなしのシンプルなプロジェクトにしています。

? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Linter
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
? Pick a linter / formatter config: Prettier
? Pick additional lint features: Lint on save, Lint and fix on commit
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files

Vue CLI Installation
Vue CLI Creating a Project

Mapbox GL JSのインストール

  1. npmでMapbox GL JSをインストール

    npm install mapbox-gl @types/mapbox-gl --save
    

    ※TypeScriptを使用しているため、typesもインストールしています。

  2. /public/index.html へ以下を追加し、CSSを読み込む

    /public/index.html(抜粋)
    <link href="https://api.mapbox.com/mapbox-gl-js/v1.4.1/mapbox-gl.css" rel="stylesheet" />
    

    Mapbox GL JS Install

mapboxアカウント作成

Access Tokenを取得するため、
Create your Mapbox accountからアカウントを作成します。
SignUpするとAccountページにAccess Tokenが表示されます。
image.png

料金体系は、Webの場合50,000回までのマップ読み込みは無料となっています。
詳細は、Mapbox pricingへ。

マップを表示する

まずは、マップを表示してみましょう。
/src/components/MyMap.vue を追加します。
これからこのファイルを編集して機能を追加していきます。
Your Access Token の箇所は、先ほど取得したAccess Tokenに変更してください。

/src/App.vue
<template>
  <div id="app">
    <my-map />
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import MyMap from './components/MyMap.vue'

@Component({
  components: {
    'my-map': MyMap
  }
})
export default class App extends Vue {}
</script>

<style>
body {
  padding: 0;
  margin: 0;
}
#app {
  height: 100vh;
}
</style>
/src/components/MyMap.vue
<template>
  <div id="map"></div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import mapboxgl, { MapboxOptions, Map } from 'mapbox-gl'

@Component({})
export default class extends Vue {
  map: Map = {} as Map
  option: MapboxOptions = {
    accessToken: 'Your Access Token',
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v8',
    center: [143.767125, 38.681236],
    zoom: 4
  }

  mounted() {
    this.map = new mapboxgl.Map(this.option)
  }
}
</script>

<style scoped>
#map {
  width: 100%;
  height: 100%;
}
</style>

すると、このように地図が表示されます!
image.png

仕組み

  1. mapbox-gl を読み込む

    /src/components/MyMap.vue
    import mapboxgl, { MapboxOptions, Map } from 'mapbox-gl'
    
  2. mapboxのオプションを設定する

    /src/components/MyMap.vue(抜粋)
    option: MapboxOptions = {
      accessToken: 'Your Access Token',
      container: 'map',
      style: 'mapbox://styles/mapbox/streets-v8',
      center: [143.767125, 38.681236],
      zoom: 4
    }
    

設定できるオプションの詳細は、Mapbox GL JS API reference Map へ。
accessTokencontainerは必須になります。
containerには、マップをバインドするタグのidを指定します。

  1. マップをバインドするタグを作成し、高さを指定する

    /src/App.vue(抜粋)
    <style>
    body {
      padding: 0;
      margin: 0;
    }
    #app {
      height: 100vh;
    }
    </style>
    
    /src/components/MyMap.vue(抜粋)
    <template>
      <div id="map"></div>
    </template>
    
    <style scoped>
    #map {
      width: 100%;
      height: 100%;
    }
    </style>
    
  2. Mapオブジェクトを生成する

    /src/components/MyMap.vue(抜粋)
    mounted() {
      this.map = new mapboxgl.Map(this.option)
    }
    

DOM作成後である必要があるので、mountedフックでMapオブジェクトを生成します。
このMapオブジェクトに、マップを操作するファンクションやイベントが定義されています。

検索機能を追加する

次に、検索機能を追加してみましょう。
検索機能は、mapbox-gl-geocoder プラグインから提供されています。

  1. npmで mapbox-gl-geocoder をインストール

    npm install @mapbox/mapbox-gl-geocoder --save
    
  2. /public/index.html へ以下を追加し、CSSを読み込む

    /public/index.html(抜粋)
    <link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.4.2/mapbox-gl-geocoder.css" rel="stylesheet" />
    

    GitHub mapbox-gl-geocoder

  3. Map オブジェクトにコントロールを追加

    /src/components/MyMap.vue(抜粋)
      <script lang="ts">
      // 省略
      const MapboxGeocoder = require('@mapbox/mapbox-gl-geocoder')
    
      @Component({})
      export default class extends Vue {
        // 省略
        mounted() {
          this.map = new mapboxgl.Map(this.option)
          this.map.addControl(
            new MapboxGeocoder({
              accessToken: this.option.accessToken,
              mapboxgl: mapboxgl
            })
          )
        }
      }
      </script>
    

すると、このように検索ができるようになります。
mapbox検索.gif

仕組み

検索時には、Geocoding API が呼ばれています。

GET https://api.mapbox.com/geocoding/v5/{endpoint}/{search_text}.json

Mapbox GL JSから、このような Control などのUIも提供されていますし、APIとしても提供されていますので、UIを自作することもできます。
その他のAPIの詳細は、mapbox API Documentation へ。

地名を日本語化する

英語のままでは見づらいので、日本語化してみましょう。
日本語化は、mapbox-gl-language プラグインから提供されています。

  1. npmでmapbox-gl-languageをインストール

    npm install @mapbox/mapbox-gl-language --save
    

    GitHub mapbox-gl-language

  2. Mapオブジェクトにコントロールを追加

    /src/components/MyMap.vue(抜粋)
      <script lang="ts">
      // 省略
      const MapboxLanguage = require('@mapbox/mapbox-gl-language')
    
      @Component({})
      export default class extends Vue {
        // 省略
        mounted() {
          this.map = new mapboxgl.Map(this.option)
          // 省略
          this.map.addControl(
            new MapboxLanguage({
              defaultLanguage: 'ja'
            })
          )
        }
      }
      </script>
    

すると、このように国名や地名が日本語になります。
image.png

マップのスタイルを作成する

Mapbox Studioでは、Web上で好きなスタイルを作成することができます。

Mapbox Studio での編集

  1. New styleをクリック
    image.png

  2. 好きなテンプレートを選択し、Customize xxxをクリック
    image.png

  3. エディターが表示される
    image.png

ここで様々な編集ができます。
詳しい使い方は、Mapbox Studio Manual へ。

今回は、日本語のSatellite Streetsを作成しました。

作成したスタイルの適用

  1. シェアアイコンをクリック
    Mapbox Studio share.png

  2. Style URLをコピー
    Mapbox Studio style.png

  3. optionstyleを変更

    /src/components/MyMap.vue(抜粋)
      <script lang="ts">
      // 省略
    
      @Component({})
      export default class extends Vue {
        // 省略
        option: MapboxOptions = {
          accessToken: 'Your Access Token',
          container: 'map',
          style: 'Copied Style URL',
          center: [143.767125, 38.681236],
          zoom: 4
        }
        // 省略
      }
      </script>
    

すると、作成したスタイルが適用されます。
image.png

位置情報を表示する

最後に、位置情報を表示してみましょう。
今回は私の好きな美術館を表示してみたいと思います。

  1. レイヤーを追加

    /src/components/MyMap.vue(抜粋)
    <script lang="ts">
    // 省略
    @Component({})
    export default class extends Vue {
      // 省略
      mounted() {
        // 省略
        this.map.on('load', () => {
          this.map.addLayer({
            id: 'points',
            type: 'symbol',
            source: {
              type: 'geojson',
              data: {
                type: 'FeatureCollection',
                features: [
                  {
                    type: 'Feature',
                    geometry: {
                      type: 'Point',
                      coordinates: [139.775792, 35.715622]
                    },
                    properties: {
                      title: '国立西洋美術館',
                      icon: 'museum'
                    }
                  },
                  {
                    type: 'Feature',
                    geometry: {
                      type: 'Point',
                      coordinates: [139.630669, 35.457194]
                    },
                    properties: {
                      title: '横浜美術館',
                      icon: 'museum'
                    }
                  },
                  {
                    type: 'Feature',
                    geometry: {
                      type: 'Point',
                      coordinates: [139.051066, 35.2454]
                    },
                    properties: {
                      title: '彫刻の森美術館',
                      icon: 'museum'
                    }
                  },
                  {
                    type: 'Feature',
                    geometry: {
                      type: 'Point',
                      coordinates: [139.021225, 35.256709]
                    },
                    properties: {
                      title: 'ポーラ美術館',
                      icon: 'museum'
                    }
                  },
                  {
                    type: 'Feature',
                    geometry: {
                      type: 'Point',
                      coordinates: [139.726423, 35.665322]
                    },
                    properties: {
                      title: '国立新美術館',
                      icon: 'museum'
                    }
                  }
                ]
              }
            },
            layout: {
              'icon-image': ['concat', ['get', 'icon'], '-15'],
              'text-field': ['get', 'title'],
              'text-font': ['ヒラギノ角ゴ Pro W3', 'メイリオ', 'sans-serif'],
              'text-offset': [0, 0.6],
              'text-anchor': 'top'
            }
          })
        })
      }
    }
    </script>
    

すると、このようにアイコンと地名が表示されます。
image.png

仕組み

様々なレイヤーを組み合わせることでマップを表示しています。
Layerには主に typesorcelayoutpaint が設定できます。
詳しい仕様は、mapbox Style Specification Layers へ。

今回は 座標アイコン表示 するので、
typesymbolsourcegeojson にしています。

GeoJSON とは

地理空間を表現するためのJSONフォーマットです。
詳しい仕様は、GeoJSON へ。

おわりに

ここまでMapbox GL JSの主要な機能を見てきました。
mapboxのSolutionsには、様々なユースケースが紹介されていますので、こちらもぜひ!

業務ではラッパーライブラリを使用していますが、もう少し自由度がほしいと思うこともしばしば・・・。
次は、ここからVue.jsのアプリとしてもっと使いやすくしていきたいと思います:bow_tone1:

31
20
2

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
31
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?