Vue.jsを利用した地図アプリ(前編)

Image from Gyazo

Vue CLIとは

Vue.jsを利用した本格的なアプリ開発のためのツールとしてVue CLIが公開されています. Vue CLIはNode.jsにおいて動作し, テンプレートを利用したプロジェクトの作成や,プラグインによる拡張などが利用可能です. ここではWindows環境を想定して,Vue CLIやNode.jsのインストール方法を示します.

まずは,Node.jsをインストールしましょう. パッケージマネージャのChocolateyを利用すると簡単です. PowerShellなどを起動して下記のコマンドを入力します.

> choco install nodejs

Node.jsをインストールしたら,次はVue CLIをインストールします. 同様にPowerShellで下記のコマンドを入力します. この-gオプションはグローバルにインストールすることを意味しており, どのディレクトリ(フォルダ)でも利用が可能になります(ローカルのnode_modulesにはインストールされない).

> npm install -g @vue/cli
> npm install -g @vue/cli-service-global

Vue CLIをインストールしたら,vueコマンドを実行してみましょう. -Vオプションでバージョンを確認することができます.

> vue -V
@vue/cli 4.4.5

Vue CLIを利用したプロジェクトのビルド(公開可能なファイルに変換する)に失敗する場合, フォルダに下記のコードを記述した vue.config.js というファイルを配置してください(ビルド方法は後述).

module.exports = {
    publicPath: './'
}

単一ファイルコンポーネントとは

Vue Cliでは,これまでのように,HTMLファイル(.html),JavaScriptファイル(.js),CSSファイル(.css)にコードを記述しません. これらの代わりに,全ての機能をまとめた単一ファイルコンポーネント(.vue)にコードを記述します. 単一ファイルコンポーネントは下記の構成になっています.

<template>
</tempalte>

<script>
export default{
}
</script>

<style scoped>
</style>

単一ファイルコンポーネントは階層的に 親コンポーネントから子コンポーネントをインポートすることができます. 例えば,child1.vueとchild2.vueを子コンポーネントとして, 親コンポーネントからインポートするには下記のように記述します.

import child1 from "./child1"
import child2 from "./child2"

export default{
  components: {
    child1,
    child2
  }
}

地図アプリのデザイン

Leefletを利用して,地図アプリを実装してみましょう. 完成したソースは下記URLで公開していますので参考にしてください.

https://github.com/naoto-github/SampleMapVue

作成するファイルは main.vuevmap.vuevcontroller.vue の3つです. main.vueは親コンポーネント,vmap.vueとvcontroller.vueは子コンポーネントの関係です. vmap.vueはLeeflet地図を表示するために用いられ,vcontroller.vueは地図を操作するためのコントローラとして用います. 今回は地図とコントローラの表示に取り組み,次回はコントローラの操作を実装することにします.

まずは,Leefletをインストールします. LeefletはCDNでも利用可能ですが,ここではNode.jsのモジュールとしてインストールします(node_modulesにインストールされます).

> npm install leaflet

コントローラのアイコンとしてFontawesomeを利用します. Fontawesomeも,Leefletと同様に,Node.jsのモジュールとしてインストールします. インストール方法の「Vue.js FontAwesome5を導入する(zukucode)」に詳しく記載されていますので参考にしましょう.

> npm install @fortawesome/fontawesome-svg-core @fortawesome/vue-fontawesome @fortawesome/free-solid-svg-icons @fortawesome/free-regular-svg-icons @fortawesome/free-brands-svg-icons

main.vue

親コンポーネントの main.vue です. componentsプロパティで,子コンポーネントのvmapvcontrollerを導入しています. これらの子コンポーネントはtemplateタグで配置されています.

<template>
  <div>
    <h1>Vue.jsで地図アプリ</h1>
    <vmap></vmap>
    <vcontroller></vcontroller>
  </div>
</template>

<script>
import vmap from "./vmap"
import vcontroller from "./vcontroller"
export default{
  components:{
    vmap,
    vcontroller
  }
}
</script>

<style scoped>
div{
  width: 640px;
}
h1{
  text-align: center;
}
</style>

vmap.vue

子コンポーネントの vmap.vue です. Leefletを利用するために,importでleaflet.jsとleaflet.cssを読み込んでいます. 地図の緯度経度(latlng)と倍率(scale)は,それぞれdataプロパティで宣言しています. この緯度経度と倍率を用いて,オープンストリートマップの地図を表示しています.

<template>
  <div>
    <div id="mymap"></div>
  </div>
</template>

<script>

// Leeflet
import L from 'leaflet';
import "leaflet/dist/leaflet.css";

export default{
  name: "vmap",
  mounted: function(){
    this.map = L.map("mymap");
    this.map.setView(this.latlng, this.scale);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(this.map);
  },
  data: function(){
    return{
      latlng: [35.159399, 136.987255],
      scale: 16
    }
  }
}
</script>

<style scoped>
#mymap{
  width: 480px;
  height: 480px;
  margin-left: auto;
  margin-right: auto;
}
</style>

vcontroller.vue

子コンポーネントの vcontroller.vue です. Fontawesomeを利用するために,importで必要なライブラリを導入しています. また,アイコンはv-faタグを記述することで利用することができます. 例えば下記のコードは左向きの矢印のアイコンを表示します.

<v-fa class="pad" icon="long-arrow-alt-left" />
<template>
  <div>
    <div id="mycontroller">
      <div id="mypad">
        <v-fa class="pad" icon="long-arrow-alt-left" />
        <v-fa class="pad" icon="long-arrow-alt-up" />
        <v-fa class="pad" icon="long-arrow-alt-right" />
        <v-fa class="pad" icon="long-arrow-alt-down" />
      </div>
    </div>
  </div>
</template>

<script>

// Fontawesome
import Vue from "vue";
import { library } from '@fortawesome/fontawesome-svg-core';
import { fas } from '@fortawesome/free-solid-svg-icons';
import { far } from '@fortawesome/free-regular-svg-icons';
import { fab } from '@fortawesome/free-brands-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
library.add(fas, far, fab);
Vue.component('v-fa', FontAwesomeIcon);

export default{
  name: "vcontroller"
}
</script>

<style scoped>
#mycontroller{
  width: 480px;
  margin-top: 20px;
  margin-left: auto;
  margin-right: auto;
}
#mypad{
  display: flex;
  justify-content: space-around;
}
.pad{
  display: block;
  width: 30px;
  height: 30px;
  border: 1px solid black;
}
</style>

ローカルサーバでの実行とビルド

それではローカルサーバで実行してみましょう. ローカルサーバで実行するには,vue serveコマンドで 親コンポーネントの main.vue を指定します.

> vue serve main.vue

また,公開用にビルドするには,vue buildコマンドを用います.

> vue build main.vue

下記のように表示されれば完成です. 次回,コントローラのイベント処理を実装します.

Image from Gyazo

参考書籍