LoginSignup
13
6

More than 3 years have passed since last update.

Leaflet + Vue.js で 地図の表示位置を切り替えられるサンプルサイトを作ってみた

Last updated at Posted at 2019-12-04

この記事は、 North Detail Advent Calendar 2019 の4日目の記事です。

2020/04/02 追記
本記事は、NorthDetail ブログにも投稿しています。
https://www.northdetail.co.jp/blog/441/

弊社は最近地図を扱う業務が増えたので、ここ数ヶ月ほど学習がてらに "Leaflet" を使ってみてます。
もともと "Vue.js" でのサイト構築も多いので、両方を合わせるとどうなるか、というのを試してみたいと思います。

デモサイト: https://sample-leaflet-tacck.netlify.com/
ソースコード: https://github.com/tacck/sample-leaflet

画面でみると

こういう感じで表示されます。
20191204_001.png

初回は "位置情報提供の許可" が求められるので、 "許可" の方を選択してください。
20191204_003.png

「現在地」のボタンをクリックすると、ブラウザ経由で取得した位置情報の地点を地図上で表示します。(ここは弊社)
20191204_002.png

解説

Vue.js や Leaflet.js それぞれの詳しい扱い方は専用のサイトにお任せします。

ここでは、少し工夫したところを。

情報の更新

現在地取得と反映

Mainコンポーネントの中に、 Tabコンポーネント(ボタンのある領域) と Mapコンポーネント(地図のある領域) を持つ形にしています。
Mapコンポーネントは、Mainコンポーネントから与えられた緯度経度を中心に地図を表示する(変更があれば更新する)だけ、という作りです。

緯度経度の変更されるタイミングは、次の二つになります。

  • ボタンが押された場合
  • ボタンが「現在地」の時にブラウザから与えられた位置情報が navigator.geolocation.watchPosition() 経由で更新された場合

ボタンが押された場合

Tabコンポーネント の中には TabButtonコンポーネント が二つ並んでいます。
TabButtonコンポーネント は、クリックされたら "クリックされたよ" というイベントを Tabコンポーネントに返すだけです。
どちらのボタンがクリックされたかは、 Tabコンポーネント の責任範囲として、ここからさらに Mainコンポーネント へイベントを投げます。
Mainコンポーネントへは "どちらのボタンが押されたか" がわかるものを引数として渡しています。

Mainコンポーネントは、受け取った値を使って緯度経度を更新し、 Mapコンポーネントへ(props経由で)情報を渡します。

TabButton.vue
(snip)
    <b-button @click="$emit('click')" size="lg" :variant="status">
(snip)
Tab.vue
    <TabButton
      @click="clickStation"
      id="sation"
      :status="stationVariant"
      label="札幌駅"
    ></TabButton>
(snip)
    clickStation() {
      this.stationVariant = "info";
      this.hereVariant = "";

      this.$emit("changeActive", "static");
    },
Main.vue
(snip)
    <Tab @changeActive="setActive"></Tab>
(snip)
    setActive: function(location) {
      console.log("active:" + location);
      this.lat = this.geosObject[location][0];
      this.lon = this.geosObject[location][1];
    },
(snip)

地図へ反映

Mapコンポーネントでは、緯度経度の情報が更新されたこと(正確にはpropsで持つ 'lat' の値が更新されたこと)がわかるように、 watch を使っています。

Main.vue
(snip)
    <Map :lat="lat" :lon="lon"></Map>
(snip)
Map.vue
(snip)
  methods: {
    updateCurrentPosition: async function() {
      if (this.map) {
        this.map.panTo([this.lat, this.lon]);
      }
      if (this.currentCircle) {
        this.currentCircle.setLatLng([this.lat, this.lon]);
      }
      if (this.currentPoint) {
        this.currentPoint.setLatLng([this.lat, this.lon]);
      }
    }
  },
  watch: {
    lat: function() {
      this.updateCurrentPosition();
    }
  }
(snip)

まとめ

Vue.js のコンポーネントの一つとして、 Leaflet を使った地図を使うことが簡単にできました。
Mapコンポーネントの外から位置情報を与えられるので、各種サービスと連携して地図表示することも気軽にできそうです。

13
6
0

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
13
6