Geolocation APIとJavaScriptだけで現在地から近い順に表示する方法


こんにちは、むったん(@6ttan)です。
「現在地から近い店舗を表示したい、でも地図APIの登録は大げさかも…」そう思って調べるのを後回しにしていませんか?
実は意外とシンプルに実装できます。
今回は外部ライブラリなし・APIキーなしで「現在地から近い駅を近い順にピックアップする」コンテンツを作ります。
コードの設計ポイントも合わせてまとめるので、ぜひ参考にしてみてください。
※リアル店舗を出すわけにもいかないので、今回は駅で紹介します
Contents close
完成デモ
まず動きを確認してみてください。
「近い駅を探す」ボタンを押すと位置情報の取得許可を求めるダイアログが表示され、許可すると登録済みの駅から近い順に4件が自動で並びます。
See the Pen Untitled by むったん (@6ttan) on CodePen.
表示件数は適宜変更可能です。
全体の仕組み
大きく3つのステップで動いています。
1. Geolocation APIでブラウザから現在地の緯度・経度を取得する
2. 登録済みの各駅との距離を計算する
3. 近い順にソートして上位4件だけ表示する
地図の描画はなし。
つまり、距離の数値だけで「近い順」を実現しているのがこのアプローチの肝です。
コードの解説
ここからは上記のコードの説明をしていきます。
設定とデータを分離して管理する
const CONFIG = {
LINK_TARGET: '_blank',
MAX_DISPLAY: 4
};
const STATIONS = [
{ name: "東京駅", lat: 35.681236, lng: 139.767125, url: "#" },
{ name: "品川駅", lat: 35.628471, lng: 139.738760, url: "#" },
{ name: "新宿駅", lat: 35.689501, lng: 139.691722, url: "#" },
// ...
];
変更頻度の高い「設定値」と「駅データ」をそれぞれ別のオブジェクトで上部に分けています。
また、LINK_TARGET はリンクの開き方の指定で、_blank なら別タブで開き、_self なら現在のウィンドウでページ遷移します。
遷移先が外部サイトなら _blank、自サイト内のページなら _self というイメージで使い分けてください。
表示件数を変えたければ MAX_DISPLAY を、場所を追加したければ STATIONS の配列に追加するだけです。
STATIONS部分をJSON読み込みでもOKですが、今回は量が少ないので直で書いています。
こうして変更が多いところを上部にまとめておくと、コードの深い部分を触らずに調整できる設計になります。
Haversine公式で地球の丸みを考慮した距離計算をする
function calcDistance(lat1, lng1, lat2, lng2) {
const R = 6371;
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLng = (lng2 - lng1) * Math.PI / 180;
const a = Math.sin(dLat / 2) ** 2 +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLng / 2) ** 2;
return R * (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)));
}
単純な平面計算だと、距離が離れるほど誤差が大きくなります。
Haversine公式は地球の球面を考慮した計算式なので、実用的な精度で距離が出ます。
高校生の時に三角関数から逃げた私にとっては「なんとなく分かるけど呪文」なので、「2点の緯度・経度を渡すと直線距離(km)が返ってくる関数」として割り切って使っています。

Geolocation APIで現在地を取得する
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude: uLat, longitude: uLng } = position.coords;
// 距離計算・表示処理
},
(error) => {
errorMsg.innerText = "位置情報の取得が許可されませんでした";
}
);
getCurrentPosition() の第1引数が成功時、第2引数がエラー時のコールバックです。
閲覧者に拒否されたときの処理を書いておくのがポイントで、これがないと反応がないまま止まってしまいます。
さらに、ボタンのテキストを「取得中…」に変えて処理後に戻す、という小さな配慮も入れています。
map → sort → slice → map のチェーンで一気に処理する
const html = STATIONS
.map(st => ({ ...st, distance: calcDistance(uLat, uLng, st.lat, st.lng) }))
.sort((a, b) => a.distance - b.distance)
.slice(0, CONFIG.MAX_DISPLAY)
.map(st => `
<a href="${st.url}" class="item" target="${CONFIG.LINK_TARGET}">
<span class="storeName">${st.name}</span>
<span class="storeDist">約${st.distance.toFixed(2)}km</span>
</a>
`).join('');
resultList.innerHTML = html;
処理の流れをメソッドチェーンで一本化しています。
| メソッド | やっていること |
|---|---|
map(1回目) | 各駅に distance プロパティを追加 |
sort | 距離の昇順で並べ替え |
slice | 上位4件に絞り込む |
map(2回目) | HTML文字列に変換 |
それぞれの責務が1行ずつ分かれているので、処理を追加・変更するときも迷わずに済みます。
場所データを自分で用意するには
STATIONSに登録する緯度・経度は、以下の方法で確認できます。
Googleマップで確認する

Googleマップで目的の場所を開き、地図上で右クリックすると緯度・経度がポップアップで表示されます。
数値をそのままコピーして lat・lng に貼り付けるだけでOKです。
国土地理院の地図サービスで確認する
所在地が分かるのであれば、地理院地図(国土地理院)も便利です。
地図上で地点を右クリックすると「ここの緯度経度」という選択肢が表示され、数値をコピーできます。
さいごに
「駅」を例にしたコードですが、応用の幅はけっこう広いです。
たとえばこんな使い方が考えられます。
- 現在地から自社の店舗を近い順に案内する(実店舗を持つ企業サイトなど)
- 現在地から近いイベント会場をピックアップする(複数会場で開催されるイベントの告知ページなど)
- 現在地から近い観光スポットを紹介する(地域の観光サイトや旅行ブログなど)
外部APIやライブラリなしで動くので、「とりあえず近い順に出したい」という場面にはちょうどいい内容です。
ぜひ試してみてください。
なお、データの並び替えや絞り込みをもっと手軽にやりたい場合は、List.jsを使う方法も紹介しています。 合わせて参考にしてみてください。
→[JS]List.jsで要素を検索、並び替え(ソート)、絞り込む方法
それではっ!





