TechVue.jsJapanese

Vue3 + TypeScript で Mapbox GL JS を使って マップ を表示する サンプル

Tech

Vue3 + TypeScript で Mapbox の マップ を表示する サンプル を紹介します。 create-vue で作成した プロジェクト に Mapbox の 公式 JavaScript クライアント ライブラリである Mapbox GL JS を組み入れることで 簡単に マップ を実装することができます。 一方で Vue3 + TypeScript 環境向けの サンプル はあまり見受けられません。 多少 コツ のようなものも必要でしたので、 本記事で合わせて紹介していきます。

macOS: 12.3
vue: 3.2.31
typescript: 4.5.5
mapbox-gl: 2.7.1
@type/mapbox-gl: 2.6.3

Vue3 + TypeScript プロジェクト の作成

[ads]

それでは最初に 今回使用する Vue3 + TypeScript の プロジェクト を以下の要領で作成します。

  • init vue@3 コマンド で プロジェクト 作成
  • TypeScript のみ追加

なお プロジェクト 作成の詳細は以下の記事を参考にしてください。


Mapbox GL JS の インストール

[ads]

mapbox-gl の インストール

次に 作成した プロジェクト に Mapbox GL JS を 公式 サイト の手順 に従って インストール していきます。 以下の ように npm install コマンド を実行します。

npm install --save mapbox-gl
% npm install --save mapbox-gl

added 29 packages, and audited 143 packages in 7s

18 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

無事 インストール が完了したら、 package.json に 以下のように mapbox-gl が追加されていることを確認することができます。

Type/mapbox-gl の インストール

次に 今回は TypeScript 環境で進めていきますので、 Type/mapbox-gl についても合わせて インストール していきます。 こちらを インストール しないと 以下のような ワーニング が表示されてしまいます。

パッケージ の 公式 サイト の手順に従って インストール していきます。

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

added 2 packages, and audited 145 packages in 3s

18 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

無事 インストール が完了したら、 package.json に 以下のように @types/mapbox-gl が追加されていることを確認することができます。

マップ 表示用の コンポーネント の準備

[ads]

最後に マップ 表示用の コンポーネント を準備しておきます。 今回は 新規に作成する MyMap.vue に マップ 表示部分を実装し App.vue から MyMap.vue を呼び出す シンプル な構成にしたいと思います。

src / App.vue

<script setup lang="ts">
import MyMap from './components/MyMap.vue'
</script>
 
<template>
 <MyMap />
</template>

src / components / MyMap.vue

<script setup lang="ts">
</script>

<template></template>

tsconfig.json

環境によっては、 コンパイラ が以下の エラー を出力する場合があります。 ここでは、以下のように tsconfig.json に Deprecations を無視する設定 (2行目) を追加して対処することにします。

Option 'importsNotUsedAsValues' is deprecated and will stop functioning in TypeScript 5.5. Specify compilerOption '"ignoreDeprecations": "5.0"' to silence this error.
  Use 'verbatimModuleSyntax' instead.
  "compilerOptions": {
    "ignoreDeprecations": "5.0",
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "./src/*"
      ]
    }
  },

ここまでで マップ を表示させるための プロジェクト の準備は完了となります。 次に 実際に マップ の表示部分を実装していきましょう。


マップ 表示の実装

[ads]

Mapbox Access Token の準備

Mapbox の マップ 表示を実装するためには Mapbox アカウント と その アカウント に紐づく Access Token が必要になります。 こちらについては 公式 サイト の手順に従っていただければ 問題なく 作成 取得 ができると思います。 今回は アカウント 作成と同時に生成される Default Public Token を用いて進めていきます。

なお、 以下は iOS 向けの 記事ですが Access Token については Mapbox GL JS と考え方は同じですので 詳細について 参考にしてみてください。

マップ 表示 コンポーネント の実装

それでは 本記事の本題である マップ 表示 コンポーネント の実装を進めていきます。MyMap.vue の script タグ に以下の内容を記載していきます。 今回は 国立競技場 を中心とした マップ を表示していきます。

実装の ポイント は以下の通りです。

  • 4 行目: 公式 サイト の手順に従って mapbox-gl で使用する CSS を インポート します。
  • 6 行目: ‘<your access token here>’ の部分には 上述した Default Public Token の値を指定してください。

環境変数を用いて、安全に Token を設定する方法については こちらの記事 を参考にしてください。

  • 11 行目: container: 生成する マップ の オブジェクト を識別する文字列
  • 13 行目: 生成する マップ の中心地点の 緯度経度 を指定
<script setup lang="ts">
import { onMounted } from 'vue'
import mapboxgl from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css'

mapboxgl.accessToken = '<your access token here>'
 
onMounted(() => {
    const mapObj = new mapboxgl.Map({
        // 国立競技場
        container: 'japan-national-stadium', // container ID
        style: 'mapbox://styles/mapbox/streets-v11', // style URL
        center: [139.714590, 35.678184], // starting position [lng, lat]
        zoom: 14 // starting zoom
    })
})
</script>

template 部分には 上記 container で 指定した 名称を id にもつ div コンテンツ を配置していきます。

<template>
   <div id="japan-national-stadium"></div>
</template>

ここまでで 公式 サイト に記載されている手順 は完了となりますが、 実際にこの状態で npm run dev を用いて アプリケーション を起動しても マップ が表示されていないと思います。 次に この問題に対処していきます。

mapbox-gl.css インポート 問題への対処

色々試したところ 4 行目 に記載した import 文 を コメントアウト すると マップ が表示されるようになることが分かりました。 ただし これでは根本的な解決にはなっていません。コメントアウト した状態で ブラウザ の コンソール を開くと 以下の ワーニング が表示されていることを見つけることができます。

ワーニング の詳細確認

1 つ目の警告は必要な css である mapbox-gl.css が ロードできていないという内容です。

2 つ目の警告は環境固有のため無視できます。 3 つ目の警告は ズームレベル が大きい時に 一部の画像が ロード できなかった というもので これも無視できます。

つまり やはり対処すべきは 1 つ目の mapbox-gs.css に関する問題です。mapbox-gl.css を インポート した状態で マップ が表示できる必要がありそうです。

div の 高さ指定を追加

更に 色々と調査したところ、 以下の情報の通り、「div の 高さを指定する」 ことで マップ が表示されるようになります。 ちなみに 高さの指定は パーセント ではうまくいかず、 px や em といった 実値 を指定する必要があるようでした。

<template>
   <div id="japan-national-stadium" :style="{ height: '20em' }"></div>
</template>

上記の template に修正した後に npm run dev で起動してみると、無事 以下のように マップ を表示することができました。 この部分は今後改善される可能性もありますが 少なくとも mapbox-gl v2.7.1 では必須になってきますので 注意してください。

参考:

Attention Required! | Cloudflare

まとめ

[ads]

init vue@3 で TypeScript を 追加 して プロジェクト 作成

mapbox-gl, @type/mapbox-gl の 2 つを npm install

onMounted フック で mapbox.Map オブジェクト を生成

  • Default Public Token を用いる
  • container に オブジェクト の名称を指定

div タグ に Map 表示部を記載

  • idcontainer で指定した 名称を指定
  • heightpxem で指定

[ads]

今回使用したコード

src / App.vue

<script setup lang="ts">
import MyMap from './components/MyMap.vue'
</script>
<template>
  <MyMap />
</template>
[ads]

src / components / MyMap.vue

<script setup lang="ts">
import { onMounted } from 'vue'
import mapboxgl from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css'

mapboxgl.accessToken = '<your access token here>'

onMounted(() => {
    const mapObj = new mapboxgl.Map({
        // 国立競技場
        container: 'japan-national-stadium', // container ID
        style: 'mapbox://styles/mapbox/streets-v11', // style URL
        center: [139.714590, 35.678184], // starting position [lng, lat]
        zoom: 14 // starting zoom
    })
})
</script>
<template>
    <div id="japan-national-stadium" :style="{ height: '20em' }"></div>
</template>

tsconfig.json

{
  "extends": "@vue/tsconfig/tsconfig.web.json",
  "include": [
    "env.d.ts",
    "src/**/*",
    "src/**/*.vue"
  ],
  "compilerOptions": {
    "ignoreDeprecations": "5.0",
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "./src/*"
      ]
    }
  },
  "references": [
    {
      "path": "./tsconfig.vite-config.json"
    }
  ]
}
[ads]

Ads