Torch プロジェクト

学祭を盛り上げるアプリを作りはじめます!(作りおわった) 3 地球!フロントエンド編

投稿日:

学び: 地球は球体である。

ここまでバックエンドのお話やUIのお話をご覧になられたと思います。
ご覧になられていない方は、この記事を読んだ後にでも読んでみてください。

それでは、フロントエンドが以下にして”地球”と戦ったかを御覧いただきましょう。

開発環境

今回のアプリケーションはスピード重視の爆速開発のため、慣れている環境でサクッと開発していきましょうということです。
今回フロントエンドで使うことになったものは下記のリストにまとめました。

  • Typescript
  • Nuxt.js
    • Nuxt TypeScript
  • Vuetify
  • Geolib
  • eslint

NuxtやVuetifyあたりは、ぼくが仕事で使ったこともあるのでまぁ、特に詰まることもなく開発できるでしょうということで選んでいます。
eslintは、人間には必要なため選んでいます。

緯度・経度 vs ぼく

TorchではGPSを使って現在地を取得しています。GPSから取れるデータは緯度・経度です。これを、ブラウザのUI上に表示しなくてはなりません。また、逆もあります。画面上にピンを追加する際は画面上で表す座標から緯度経度にも変換しなくてはなりません。つまりは、以下のことができる必要があります。

  • 緯度・経度から画面のX・Y座標へ変換
  • 画面X・Y座標から緯度・経度へ変換

これで最初に何も考えずに、左上と右下の緯度経度を取得して、これを単純に 長方形 であると仮定し変換をしました。そうしたところ、不思議なことにずれます。
そこで気づいたのです。 「あっ、地球は丸いんだ・・・」と。

地球は丸い

地球が丸いことに気づいたぼくは、延々とGoogleでいい感じに使える数式を探しました。
そこでやっと探し、見つけたのが緯度・経度<->メートルの数式でした。具体的には、以下のコードです。(Typescript)

  static toXAndY(lat: number, lon: number): XAndY {
    let pointX = lon * 20037508.34 / 180.0;
    let pointY = Math.log(Math.tan((90.0 + lat) * Math.PI / 360.0)) / (Math.PI / 180.0);
    pointY = pointY * 20037508.34 / 180.0;

    return {
      x: pointX,
      y: pointY,
    }
  }

  static toLonAndLat(x: number, y: number): LonAndLat {
    let lon = x * 180 / 20037508.34;
    let lat = Math.atan(Math.exp(y * Math.PI / 20037508.34)) * 360 / Math.PI - 90;

    return {
      lat: lat,
      lon: lon,
    }
  }

この関数たちを通せば、やりたいことはできます。

GeoLocationAPI

今回のWebアプリはブラウザからGPSで位置情報を取得しています。さて、これは localhost であれば特に問題が起こらないで取得できていたのですが、スマートフォンでデバッグする際に問題が発生しました。

GeoLocationAPI MDNの説明

まぁ、言いたいことはわかります。HTTPS以外でユーザーの位置情報を扱ってほしくないんですね・・・でも、 192.168.1.0/24でくらい許してくれてもいいんじゃないですか・・・?
そんなで、スマートフォンでデバッグをするためにはHTTPSなURLが必要になりました。ここで、2つの選択肢があります。

  1. オレオレ証明書を発行して自分のマシンでデバッグするか?
  2. 自分のサーバー(HTTPS)へSSHトンネルでデバッグするか?

結果的には、2を選んだわけです。2を選んだのはかんたんで、開発している部屋から出てデバッグすることもありうるのです。実際に、動いているかを確認するために突然、K1号館から走り出て、デバッグもしました。
SSHトンネルはかんたんです。すでに起動している自分の個人サーバーへ ssh トンネルを張り、グローバルなドメインで接続するだけです。

ssh -R 8850:localhost:2800 192.168.10.xx

こんな感じです。(VPNを使っているため、プライベートIP)

最寄りを探そう

今までの経緯でマップ上にピンとユーザーの位置を乗せることができました。 やったね。
マップにピンとユーザーの位置を乗せるだけではしょうがないですね。
それだけならGoogleMapにピンを乗せればいいですよね。
このアプリにはエリアという概念が存在します。エリアは矩形で区切られており、サーバーからAPIで提供されます。

これですね。
そして、今回はマップ上の最寄りのエリアを探さなければなりません。ユーザーがいる箇所で一番近いエリアはどこかと。
矩形ですが、矩形エリアで探してしまうとイイカンジにならないことが走ってみてわかりました。そこで、矩形エリアの中心点を求め、そこから円形に表示することにしました。
はい、こんな高度な緯度・経度の計算は位置情報初めて2日程度の自分にはできません。幸い世の中には”めんどくさいこと”や”大変なこと”をやってくれる人たちがいます。ライブラリですね。
npmを用いると非常にかんたんです。今回は、 Geolib を使うことにしました。

npm i --save geolib

これで解決しました。 あとは、矩形の中心点から円を描き、そこにユーザーが含まれているかを探すだけです。

まとめ(?)

地球は丸いです。
それはそうとして、今回は楽しく開発することもできました。バックエンドの方は死んでいましたが、フロントエンドは比較的余裕が残る形で完成までさせることができました。

バックエンドでもそうですが、フロントエンドでも短期間で開発するために工夫や使いづらいUIにならないように気をつけた事があります。それも書いていきたいと思います。

では今回はこのあたりで。また。

-Torch, プロジェクト

Copyright© ソフトウェア工房 , 2019 All Rights Reserved Powered by AFFINGER5.