位置情報を取得するVueコンポーザブル
位置情報を取得する処理がなかなか面倒で二度と書きたくないので…
code:location.ts
/**
* @file 位置情報を取得するコンポーザブル
*/
export interface ILocation {
lat: string;
lon: string;
}
export const useLocation = () => {
/** 現在地の緯度経度を取得する */
const getLocation = async (): Promise<ILocation | undefined> => {
if (!process.client) {
return;
}
if (!navigator.geolocation) {
alert(
'現在地情報を取得できませんでした。お使いのブラウザでは現在地情報を利用できない可能性があります。エリアを入力してください。'
);
return;
}
// Geolocation API を使って位置情報を取得する処理(後続処理が走らないよう非同期関数化)
async function getPosition(): Promise<any> {
const optionObj = {
enableHighAccuracy: false,
timeout: 8000,
maximumAge: 5000,
};
return new Promise((resolve, reject) => navigator.geolocation.getCurrentPosition(resolve, reject, optionObj));
}
try {
const position = await getPosition();
// 動作確認用
alert(${position.coords.latitude}, ${position.coords.longitude});
return {
lat: position.coords.latitude,
lon: position.coords.longitude,
};
} catch (err) {
switch (err.code) {
case 1: // PERMISSION_DENIED
alert('位置情報の利用が許可されていません');
break;
case 2: // POSITION_UNAVAILABLE
alert('現在位置が取得できませんでした');
break;
case 3: // TIMEOUT
alert('タイムアウトになりました');
break;
default:
alert('現在位置が取得できませんでした');
break;
}
}
};
return {
getLocation,
};
};
困りどころ1: ローカル環境で動作しない
セキュリティの問題上、安全なコンテキスト (HTTPS) でのみ利用できる。
なので HTTP のローカル環境で動作しない。開発環境にデプロイして確認する必要がある。
困りどころ2: アクセス許可が面倒
その際も、OSのアクセス権限によりブロックされている場合がある。
Macであれば「セキュリティとプライバシー」から利用ブラウザをまず許可し、その上でページに位置情報の利用を許可する必要がある。
困りどころ3: navigator.geolocation.getCurrentPosition() が非同期関数じゃない
上記処理では緯度経度を返す処理の中に現在地を取得する API navigator.geolocation.getCurrentPosition() が含まれているが、これは Promise の関数ではないのでそのまま使うと緯度経度が空の値が返却されてしまう。
そこで こちらのページ にあるように Promise() でラップして非同期関数化する必要がある。その際、コールバックの書き方も MDN などに記載のサンプルとは変わってきてしまう。