Edited at

Vue で地図を表示する無料で最短の道


概要

Vue で地図を表示するアプリを作ってみます。

地図ライブラリは leaflet を使います。


前提


node と npm

 ここからダウンロード 


vue-cli

vue-cliのインストール

$ npm i -g @vue/cli

$ vue -V
3.4.1


最短の道


プロジェクトの作成

とりあえず vf という名前でプロジェクトを作成します。選択肢が出てきますが、デフォルトですすめます。

$ vue create vf


Vue CLI v3.4.0
? Please pick a preset:
❯ default (babel, eslint)
Manually select features


leaflet をインストール

vf という名前のディレクトリができているので、中に入って、leaflet をインストールします。

$ cd vf

$ npm i leaflet --save


App.vue を変更

App.vue を変更します。


App.vue

<template>

<div id=app>
</div>
</template>

<script>
import 'leaflet/dist/leaflet.css'
import L from 'leaflet'

export default {
mounted() {
L.map( 'app', { center: L.latLng( 35.6825, 139.752778 ), zoom: 15 } ).addLayer(
L.tileLayer( 'http://{s}.tile.osm.org/{z}/{x}/{y}.png' )
)
}
}
</script>

<style>
html, body, #app { height: 100% }
body { margin: 0 }
</style>



起動と接続

vf ディレクトリでサービスを開始して、ブラウザから localhost:8080 に繋ぎます。

$ npm run serve


勘所

import  'leaflet/dist/leaflet.css'

がないと、地図の表示が崩れます。

html, body, #app { height: 100% }

で地図を囲む全ての要素の height を 100% にしないと地図が表示されません。

body { margin: 0 }

がないと、地図の左上にちょっと余白ができて、右下が切れてしまいます。

L.map( 'app', { center: L.latLng( 35.6825, 139.752778 ), zoom: 15 } )

で app という id の div に地図をつけています。

center と zoom の両方を指定しないと、地図が表示されません。


マーカー

クリックされた場所にマーカーをつけてみます。


デフォルトのマーカー

デフォルトのマーカーを使うにはちょっと面倒なんですがアイコンのリソースの位置を指定してやることが必要です。

<template>

<div id=app>
</div>
</template>

<script>

import 'leaflet/dist/leaflet.css'
import L from 'leaflet'

delete L.Icon.Default.prototype._getIconUrl

L.Icon.Default.mergeOptions(
{ iconUrl : require( 'leaflet/dist/images/marker-icon.png' )
, iconRetinaUrl : require( 'leaflet/dist/images/marker-icon-2x.png' )
, shadowUrl : require( 'leaflet/dist/images/marker-shadow.png' )
}
)

export default {
mounted() {
const map = L.map( 'app', { center: L.latLng( 35.6825, 139.752778 ), zoom: 15 } ).addLayer(
L.tileLayer( 'http://{s}.tile.osm.org/{z}/{x}/{y}.png' )
).on(
'click'
, p => map.addLayer( L.marker( p.latlng ) )
)
}
}
</script>

<style>
html, body, #app { height: 100% }
body { margin: 0 }
</style>

北の丸公園においてみました。


divIcon を使ったマーカー

divIcon を使うと、マーカーのアイコンとして div を使えます。div なんでやりたい放題できます。


App.vue

<template>

<div id=app>
</div>
</template>

<script>

import 'leaflet/dist/leaflet.css'
import L from 'leaflet'

export default {
mounted() {
const map = L.map( 'app', { center: L.latLng( 35.6825, 139.752778 ), zoom: 15 } ).addLayer(
L.tileLayer( 'http://{s}.tile.osm.org/{z}/{x}/{y}.png' )
).on(
'click'
, p => map.addLayer(
L.marker(
p.latlng
, { icon: L.divIcon( { className: 'red marker', iconSize: [ 16, 16 ] } ) }
)
)
)
}
}
</script>

<style>

html, body, #app { height: 100% }
body { margin: 0 }

.marker {
text-align : center
; color : white
; font-size : 16
; border-radius : 8px
; box-shadow : 8px 8px 8px rgba( 0, 0, 0, 0.4 )
}
.red {
background : red
}

</style>



応用編


マーカークラスターグループ

leaflet.markercluster をインストールすると、地図にたくさんマーカーを置くとき、近接するマーカーをまとめて表示するような機能を実現できます。

npm i leaflet.markercluster --save

5個のマーカーのクラスターグループを作ってみます。


App.vue

<template>

<div id=app>
</div>
</template>

<script>

import 'leaflet/dist/leaflet.css'
import L from 'leaflet'
require( 'leaflet.markercluster' )
import 'leaflet.markercluster/dist/MarkerCluster.css'
import 'leaflet.markercluster/dist/MarkerCluster.Default.css'

export default {
mounted() {
const w = { icon: L.divIcon( { className: 'red marker', iconSize: [ 16, 16 ] } ) }
L.map( 'app', { center: L.latLng( 35.6825, 139.752778 ), zoom: 15 } ).addLayer(
L.tileLayer( 'http://{s}.tile.osm.org/{z}/{x}/{y}.png' )
).addLayer(
L.markerClusterGroup().addLayer(
L.marker( [ 35.691, 139.752 ], w )
).addLayer(
L.marker( [ 35.692, 139.752 ], w )
).addLayer(
L.marker( [ 35.690, 139.752 ], w )
).addLayer(
L.marker( [ 35.691, 139.753 ], w )
).addLayer(
L.marker( [ 35.691, 139.751 ], w )
)
)
}
}
</script>

<style>

html, body, #app { height: 100% }
body { margin: 0 }

.marker {
text-align : center
; color : white
; font-size : 16
; border-radius : 8px
; box-shadow : 8px 8px 8px rgba( 0, 0, 0, 0.4 )
}
.red {
background : red
}

</style>


5個まとめて表示されています。

クリックするとズームして別々に表示されます。


最後に

leaflet は機能豊富なライブラリなので、いくらでもネタはあるんですが、キリがないのでこのへんにしておきます。最後までおつきあいいただいてありがとうございました。