6
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

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

この記事は、 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コンポーネントの外から位置情報を与えられるので、各種サービスと連携して地図表示することも気軽にできそうです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
6
Help us understand the problem. What are the problem?