Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9409

【アプリ開発 2】【Node.js JavaScript MongoDB】 JavaScriptを用いて端末の現在地を取得する。【2021年1月】

$
0
0

Node.js Express MongoDBを用いたアプリ開発

Node.js Express MongoDBを用いたアプリ開発を行うことになりました。
開発の中で得られた知見を、支障のない範囲で記録していきたいと思います。

アプリの仕様上、各ユーザーの携帯電話の位置情報を取得し、googleマップ上で表示させる必要が生じました。
まずは、位置情報を取得する機能を実装してみます。

要件

  • ユーザーがログインし、「位置情報通知」ボタンをクリックした場合、位置情報がデーターベースに格納される。
  • ユーザーがログアウトもしくは、「位置情報通知解除」ボタンをクリックした場合、位置情報がデーターベースから削除される。
  • 24時になった時点で、ユーザーの操作なしに、「位置情報通知解除」状態となる。
  • ユーザーの位置が変更した場合、最新の位置情報がデータベースに格納される。
  • 管理者は、定期的にデーターベースにアクセスしGoogleマップを用いて、ユーザーの位置を確認することができる。
  • 位置情報には、ユーザーの連絡先と、コメント等が表示される。

Javascriptを用いて位置情報を取得するテスト

とりあえずブラウザにアクセスした段階で、位置情報が取得できるようにしてみます。

位置情報Geolocation API ついて

位置情報の取得についてh、Geolocation API を使用します。

Geolocation APIとは

ウェブアプリでユーザーの位置情報を取得したいと思うことはよくあります。例えば、ユーザーの位置を地図上にプロットしたり、ユーザーの位置に関連するパーソナライズされた情報を表示したりすることができます。

位置情報 APIは navigator.geolocation への呼び出しを介してアクセスします。これにより、ブラウザーはユーザーに自分の位置情報にアクセスする許可を要求します。ユーザーが許可すると、ブラウザーは端末上で利用可能な最良の機能を使用してこの情報にアクセスします (GPS など)。

https://developer.mozilla.org/ja/docs/Web/API/Geolocation_API

<!DOCTYPE html><htmllang="ja"><head><metacharset="utf-8"><metaname="viewport"content="width=device-width,initial-scale=1"><title>CAR MATCH APP</title></head><body><divid="position-display">取得中</div><script>// GPS センサの値が変化したら何らか実行する geolocation.watchPosition メソッドnavigator.geolocation.watchPosition((position)=>{letposition_y=position.coords.latitude;// 緯度を取得letposition_x=position.coords.longitude;// 経度を取得letaccuracy=position.coords.accuracy;// 緯度・経度の精度を取得displayData(position_y,position_x,accuracy);// displayData 関数を実行},(error)=>{// エラー処理(今回は特に何もしない)},{enableHighAccuracy:true// 高精度で測定するオプション});// データを表示する displayData 関数constdisplayData=(position_y,position_x,accuracy)=>{vartxt=document.getElementById("position-display");txt.innerHTML="緯度:"+position_y+"経度 "+position_x+"<br>"// データ表示+"精度: "+accuracy;}</script></body></html>

IMG_BBE4EF911ADD-1.jpeg

ページにアクセスするとブラウザ上にアクセスした端末の現在地が表示されます。

スマホからも確認できるか試してみます。

netlifyに簡易的にアップロードします。

https://app.netlify.com/drop

その際、ファイル名はindex.htmlにします。また、アップロードはディレクトリで行う必要があるので、適当に"test/index.html"のような構造にして、testディレクトリをアップロードします。
アップロード方法はディレクトリをドラックするだけです。

スマホからアクセスしたところ、同様に確認することができました。

node.jsから取得したデータをmongoDBに保存。

ユーザーがページにアクセスしたら、位置情報がデータベースに登録できる様にします。

5秒毎に、データを更新して、mongoDBに保存します。

<!DOCTYPEhtml><htmllang="ja"><head><metacharset="utf-8"><metaname="viewport"content="width=device-width,initial-scale=1"><title>CARMATCHAPP</title>
</head>
<body><divid="position-display">取得中</div>
<script>constsendPosition=(latitude_i_y,longitude_k_x)=>{//URLパラメータで遷移。location.href=`/savePosition?latitude_i_y=${latitude_i_y}&longitude_k_x=${longitude_k_x}`//ページ遷移し、savePositionメソッドを呼び出す。}// GPS センサの値が変化したら何らか実行する geolocation.watchPosition メソッドnavigator.geolocation.watchPosition((position)=>{letlatitude_i_y=position.coords.latitude;// 緯度を取得letlongitude_k_x=position.coords.longitude;// 経度を取得letaccuracy=position.coords.accuracy;setTimeout(function(){//ページリロード後、5秒経過でsendPosition関数を呼び出し。sendPosition(latitude_i_y,longitude_k_x);},5000);},(error)=>{// エラー処理(今回は特に何もしない)},{enableHighAccuracy:true// 高精度で測定するオプション});</script>
</body>
</html>

c_positionコントローラー.savePositionアクションを呼び出し。

c_position.js
"use strict";constPosition=require("../models/m_position.js");constDriver=require("../models/m_driver.js");constgetPosition=(req,res,next)=>{res.render("v_getPosition");}constsavePosition=(req,res,next)=>{Driver.findOne({name:"driverTaro"}).populate("position").exec((error,data)=>{//ユーザーはテストで固定。本来はセッションから取得。該当するユーザーのpostionを更新する。Position.findOneAndUpdate({_id:data.position._id},{$set:{latitude_i_y:req.query.latitude_i_y,longitude_k_x:req.query.longitude_k_x}}).exec();})res.redirect("/getPosition");//再度位置情報取得へリダイレクト}module.exports={getPosition,savePosition};
{"_id":{"$oid":"5ff163eb514e011e79ccc284"},"latitude_i_y":●●●.574898349,"longitude_k_x":●●●.0487293840238428,"driver":{"$oid":"5ff163eb514e011e79ccc283"},"__v":0}

保存を確認。
これでユーザーが任意に位置情報をアプリに提供できるようになりました。

データーベースから値を取得し、位置を表示させます。

googlemapを利用するため、まずはgooglemaps apiキーを取得します。
https://developers.google.com/maps/documentation/android-sdk/get-api-key?hl=ja
apiキーの埋め込みはソースコードで見えてしまうのでセキュリティー対策も必要です。
参考

mongoDBからデータを取得して、地図上に表示。

管理者側がユーザーの位置情報を知るために、googlemap上に表示させる様に実装します。

まず、ユーザーが登録している位置情報を返却するapiを作成します。

constreturnCarPositions=(req,res,next)=>{Driver.find().populate('position').exec((error,data)=>{res.json(data);})}

ユーザー(Driver)モデルから全て取得し、位置情報をpopulateしjsonをレスポンスします。

続いて、管理者がアクセスするビューを作成します。

<head><title>CARMATCHAPP</title>
<style>/* Google マップを表示させるためには style 内で width と height の指定が必要 */#mapDiv{width:100%;height:1000px;}</style>
</head>
<body><divid="mapDiv"></div> <!-- 地図を置くdiv要素 -->
</body>
<script>constplaceCars=()=>{fetch('http://localhost:8080/admin/getCarPositions').then(response=>response.json())//fetchでapiを呼び出し。.then(data=>{data.map(d=>{// マーカーをつけるconstmarker=newgoogle.maps.Marker({position:{lat:d.position.latitude_i_y,lng:d.position.longitude_k_x},map:map});});})}functioninitMap(){navigator.geolocation.getCurrentPosition((position)=>{varlatitude_i_y=position.coords.latitude;// 緯度を取得varlongitude_k_x=position.coords.longitude;// 経度を取得varinitPos=newgoogle.maps.LatLng(latitude_i_y,longitude_k_x);// 初期位置を指定map=newgoogle.maps.Map(mapDiv,{// Map オブジェクトを作成して mapDiv に表示center:initPos,zoom:13,});placeCars();})}</script>
<scriptid="googleMapUrl"src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDl7XzTVOilq7dDEMXjWjJLXgjz6VCTymc&callback=initMap"></script>
動作確認

initMapは地図の初期設定を行う関数で、urlの末尾に"callback=initMap"という形で組み込まれているため、ページ読み込み時に呼び出されます。

initMap内でplaceCars関数を呼び出します。
placeCars関数で、先ほど作ったapiに対しfetchします。
返却されたデーターをmarkオブジェクトにし、initMapで作成したmapオブジェクトに埋め込み、マーカーを地図上に表示させます。

image.png

この様に複数の箇所にマーカーを表示させることができました。

今後の実装

現状は、ユーザーが任意のタイミングでブラウザを開き位置情報を送る必要があります。
これを、定期的に位置情報を送信するように実装したいと思います。
これには、service workerを用いて、サイトをPWA化する必要がありそうです。
もしくはネイティブアプリを作るか。。。

続く。

なお、ダミーデーターは東京付近の観光名所を指定してたんですが、どうしても表示させれずに途方にくれていました。もしやと思い地図をズームアウトしたところ

image.png

こんなところにいました。。。緯度と経度は、間違えないようにしようにしましょう。

参考:
Geolocation_API
こくぶん研究室
Node.jsとexpressを使って簡単なWebAPIを作成する
Google Maps JavaScript APIで複数マーカーをいい感じに表示する


Viewing all articles
Browse latest Browse all 9409

Trending Articles