🚶

【Laravel】GoogleMapsAPIを使って現在地を表示させる方法

2020/10/06に公開

はじめに

この記事のゴール

Laravelのプロジェクト内に、GoogleMapsAPIを使って現在地を表示させる

この記事の続きです。
【Laravel】GoogleMapsAPIを使って地図を表示させる方法(完全版)

【完成の図】

ゴールまでの道のり

  1. 現在地を取得して、consoleに表示させる
  2. 位置情報をタグに埋め込む
  3. 現在地にピンを刺す

この記事の対象者

  • 初めてGoogleMapsAPIを使う方
  • Laravel初学者

環境

  • macOS Catalina 10.15.5
  • PHP 7.3.17
  • Laravel Framework 6.18.41

実践

1. 現在地を取得して、consoleに表示させる

1-1.LaravelCollective HTMLのインストール

まず初めに、LaravelCollective HTMLをインストールしましょう。
LaravelCollective HTMLとは、HTMLのリンクやフォームなどをPHPコードで作成することができる、Laravelの便利なライブラリです。

ターミナルにて

composer require laravelcollective/html:^6.0

と打ってください。インストールが始まるので、少し待ちます。

処理が終わったら、
プロジェクト直下にcomposer.json が 自動的に更新され、指定したパッケージ名とバージョンが記載されていればオッケーです(同じくcomposer.lockも更新されます)
composer.jsonにて

"laravelcollective/html": "^6.0"

(僕の場合は15行目でした)

1-2.現在地を取得し、consoleに出力させます

次に、現在地を取得して、consoleに出力させます。

まず、現在地を取得するため、jsファイル作成しましょう。
maps/public/js/setLocation.jsとします。
(publicの下にjsディレクトリ作って、その中にsetLocation.jsを作ります)
中身はこのように記述します。

function setLocation(pos) {

    // 緯度・経度を取得
    const lat = pos.coords.latitude;
    const lng = pos.coords.longitude;
    // 定数lat,lng をconsoleに出力
    console.log(lat);
    console.log(lng);

}

// エラー時に呼び出される関数
function showErr(err) {
    switch (err.code) {
        case 1 :
            alert("位置情報の利用が許可されていません");
            break;
        case 2 :
            alert("デバイスの位置が判定できません");
            break;
        case 3 :
            alert("タイムアウトしました");
            break;
        default :
            alert(err.message);
    }
}

// geolocation に対応しているか否かを確認
if ("geolocation" in navigator) {
    var opt = {
        "enableHighAccuracy": true,
        "timeout": 10000,
        "maximumAge": 0,
    };
    navigator.geolocation.getCurrentPosition(setLocation, showErr, opt);
} else {
    alert("ブラウザが位置情報取得に対応していません");
}

次に、いま作成した setlocation.js をwelcome.blade.php で使えるようにします。

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
    中略
    </head>
    <body>
        <div id="map" style="height:500px">
	</div>
	<script src="{{ asset('/js/setLocation.js') }}"></script> //追加
        <script src="{{ asset('/js/result.js') }}"></script>
     <script src="https://maps.googleapis.com/maps/api/jslanguage=ja&region=JP&key=AIzaSyBrAYTpz9zu0CARYKdQNyYxjuICkA5ajI&callback=initMap" async defer>
	</script>
    </body>
</html>

ここまでできたら、ブラウザで確認してみましょう。
ブラウザを開いて、「Command + Option + I」でChromeデベロッパーツールを開きます。
次にConsoleタブを開きます。

このように、緯度、経度が表示されます。

2. 位置情報をタグに埋め込む

この第2章では、controllerに渡す前段階の、「取得した位置情報(lat,lng)をタグに埋め込む」ところまでやります。(第3章では、Controllerに渡された位置情報(lat,lng)を使い現在地を表示させます)

2-1. welcome.blade.phpにフォームを作成する

welcome.blade.phpにて

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
    中略
    </head>
    <body>
        <div id="map" style="height:500px">
	</div>
	
	{{ 以下を追加 }}
	{!! Form::open(['route' => 'result.currentLocation','method' => 'get']) !!}
       {{--隠しフォームでresult.currentLocationに位置情報を渡す--}}
       {{--lat用--}}
       {!! Form::hidden('lat','lat',['class'=>'lat_input']) !!}
       {{--lng用--}}
       {!! Form::hidden('lng','lng',['class'=>'lng_input']) !!}
       {{--setlocation.jsを読み込んで、位置情報取得するまで押せないようにdisabledを付与し、非アクティブにする。--}}
       {{--その後、disableはfalseになるようにsetlocation.js内に記述した--}}
       {!! Form::submit("周辺を表示", ['class' => "btn btn-success btn-block",'disabled']) !!}
       {!! Form::close() !!}
	
	<script src="{{ asset('/js/setLocation.js') }}"></script>
        <script src="{{ asset('/js/result.js') }}"></script>
     <script src="https://maps.googleapis.com/maps/api/jslanguage=ja&region=JP&key=AIzaSyBrAYTpz9zu0CARYKdQNyYxjuICkA5ajI&callback=initMap" async defer>
	</script>
    </body>
</html>

ここでのポイントは3つです。

  • {!! Form::open(['route' => 'result.currentLocation','method' => 'get']) !!} これでGETメソッドで、result.currentLocationという名前のルートを使うことを指定しています(このルートはまだ、作ってないので、あとで作っていきます)
  • Form::hidden これを使って、ユーザーには見えない形で値の取得や引き渡しができます。
  • submitタグ内にdisabledと記述することで、ボタンをデフォルトで、押せなくしておきます。(現在地を取得したらボタンを押せるように、後ほどsetLocation.jsに記述していきます)

2-2. jQueryのCDN利用

jQueryをCDNで利用します。

<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>

これを、
welcome.blade.php内に追加します。

省略
    <div id="map" style="height:500px">
    </div>
    {!! Form::open(['route' => 'result.currentLocation','method' => 'get']) !!}
    {{--隠しフォームでresult.currentLocationに位置情報を渡す--}}
    {{--lat用--}}
    {!! Form::hidden('lat','lat',['class'=>'lat_input']) !!}
    {{--lng用--}}
    {!! Form::hidden('lng','lng',['class'=>'lng_input']) !!}
    {{--setlocation.jsを読み込んで、位置情報取得するまで押せないようにdisabledを付与し、非アクティブにする。--}}
    {{--その後、disableはfalseになるようにsetlocation.js内に記述した--}}
    {!! Form::submit("周辺を表示", ['class' => "btn btn-success btn-block",'disabled']) !!}
    {!! Form::close() !!}
    
    {{-- ここに追加 --}}
    <script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
    
    <script src="{{ asset('/js/setLocation.js') }}"></script>
    <script src="{{ asset('/js/result.js') }}"></script>
    <script src="https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key=AIzaSyDkveHRqHWUqMU4CS_isfGbuBrzzoo6v4o&callback=initMap" async defer>
    </script>

これで、jQueryが使えるようになりました。

2-3. フォームへ埋め込む

setLocation.jsにて
jQueryを用いて、$(".lat_input").val(lat);と$(".lng_input").val(lng);を追加します。
welcome.blade.php内において、lat_input(lng_input)クラスを探して、そのvalue属性に定数lat(lng)を埋め込むという記述です。
実際に追加していきましょう。

function setLocation(pos) {

    // 緯度・経度を取得
    const lat = pos.coords.latitude;
    const lng = pos.coords.longitude;

    console.log(lat);
    console.log(lng);

    // welcomeの中からlat_inputのclassを見つけて、そのvalueに、定数latを代入
    $(".lat_input").val(lat);
    //welcomeの中からlng_inputのclassを見つけて、そのvalueに、定数lngを代入
    $(".lng_input").val(lng);
}

以下省略
$('.btn').prop('disabled', false)

ここで最後の行に$('.btn').prop('disabled', false)を追加しています。
これは、welcome.blade.php内に書いた、```disabled'''をfalseにするための記述です。
ファイルの一番最後に書くことで、読み込みが終わったら(現在地を取得できたら)、ボタンを押せるようにすることができます。

ここまで、できたら、ブラウザの確認してみましょう。
ChromeデベロッパーツールのElementsタブのform内のinputタグのvalueの値が緯度経度になっているかと思います。

3. 現在地にピンを刺す

最後にvalueの値をcontrollerで処理して、現在地周辺の地図を表示させていきます。

3-1. ルートの設定

routes/web.phpにて

<?php

Route::get('/', function () {
    return view('welcome');
});

// 追加
Route::get('result', 'ResultController@currentLocation')->name('result.currentLocation');

これは、GETメソッドで、/resultページの処理について、ResultControllerのcurrentLocationアクションを実行するというルートをresult.currentLocfationという名前で保存するということです。

このResultControllerとcurrentLocationアクションは今から作っていきます。

3-2. アクションの作成

まず、ResultControllerを作っていきます。
ターミナルにて

php artisan make:controller ResultController

とコマンドを打つと、
app/Http/Controllersの中にResultControllerができているはずです。
中身はこんな感じだと思います。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ResultController extends Controller
{

}

ここに、アクションを記述していきます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ResultController extends Controller
{
    public function currentLocation(Request $request)
    {
        $lat = $request->lat;
        $lng = $request->lng;
        // currentLocationで表示
        return view('currentLocation', [
            // 現在地緯度latをbladeへ渡す
            'lat' => $lat,
            // 現在地経度lngをbladeへ渡す
            'lng' => $lng,
        ]);
    }
}

まず,送られてきたフォームの内容は $request に入っています。
なので、$lat = $request->latとすることで、送られてきたフォームのlatのvalueを変数$latに格納することができます。
次に、return viewとし、currentLocation.blade.phpに、ここで指定した、latを blade側で、latという形で使えるようにします。

3-3. 現在地を表示させるbladeの作成

welcome.blade.phpをコピーして、同じディレクトリにcurrentLocation.blade.phpを作成します。
このように修正します。

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
    中略
    </head>
    <body>
    <div id="map" style="height:500px">
    </div>
        <script>
            // currentLocation.jsで使用する定数latに、controllerで定義した$latをいれて、currentLocation.jsに渡す
            const lat = {{ $lat }};

            // currentLocation.jsで使用する定数lngに、controllerで定義した$lngをいれて、currentLocation.jsに渡す
            const lng = {{ $lng }};
        </script>
        {{--    上記の処理をしてから、googleMapを読み込まないとエラーが出てくる--}}

    <script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
    <script src="{{ asset('/js/setLocation.js') }}"></script>
    <script src="{{ asset('/js/currentLocation.js') }}"></script>
    <script src="https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key=AIzaSyDkveHRqHWUqMU4CS_isfGbuBrzzoo6v4o&callback=initMap" async defer>
    </script>
    </body>
</html>

ここでのポイントは2つです。
1つ目は、currentLocation.jsでコントローラーから渡ってきた$latを使うために、scriptタグで挟んで定数latに格納していることです。
2つ目は
<script src="{{ asset('/js/currentLocation.js') }}"></script>を追加して、currentLocation.jsを使う準備をしたことです(currentLocation.jsは今から作っていきます)

3-4. 現在地を表示させるjsの作成

currentLocation.blade.phpにおいて、<script src="{{ asset('/js/currentLocation.js') }}"></script>を記述しているので、あとは、
currentLocation.jsを作っていきます。
result.jsと同じディレクトリに作成します。
中身はこのように記述します。

function initMap() {
    // google map へ表示するための設定
    latlng = new google.maps.LatLng(lat, lng);
    map = document.getElementById("map");
    opt = {
        zoom: 2,
        center: latlng,
    };
    // google map 表示
    mapObj = new google.maps.Map(map, opt);
    // マーカーを設定
    marker = new google.maps.Marker({
        position: latlng,
        map: mapObj,
        title: '現在地',
    });
}

ここでのポイントは
まず、latlng=new google.maps.LatLng(lat,lng)とすることで、bladeから渡ってきた現在地情報のlat,lngをlanlngの中に格納することができます。
次に、map = document.getElementById("map");とすることで、currentLocation.blade.php内のidがmapの要素を見つけて、mapに格納します。
また、opt = {center: latlng}とすることで、現在地情報が入ったlatlngをセンターにすることができます。

※opt = {zoom:2}としているため、世界地図レベルの縮尺となっております。みなさんは13とか14で試してみてくださいね。

ここまでできたら、ブラウザを見てみましょう。

http://127.0.0.1:8000/ にアクセスします。
(ターミナルでphp artisan serveでサーバーが起動しているか確認してから)

この画面が出たら、画面左に配置している「周辺を表示」ボタンを押しましょう。

すると、

現在地周辺が表示され、ピンが刺されているかと思います。
(IPアドレスの関係で、まあまあ誤差がありますが、、、)

以上が
「Laravelのプロジェクト内に、GoogleMapsAPIを使って現在地を表示させる方法」でした。

おわりに

次は、住所を入力したら、緯度経度を表示させる方法を共有したいと思います。

Discussion