スポンサーリンク

Vue.jsとOpenStreetMapで1分おきに移動距離を表示するアプリ作成にtryしてみる(1)

2019年9月14日

以前、Vue.jsとLeaflet.jsとOpenStreetMapで現在位置を地図で表示するPWAを作成してみました。

今回は、このアプリを複数ページにして、1ページ目で現在地を地図で表示し、2ページ目で、1分おきに歩いた距離を表示し、さらに、今まで動いた距離を表示したいと思います。

スポンサードリンク

ソースコードとDEMOサイト

ソースコード
https://github.com/adash333/vue-osmap-distance

DEMOサイト
https://laughing-shaw-6881f1.netlify.com/

開発環境

Windows 10 Pro
VisualStudioCode 1.37.1
git version 2.20.1.windows.1
nvm-windows 1.1.7
node 12.2.0
npm 6.9.0
yarn 1.16.0
@vue/cli 3.10.0

Node.jsをインストールした状態で、npm i -g @vue/cli でVue CLI(Version 3)をインストールしています。

新規Vue.jsアプリの作成

C:/vue/ フォルダをVisualStudioCodeで開き、Ctrl+@でコマンドプロンプトを開き、以下を入力します。
最初にマニュアル設定を選び、次の選択肢のうち以下の3つをスペースキーで追加して、後は、vue routerのHistoryモードのところ以外はEnterを連打します。(vue routerのHistoryモードは、n としておきます。 )

  • Progressive Web App (PWA) Support
  • Router
  • Vuex
vue create vue-osmap-distance

いったん、開発サーバを起動して現在のページを確認します。

cd vue-osmap-distance
yarn serve
( または、npm run serve )

VisualStudioCodeのターミナル画面で、一旦、Ctrl+C => y + Enter でサーバを停止しておきます。

leafletのインストール

leaflet.jsは、OpenStreetMapを呼び出すために非常に便利なJavaScriptライブラリです。Vue.jsアプリでなくても、普通にindex.htmlから呼び出して利用することもできます。(参考: https://kita-note.com/leaflet-tutorial-1 )
今回は、以下を入力します。

yarn add leaflet
(または npm i leaflet --save)

参考: https://qiita.com/po3rin/items/3968f825f3c86f9c4e21
po3rin
2019年06月13日に更新
VueCLIからVue.js入門①【VueCLIで出てくるファイルを概要図で理解】

src/views/Home.vueの編集

まず、yarn serve して、ブラウザで http://localhost:8080/ を開いておきます。
写経元サイトのコードをコピペします。
http://のところだけhttps:// に変更しています。

(変更前)

(変更後)

地図は表示されましたが、HomeとAboutのリンクも消えてしまい、複数ページにできません。
試しに、src/components/Map.vue を新規作成し、 Home.vueの中身をほぼコピペしてみます。
また、さらにHome.vueも変更します。

→どうしても表示されず、うまくいきません。。。もう一度、写経元サイトを読み返してみると、以下のような記載がありました。

(Leaflet.jsでは、)html, body, #app { height: 100% }
で地図を囲む全ての要素の height を 100% にしないと地図が表示されません。

参考:https://qiita.com/Satachito/items/929a63e9b266f6db7958

つまり、さらに、<style>のところに、#mapid を追加すればよいのかも、、、

ここまでのソースコード
https://github.com/adash333/vue-osmap-distance/tree/acca7ce6d65c0da55735afe91182d79d526848a1

src/views/About.vueの編集

Aboutページには、以下の3つを表示したいと思います。

  1. 現在地の緯度と経度
  2. 1分おきに移動した距離
  3. アプリを開いてから移動した距離の合計

まず、現在地の緯度経度をGeolocation APIを用いて取得して表示します。(参考:Vue.jsにてGeolocation APIで取得した値をdataプロパティに設定する)

次に、1分おきに移動した距離を表示したいと思います。setInterval()関数を用います。

(変更前)

(変更後)

Ctrl + Shift + I でconsole画面を見てみると、“Cannot set property 'lat2’ of undefined” とエラーが出ており、いろいろやったのですが、どうにもできませんでした。

どうやら、"this" に問題がありそうです。

setInterval()の外でlet self = thisとしてthisオブジェクトを別の変数に割り当てる(JavaScriptの"this")

JavaScriptでよく出てくる this ですが、正直、まったくよくわかりません。以下のリンクを読んでみます。

https://www.sejuku.net/blog/29389
thisって何?使い方を覚えて、JavaScriptをもっと楽しく使おう!
マサト
2019/5/11

https://qiita.com/tsukishimaao/items/39d22fd9178546d6cdeb
@tsukishimaao
2014年02月01日に更新
windowオブジェクト

https://qiita.com/takeharu/items/9935ce476a17d6258e27
@takeharu
2015年12月07日に更新
JavaScriptの「this」は「4種類」??

今回の、setInterval(){} の中のthis.lat2がundefinedになってしまうことに対する解決策としては、

  1. .bind()を用いる
  2. let self = thisとしてthisオブジェクトを別の変数に割り当てる
  3. アロー関数を用いる

の3つがあるそうです。let self = thisとしてthisオブジェクトを別の変数に割り当てる方法が、一番分かりやすそうです。
(参考1:how to use setInterval in vue component
(参考2:How to access the correct `this` inside a callback?

以下のように書きなおしてみました。

しかし、これだと、最初の1分間(今だけ便宜的に20秒毎にしてあります)だけ、距離が(緯度, 経度)=(0, 0)からの距離になってしまいます。どうしたらよいでしょうか?(総距離から同じ値を引けばよいか???)

とりあえず、Netlifyにデプロイしてスマホでサイトを開き、位置情報を許可して、歩いてみたところ、とりあえずは以下のように、20秒ごとに、歩いた距離が表示されました。

さらに少しコードを変更して、最初の1分間で移動した距離を0 (最初の1分間はあきらめる、、、(爆))としました。

ここまでのソースコード
https://github.com/adash333/vue-osmap-distance/tree/19a83b9da3a70305b24fc26a2699e51db73253c2

filterを用いて小数点以下3桁表示に変更

Vue.jsのfilterを用いて、以下のようにします。

// <template>の一部
    <h1>現在地</h1>
    <p>緯度:{{latitude | round}}</p>
    <p>経度:{{longitude | round}}</p>

// <script>の一部
  filters: {
    // 小数点以下を第3位に丸めるフィルタ
    round: function (val) {
      return Math.round(val * 1000) / 1000
    }
  }

Bulmaを用いて表示を修正

CSSフレームワークBulmaを用いるために、コマンドプロンプトで以下のようにbulmaをインストールします。

yarn add bulma
// npm install bulma  でもOK

なんか、leaflet.jsとバッティングしそうですが、とりあえず見なかったことにして進みます。

public/index.htmlの</head>の直前に、以下のコードを挿入します。

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">

(変更前)

(変更後)

次に、src/main.jsの6行目付近に以下のコードを追加します。

import './../node_modules/bulma/css/bulma.css';

これで、Vue.jsでbulmaとFontAwesome5が利用できるようになります。
参考:CodeSandboxのVue.jsでBulmaを利用する方法

src/App.vueと、src/components/about.vue を、bulmaを用いて少し変更します。

歩いた距離をlocalStorageに保存して永続化する

現時点では、ページを変更すると、それまで歩いた距離はリセットされて0になってしまうため、今まで歩いた距離をlocalStorageに保存するようにしてみたいと思います。

参考:
https://iwb.jp/javascript-vuejs-install-localstorage/

src/views/About.vue

// mounted() {} の最初のところに以下を挿入
    if (localStorage.length) {
      this.length = localStorage.length
    }

// self.length = self.length + self.d の下に以下を挿入
localStorage.setItem('length', self.length)

setInterval()に対するclearInterval()

SPA(Single Page Application)の場合、一度setIntervalしたものは、全画面で有効になり続けるそうです。他のページに移動したときにsetInterval内の操作を中止したい場合には、

  1. data: {} の中で、interalId: undefined
  2. this.intervalId = setInterval(…)
  3. beforeDestroy() {} の中に、clearInterval(this.intervalId)

のように記載するそうです。

しかし、今回は、地図の画面に移動しても歩いた距離は計算し続けてほしいため、この実装は行わないことにしました。

参考:Vuejs ポーリングする時の注意点(@kimullaa 2018年05月30日に投稿)

ソースコードとDEMOサイト

ソースコード
https://github.com/adash333/vue-osmap-distance

DEMOサイト
https://laughing-shaw-6881f1.netlify.com/

参考:Netlifyにデプロイするときの設定

スポンサーリンク