WEB制作、マーケティングに関する情報をお届けします。ホームページ制作会社、テラのブログ

Javascriptでユーザーの位置情報を取得、県ごとに処理を行う方法

タグ:

他店舗運営しているサイトなどにアクセスすると自分の所在地に近い店舗が表示されたりすることはありませんか?
これを実装するにはブラウザでユーザーの現在位置を取得して任意の処理を行う必要があります。
今回は『Javascriptでユーザーの位置情報を取得、県ごとに処理を行う方法』を紹介します。
※位置情報取得の許可後に少し時間がかかりますのでローディングアイコンなどがあった方がいいかもしれません。

コードを紹介

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>位置情報による県ごとの処理</title>
</head>
<body>
    <!-- ここにページのコンテンツを記載 -->
    <div class="output_wrap">
        <h3>位置情報を取得します。</h3>
        <div id="output">- -</div>
    </div>
<style>
body{
    position: relative;
    height: 100vh;
    width: 100vw;
}
.output_wrap{
    width: 300px;
    height: 130px;
    text-align: center;
    background: #313131;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    color: #FFF;
    font-weight: bold;
    padding: 15px 0;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
<script>
(function($) {
    const timerElement = document.getElementById('output');
    $(document).ready(function() {
        // 県ごとの位置情報 (県庁所在地の緯度・経度)
        var prefectures = [
            ['北海道', 43.064310,141.346879],
            ['青森県', 40.824589,140.740548],
            ['岩手県', 39.703526,141.152696],
            ['宮城県', 38.268579,140.872072],
            ['秋田県', 39.718626,140.102381],
            ['山形県', 38.240434,140.363690],
            ['福島県', 37.750029,140.467771],
            ['茨城県', 36.341737,140.446824],
            ['栃木県', 36.565912,139.883592],
            ['群馬県', 36.390688,139.060453],
            ['埼玉県', 35.857033,139.649012],
            ['千葉県', 35.604560,140.123154],
            ['東京都', 35.689501,139.691722],
            ['神奈川県', 35.447734,139.642537],
            ['新潟県', 37.902451,139.023245],
            ['富山県', 36.695265,137.211305],
            ['石川県', 36.594606,136.625669],
            ['福井県', 36.065209,136.221720],
            ['山梨県', 35.664108,138.568455],
            ['長野県', 36.651306,138.180904],
            ['岐阜県', 35.391174,136.723657],
            ['静岡県', 34.976944,138.383056],
            ['愛知県', 35.180209,136.906582],
            ['三重県', 34.730278,136.508611],
            ['滋賀県', 35.004513,135.868568],
            ['京都府', 35.021242,135.755613],
            ['大阪府', 34.686344,135.520037],
            ['兵庫県', 34.691257,135.183078],
            ['奈良県', 34.685274,135.832861],
            ['和歌山県', 34.226111,135.167500],
            ['鳥取県', 35.503449,134.238261],
            ['島根県', 35.472293,133.050520],
            ['岡山県', 34.661739,133.935032],
            ['広島県', 34.396558,132.459646],
            ['山口県', 34.186041,131.470654],
            ['徳島県', 34.065761,134.559286],
            ['香川県', 34.340112,134.043291],
            ['愛媛県', 33.841642,132.765682],
            ['高知県', 33.559722,133.531111],
            ['福岡県', 33.606389,130.417968],
            ['佐賀県', 33.249351,130.298792],
            ['長崎県', 32.750040,129.867251],
            ['熊本県', 32.789800,130.741584],
            ['大分県', 33.238130,131.612645],
            ['宮崎県', 31.911034,131.423887],
            ['鹿児島県', 31.560171,130.558025],
            ['沖縄県', 26.212445,127.680922]
        ];

        // 位置情報の取得
        if (navigator.geolocation) {
            // ユーザーの現在位置を取得
            navigator.geolocation.getCurrentPosition(success, error);
        } else {
            // 位置情報がサポートされていない場合の処理
            timerElement.textContent = "お使いのブラウザでは位置情報がサポートされていません。";
        }

        // 位置情報の取得に成功した場合の処理
        function success(position) {
            var lat = position.coords.latitude;  // 現在の緯度を代入
            var lng = position.coords.longitude; // 現在の経度を代入
            // 最も近い県を特定
            var closestPrefecture = getClosestPrefecture(lat, lng);
            // ここに県ごとの処理を追加
            timerElement.textContent = closestPrefecture[0] + "と判断しました。";
        }

        // 最も近い県を特定する関数
        function getClosestPrefecture(lat, lng) {
            var minDistance = Infinity;  // 最小距離を初期化
            var closestPrefecture = null; // 最も近い県を初期化
            // 各県との距離を計算して最も近い県を特定
            prefectures.forEach(function(prefecture) {
                var distance = getDistance(lat, lng, prefecture[1], prefecture[2]);
                if (distance < minDistance) {
                    minDistance = distance;
                    closestPrefecture = prefecture;
                }
            });
            return closestPrefecture;
        }
        
        // 2地点間の距離を計算する関数(ハバースインの公式を使用)
        function getDistance(lat1, lng1, lat2, lng2) {
            var radLat1 = lat1 * Math.PI / 180; // 緯度1をラジアンに変換
            var radLng1 = lng1 * Math.PI / 180; // 経度1をラジアンに変換
            var radLat2 = lat2 * Math.PI / 180; // 緯度2をラジアンに変換
            var radLng2 = lng2 * Math.PI / 180; // 経度2をラジアンに変換
            var a = radLat1 - radLat2; // 緯度の差
            var b = radLng1 - radLng2; // 経度の差
            // ハバースインの公式による距離の計算
            var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
                    Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
            s = s * 6378137.0; // 地球の半径(メートル)
            s = Math.round(s * 10000) / 10000; // 距離を四捨五入してメートル単位に
            return s;
        }
        
        
        // 位置情報の取得に失敗した場合の処理
        function error() {
            timerElement.textContent = "位置情報の許可が必要です。";
        }


    });
})(jQuery);
</script>
</body>
</html>

コードを解説

HTMLの説明は割愛します。
jqueryを使用しますのでインクルードしてください。
以下は、HTMLに処理を吐き出すためのものですので書き換えて使用してください。

const timerElement = document.getElementById('output');

県ごとの位置を設定していきますが、今回はこちらのサイトを参考にして緯度軽度を設定していきます。
以下で、県名、緯度、経度を配列で入れていきます。

var prefectures = [
    ['北海道', 43.064310,141.346879],
    ['青森県', 40.824589,140.740548],
    ['岩手県', 39.703526,141.152696],
    ['宮城県', 38.268579,140.872072],
    ['秋田県', 39.718626,140.102381],
    ['山形県', 38.240434,140.363690],
    ['福島県', 37.750029,140.467771],
    ['茨城県', 36.341737,140.446824],
    ['栃木県', 36.565912,139.883592],
    ['群馬県', 36.390688,139.060453],
    ['埼玉県', 35.857033,139.649012],
    ['千葉県', 35.604560,140.123154],
    ['東京都', 35.689501,139.691722],
    ['神奈川県', 35.447734,139.642537],
    ['新潟県', 37.902451,139.023245],
    ['富山県', 36.695265,137.211305],
    ['石川県', 36.594606,136.625669],
    ['福井県', 36.065209,136.221720],
    ['山梨県', 35.664108,138.568455],
    ['長野県', 36.651306,138.180904],
    ['岐阜県', 35.391174,136.723657],
    ['静岡県', 34.976944,138.383056],
    ['愛知県', 35.180209,136.906582],
    ['三重県', 34.730278,136.508611],
    ['滋賀県', 35.004513,135.868568],
    ['京都府', 35.021242,135.755613],
    ['大阪府', 34.686344,135.520037],
    ['兵庫県', 34.691257,135.183078],
    ['奈良県', 34.685274,135.832861],
    ['和歌山県', 34.226111,135.167500],
    ['鳥取県', 35.503449,134.238261],
    ['島根県', 35.472293,133.050520],
    ['岡山県', 34.661739,133.935032],
    ['広島県', 34.396558,132.459646],
    ['山口県', 34.186041,131.470654],
    ['徳島県', 34.065761,134.559286],
    ['香川県', 34.340112,134.043291],
    ['愛媛県', 33.841642,132.765682],
    ['高知県', 33.559722,133.531111],
    ['福岡県', 33.606389,130.417968],
    ['佐賀県', 33.249351,130.298792],
    ['長崎県', 32.750040,129.867251],
    ['熊本県', 32.789800,130.741584],
    ['大分県', 33.238130,131.612645],
    ['宮崎県', 31.911034,131.423887],
    ['鹿児島県', 31.560171,130.558025],
    ['沖縄県', 26.212445,127.680922]
];

次にユーザーの緯度軽度を取得します。
『navigator.geolocation』で位置情報にアクセスするためのGeolocationオブジェクトがあるかどうかを確認します。空値が返ってくる場合はブラウザが対応していません。
『true』が返ってきたら
処理内にある『navigator.geolocation.getCurrentPosition(success, error);』で位置情報を取得します。『success』で位置情報の取得できた場合のコールバック関数を設定、positionオブジェクトを引数として引き取ります。『error』で位置情報の取得できなかった場合のコールバック関数を設定、errorオブジェクトを引数として引き取ります。

// 位置情報の取得
if (navigator.geolocation) {
    // ユーザーの現在位置を取得
    navigator.geolocation.getCurrentPosition(success, error);
} else {
    // 位置情報がサポートされていない場合の処理
    timerElement.textContent = "お使いのブラウザでは位置情報がサポートされていません。";
}

位置情報の取得に成功した場合の処理を書いていきます。
成功した場合はpositionオブジェクトから緯度と緯度を取得していきます。
位置情報を取得後に『getClosestPrefecture(lat, lng);』で最も近い県を特定するための関数へと処理を回します。
この処理で県名が返ってくるので処理を書いていきますが、配列の最初に県名が入っていますので県ごとに処理を書くと分岐できます。今回は県名を表示するだけとなっています。

function success(position) {
    var lat = position.coords.latitude;  // 現在の緯度を代入
    var lng = position.coords.longitude; // 現在の経度を代入
    // 最も近い県を特定
    var closestPrefecture = getClosestPrefecture(lat, lng);
    // ここに県ごとの処理を追加
    timerElement.textContent = closestPrefecture[0] + "と判断しました。";
}

県を特定する関数を書いていきます。
『getClosestPrefecture(lat, lng)』では経度と緯度が引き渡されています。
『minDistance』に最大値、『closestPrefecture』にnullを入れてそれぞれ変数を初期化します。
最初に県ごとの経度、緯度を配列で挿入した『prefectures』を『forEach』でループにかけて一つずつ処理していきます。『getDistance』に現在の緯度経度、県ごとの緯度経度を渡して計算させます。
この処理は47県分処理されます。
『if (distance < minDistance) {}』で最大値より小さい場合に『closestPrefecture』に県名、経度、緯度をセットします。最後に『return』で『closestPrefecture(最も近い県名、経度、緯度が入っている)』を返します。

// 最も近い県を特定する関数
function getClosestPrefecture(lat, lng) {
    var minDistance = Infinity;  // 最小距離を初期化
    var closestPrefecture = null; // 最も近い県を初期化
    // 各県との距離を計算して最も近い県を特定
    prefectures.forEach(function(prefecture) {
        var distance = getDistance(lat, lng, prefecture[1], prefecture[2]);
        if (distance < minDistance) {
            minDistance = distance;
            closestPrefecture = prefecture;
        }
    });
    return closestPrefecture;
}

2地点の距離を計算するにはハバースインの計算式を使用します。
ハバースインの計算式はこちらをご確認ください。
retuen sで距離が返されます。

// 2地点間の距離を計算する関数(ハバースインの公式を使用)
function getDistance(lat1, lng1, lat2, lng2) {
    var radLat1 = lat1 * Math.PI / 180; // 緯度1をラジアンに変換
    var radLng1 = lng1 * Math.PI / 180; // 経度1をラジアンに変換
    var radLat2 = lat2 * Math.PI / 180; // 緯度2をラジアンに変換
    var radLng2 = lng2 * Math.PI / 180; // 経度2をラジアンに変換
    var a = radLat1 - radLat2; // 緯度の差
    var b = radLng1 - radLng2; // 経度の差
    // ハバースインの公式による距離の計算
    var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
            Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
    s = s * 6378137.0; // 地球の半径(メートル)
    s = Math.round(s * 10000) / 10000; // 距離を四捨五入してメートル単位に
    return s;
}

位置情報の取得が失敗した場合の処理も書いておきます。

// 位置情報の取得に失敗した場合の処理
function error() {
    timerElement.textContent = "位置情報の許可が必要です。";
}

まとめ

以上、『Javascriptでユーザーの位置情報を取得、県ごとに処理を行う方法』でした。
現在地から近い施設へ誘導するという仕組みはスマホの機能向上から少しずつ見るようになりましたが今は当たり前のようにサイトでは使用しますね。
ぜひ、こちらを参考にしてください。

テラ合同会社(東京都)

テラは2014年に東京都でスタートアップしたホームページ制作会社です。ホームページ制作以外にも広告運用、マーケティング、ブランディング、印刷物など幅広い領域をサポートしています。
コーポレートサイトはこちらをご覧ください。