【Laravel】GoogleMapsAPIを使って現在地を表示させる方法
はじめに
この記事のゴール
Laravelのプロジェクト内に、GoogleMapsAPIを使って現在地を表示させる
この記事の続きです。
【Laravel】GoogleMapsAPIを使って地図を表示させる方法(完全版)
【完成の図】
ゴールまでの道のり
- 現在地を取得して、consoleに表示させる
- 位置情報をタグに埋め込む
- 現在地にピンを刺す
この記事の対象者
- 初めて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®ion=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®ion=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®ion=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に、ここで指定した、
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®ion=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