North Detail / ノースディテール

BLOG ブログ

ブログ
CATEGORY
TECH

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

本記事は、 North Detail Advent Calendar 2019 の4日目の記事です。
Qiita にて作成した記事からの転記となります。 (2019年12月4日公開)

https://qiita.com/tacck/items/b7863a56d17a4c5cf70a

※本記事は、NorthDetail Advent Calendar 2019の一環として投稿しています

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

画面でみると

こういう感じで表示されます。

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

「現在地」のボタンをクリックすると、ブラウザ経由で取得した位置情報の地点を地図上で表示します。(ここは弊社[2019年12月4日時点])

解説

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

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

情報の更新

現在地取得と反映

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

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

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

ボタンが押された場合

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

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

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

      this.$emit("changeActive", "static");
    },
(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 を使っています。

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

tacck
WRITER:tacck
元 技術推進Group Group Leader

現在は株式会社ノースディテールを離れて、
エバンジェリストとして技術啓蒙や勉強会の開催、各種プロジェクトに参画しています。
機会があれば、ノースディテールでのプロジェクトに参加できればと思っています。

言語は問わずに対応しますが、心はPHPer。
フロントエンド・バックエンド・インフラ・スマホアプリなどを、
「垣根を超えて」どう作るか、を考えるのが好きです。

好きなフィギュアスケートの技はスプレッド・イーグル。
主な記事 一覧へ

一覧へ

IS 501383 / ISO 27001