1. 始める前に
Google Maps Platform の Maps API と Places API を使用してローカル ビジネス検索を作成し、ユーザーの現在地や付近の注目スポットを表示する方法を学習します。このアプリには、位置情報、Place Details、プレイスフォトなどが統合されています。
前提条件
- HTML、CSS、JavaScript の基本的な知識
- 請求先アカウントを含むプロジェクト(まだお持ちでない場合は、次のステップに従ってください)。
- 以下の有効化の手順では、Maps JavaScript API と Places API を有効にする必要があります。
- 上記のプロジェクトの API キー。
Google Maps Platform を使ってみる
Google Maps Platform を初めて使用する場合は、Google Maps Platform スタートガイドを参照するか、再生リスト「Getting Started with Google Maps Platform」を視聴して、以下の手順を行ってください。
- 請求先アカウントを作成します。
- プロジェクトを作成します。
- Google Maps Platform の API と SDK(前セクションに記載のもの)を有効化します。
- API キーを生成します。
演習内容
- Google マップを表示するウェブページを作成する
- ユーザーの現在地が地図の中心に表示されるようになりました
- 付近の場所を見つけて、結果をクリック可能なマーカーとして表示する
- 各場所の詳細を取得して表示します
必要なもの
- Google Chrome(推奨)、Firefox、Safari、Internet Explorer などのウェブブラウザ
- お気に入りのテキスト エディタやコードエディタ
サンプルコードを取得する
- コマンドライン インターフェース(MacOS の場合は Terminal、Windows の場合はコマンド プロンプト)を開き、次のコマンドを使用してサンプルコードをダウンロードします。
git clone https://github.com/googlecodelabs/google-maps-nearby-search-js/
それでも問題が解決しない場合は、次のボタンをクリックしてこの Codelab のすべてのコードをダウンロードし、ファイルを解凍します。
- クローンを作成またはダウンロードしたディレクトリに移動します。
cd google-maps-nearby-search-js
stepN
フォルダには、この Codelab の各ステップの望ましい最終状態が含まれています。参考用に用意されています。コーディング作業はすべて、work
というディレクトリで行います。
2. デフォルトの中心点を含む地図を作成する
ウェブページに Google マップを作成するには、次の 3 つの手順を行います。
- HTML ページを作成する
- 地図を追加する
- API キーを貼り付ける
1. HTML ページを作成する
以下は、このステップで作成したマップです。マップの中心はシドニー(オーストラリア)のシドニー オペラハウスです。ユーザーが位置情報の取得を許可しなかった場合、地図はデフォルトではこの位置情報を使用しますが、興味深い検索結果を表示します。
work/
フォルダに移動します。Codelab の残りの部分を通して、work/
フォルダのバージョンを編集します。
cd work
work/
ディレクトリで、テキスト エディタを使用してindex.html
という名前の空のファイルを作成します。- 次のコードを
index.html
にコピーします。
index.html
<!DOCTYPE html>
<html>
<head>
<title>Sushi Finder</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
background-color: grey;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
/* TODO: Step 4A1: Make a generic sidebar. */
</style>
</head>
<body>
<!-- TODO: Step 4A2: Add a generic sidebar -->
<!-- Map appears here -->
<div id="map"></div>
<!-- TODO: Step 1B, Add a map -->
</body>
</html>
- ウェブブラウザで
index.html
ファイルを開きます。
open index.html
2. 地図を追加する
このセクションでは、Maps JavaScript API をウェブページに読み込み、API を使って地図をウェブページに追加する独自の JavaScript を作成する方法を説明します。
- このスクリプト スクリプトを、
map
div の後の<!-- TODO: Step 1B, Add a map -->
終了タグ</body>
の前に追加します。
step1/index.html
<!-- TODO: Step 1B, Add a map -->
<script>
/* Note: This example requires that you consent to location sharing when
* prompted by your browser. If you see the error "Geolocation permission
* denied.", it means you probably did not give permission for the browser * to locate you. */
/* TODO: Step 2, Geolocate your user
* Replace the code from here to the END TODO comment with new code from
* codelab instructions. */
let pos;
let map;
function initMap() {
// Set the default location and initialize all variables
pos = {lat: -33.857, lng: 151.213};
map = new google.maps.Map(document.getElementById('map'), {
center: pos,
zoom: 15
});
}
/* END TODO: Step 2, Geolocate your user */
</script>
<!-- TODO: Step 1C, Get an API key -->
<!-- TODO: Step 3A, Load the Places Library -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
3. API キーを貼り付ける
<!-- TODO: Step 1C, Get an API key -->
の後の行で、スクリプト ソース URL のキーパラメータの値をコピーして、前提条件で作成した API キーに置き換えます。
step1/index.html
<!-- TODO: Step 1C, Get an API key -->
<!-- TODO: Step 3A, Load the Places Library -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
- 作業中の HTML ファイルを保存します。
テスト
編集中のファイルのブラウザビューを再読み込みします。グレーの長方形が配置されていた地図が表示されます。エラー メッセージが表示される場合は、最後の <script>
タグの「YOUR_API_KEY
」をご自身の API キーに置き換えてください。API キーを取得する方法については、上記を参照してください。
完全なサンプルコード
ここまでのこのプロジェクトの完全なコードは、GitHub で入手できます。
3. ユーザーの位置情報を取得する
次に、ブラウザ上の HTML5 Geolocation 機能と Maps JavaScript API を併用して、ユーザーやデバイスの地理的位置を Google マップに表示します。
次の画像は、カリフォルニア州マウンテンビューからブラウジングしているときに、地理的位置を示したものです。
位置情報とは
位置情報とは、さまざまなデータ収集メカニズムによって、ユーザーまたはコンピューティング デバイスの地理的位置を特定することです。通常、ほとんどの位置情報サービスでは、ネットワークのルーティング アドレスや内蔵 GPS デバイスを使用してこの位置を判断します。このアプリは、ウェブブラウザの W3C Geolocation 規格 navigator.geolocation
プロパティを使用して、ユーザーの位置情報を判定します。
実際に試す
コメント TODO: Step 2, Geolocate your user
と END TODO: Step 2, Geolocate your user
の間にあるコードを次のコードで置き換えます。
step2/index.html
/* TODO: Step 2, Geolocate your user
* Replace the code from here to the END TODO comment with this code
* from codelab instructions. */
let pos;
let map;
let bounds;
let infoWindow;
let currentInfoWindow;
let service;
let infoPane;
function initMap() {
// Initialize variables
bounds = new google.maps.LatLngBounds();
infoWindow = new google.maps.InfoWindow;
currentInfoWindow = infoWindow;
/* TODO: Step 4A3: Add a generic sidebar */
// Try HTML5 geolocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(position => {
pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
map = new google.maps.Map(document.getElementById('map'), {
center: pos,
zoom: 15
});
bounds.extend(pos);
infoWindow.setPosition(pos);
infoWindow.setContent('Location found.');
infoWindow.open(map);
map.setCenter(pos);
/* TODO: Step 3B2, Call the Places Nearby Search */
}, () => {
// Browser supports geolocation, but user has denied permission
handleLocationError(true, infoWindow);
});
} else {
// Browser doesn't support geolocation
handleLocationError(false, infoWindow);
}
}
// Handle a geolocation error
function handleLocationError(browserHasGeolocation, infoWindow) {
// Set default location to Sydney, Australia
pos = {lat: -33.856, lng: 151.215};
map = new google.maps.Map(document.getElementById('map'), {
center: pos,
zoom: 15
});
// Display an InfoWindow at the map center
infoWindow.setPosition(pos);
infoWindow.setContent(browserHasGeolocation ?
'Geolocation permissions denied. Using default location.' :
'Error: Your browser doesn\'t support geolocation.');
infoWindow.open(map);
currentInfoWindow = infoWindow;
/* TODO: Step 3B3, Call the Places Nearby Search */
}
/* END TODO: Step 2, Geolocate your user */
/* TODO: Step 3B1, Call the Places Nearby Search */
テスト
- ファイルを保存します。
- ページを再読み込みします。
ブラウザで現在地情報の共有を求めるメッセージが表示されます。
- [ブロック] を 1 回クリックして、エラーが適切に処理され、中心がシドニーにあるかどうかを確認します。
- もう一度再読み込みを行い、[許可] をクリックして、位置情報が機能するかどうかを確認し、地図を現在地に移動します。
完全なサンプルコード
ここまでのこのプロジェクトの完全なコードは、GitHub で入手できます。
4. 付近の場所を検索する
周辺検索では、キーワードまたはタイプで、指定した地域内の場所を検索できます。周辺検索には、次のいずれかの方法で指定して、場所を含める必要があります。
- 長方形の検索領域を定義する
LatLngBounds
オブジェクト location
プロパティ(円の中心をLatLng
オブジェクトとして指定)と半径(メートル単位)の組み合わせとして定義された円形の領域
Nearby Search を開始するには、PlacesService
nearbySearch()
メソッドを呼び出します。このメソッドは PlaceResult
オブジェクトの配列を返します。
A. プレイス ライブラリを読み込む
まず、プレイス ライブラリ サービスにアクセスするには、スクリプトのソース URL を更新して、libraries
パラメータを追加し、値として places
を追加します。
step3/index.html
<!-- TODO: Step 3A, Load the Places Library -->
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap">
B. Places Nearby Search リクエストを呼び出し、レスポンスを処理します。
次に、PlaceSearch リクエストを作成します。最小必須項目は次のとおりです。
最小必須項目は次のとおりです。
bounds
: 長方形の検索領域を定義するgoogle.maps.LatLngBounds
オブジェクト、またはlocation
とradius
である必要があります。前者はgoogle.maps.LatLng
オブジェクト、後者は円の半径(メートル単位)を表す単純な整数を取ります。最大半径は 50,000 メートルです。rankBy
がDISTANCE
に設定されている場合、場所を指定する必要がありますが、半径または境界を指定することはできません。keyword
利用可能なすべてのフィールド(名前、種類、住所、およびユーザーのレビューと第三者のコンテンツまたはtype
を含むが、これらに限定されない)に一致させ、結果を指定したタイプに一致する場所に限定します。指定できるタイプは 1 つのみです(複数のタイプが指定されている場合、最初の入力に続くすべてのタイプは無視されます)。サポートされるタイプのリストをご覧ください。
この Codelab では、検索の位置としてユーザーの現在位置を使用し、距離に基づいて結果をランク付けします。
- コメント
TODO: Step 3B1
に次のコードを追加して、検索を呼び出し、レスポンスを処理する 2 つの関数を記述します。
検索キーワードとして「sushi
」を使用していますが、変更することもできます。createMarkers
関数を定義するコードは次のセクションで説明します。
step3/index.html
/* TODO: Step 3B1, Call the Places Nearby Search */
// Perform a Places Nearby Search Request
function getNearbyPlaces(position) {
let request = {
location: position,
rankBy: google.maps.places.RankBy.DISTANCE,
keyword: 'sushi'
};
service = new google.maps.places.PlacesService(map);
service.nearbySearch(request, nearbyCallback);
}
// Handle the results (up to 20) of the Nearby Search
function nearbyCallback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
createMarkers(results);
}
}
/* TODO: Step 3C, Generate markers for search results */
- 次の行を
initMap
関数の最後にあるコメントTODO: Step 3B2
に追加します。
/* TODO: Step 3B2, Call the Places Nearby Search */
// Call Places Nearby Search on user's location
getNearbyPlaces(pos);
- 次の行を
handleLocationError
関数の最後にあるコメントTODO: Step 3B3
に追加します。
/* TODO: Step 3B3, Call the Places Nearby Search */
// Call Places Nearby Search on the default location
getNearbyPlaces(pos);
C. 検索結果のマーカーを生成する
マーカーは、地図上の場所を特定するものです。デフォルトでは、マーカーには標準画像が使用されます。マーカー画像のカスタマイズについて詳しくは、マーカーをご覧ください。
google.maps.Marker
コンストラクタは、単一の Marker options
オブジェクト リテラルを受け取ってマーカーの初期プロパティを指定します。
以下のフィールドは、特に重要であり、マーカーの構築時に一般的に設定されます。
position
(必須)は、マーカーの初期位置を識別するLatLng
を指定します。map
(省略可)は、マーカーを配置するマップを指定します。マーカーの作成時に地図を指定しなかった場合、マーカーは作成されても、地図には追加(または表示)されません。後でマーカーを追加するには、マーカーのsetMap()
メソッドを呼び出します。- コメント
TODO: Step 3C
の後に次のコードを追加して、レスポンスで返される場所ごとに 1 つのマーカーの位置、地図、タイトルを設定します。また、bounds
変数のextend
メソッドを使用して、中央とすべてのマーカーが地図上に表示されるようにします。
step3/index.html
/* TODO: Step 3C, Generate markers for search results */
// Set markers at the location of each place result
function createMarkers(places) {
places.forEach(place => {
let marker = new google.maps.Marker({
position: place.geometry.location,
map: map,
title: place.name
});
/* TODO: Step 4B: Add click listeners to the markers */
// Adjust the map bounds to include the location of this marker
bounds.extend(place.geometry.location);
});
/* Once all the markers have been placed, adjust the bounds of the map to
* show all the markers within the visible area. */
map.fitBounds(bounds);
}
/* TODO: Step 4C: Show place details in an info window */
テスト
- ページを保存して再読み込みし、[許可] をクリックして位置情報の利用を許可します。
地図の中心付近に、最大 20 個の赤いマーカーが表示されます。
- もう一度ページを再読み込みし、今回は位置情報の利用許可をブロックします。
地図のデフォルト中央に検索結果は引き続き表示されますか?(このサンプルでは、オーストラリアのシドニーがデフォルトで表示されます)。
完全なサンプルコード
ここまでのこのプロジェクトの完全なコードは、GitHub で入手できます。
5. オンデマンドで Place Details を表示
場所 ID(Nearby Search の検索結果のフィールドの 1 つとして提供されます)を取得したら、その住所に関する追加情報(住所、電話番号、ユーザーの評価やクチコミなど)をリクエストできます。この Codelab では、詳細な Place を表示するためのサイドバーを作成し、マーカーがインタラクティブな場所になるようにして、ユーザーが詳細を表示する場所を選択できるようにします。
A. 一般的なサイドバーを作成する
ここでは、Place Details を表示する場所が必要です。ここでは、サイドバー上でシンプルなマーカーコードを紹介します。このコードは、ユーザーがマーカーをクリックしたときに、場所の詳細をスライドして表示するために使用できます。
- コメント
TODO: Step 4A1
の後にstyle
タグを追加します。
step4/index.html
/* TODO: Step 4A1: Make a generic sidebar */
/* Styling for an info pane that slides out from the left.
* Hidden by default. */
#panel {
height: 100%;
width: null;
background-color: white;
position: fixed;
z-index: 1;
overflow-x: hidden;
transition: all .2s ease-out;
}
.open {
width: 250px;
}
/* Styling for place details */
.hero {
width: 100%;
height: auto;
max-height: 166px;
display: block;
}
.place,
p {
font-family: 'open sans', arial, sans-serif;
padding-left: 18px;
padding-right: 18px;
}
.details {
color: darkslategrey;
}
a {
text-decoration: none;
color: cadetblue;
}
body
セクションのmap
div の直前に、詳細パネル用の div を追加します。
<!-- TODO: Step 4A2: Add a generic sidebar -->
<!-- The slide-out panel for showing place details -->
<div id="panel"></div>
initMap()
関数で、TODO: Step 4A3
コメントの後で、次のようにinfoPane
変数を初期化します。
/* TODO: Step 4A3: Add a generic sidebar */
infoPane = document.getElementById('panel');
B. マーカーにクリック リスナーを追加する
createMarkers
関数で、マーカーを作成する際にクリック リスナーを追加します。
クリック リスナーは、そのマーカーに関連付けられている場所の詳細を取得し、関数を呼び出して詳細を表示します。
- コードコメント
TODO: Step 4B
のcreateMarkers
関数内に次のコードを貼り付けます。
showDetails
メソッドは次のセクションで実装します。
step4/index.html
/* TODO: Step 4B: Add click listeners to the markers */
// Add click listener to each marker
google.maps.event.addListener(marker, 'click', () => {
let request = {
placeId: place.place_id,
fields: ['name', 'formatted_address', 'geometry', 'rating',
'website', 'photos']
};
/* Only fetch the details of a place when the user clicks on a marker.
* If we fetch the details for all place results as soon as we get
* the search response, we will hit API rate limits. */
service.getDetails(request, (placeResult, status) => {
showDetails(placeResult, marker, status)
});
});
addListener
リクエストでは、placeId
プロパティに詳細リクエストの場所を指定します。fields
プロパティにはその場所の詳細情報のフィールド名の配列を指定します。リクエストできるフィールドの完全なリストについては、PlaceResult インターフェースをご覧ください。
C. 情報ウィンドウに Place Details を表示する
情報ウィンドウは、地図上の特定の場所でダイアログの上にコンテンツ(通常はテキストや画像)を表示します。情報ウィンドウには、コンテンツ領域と先が細くなった部分があります。茎の先端が地図上の指定された場所に付けられます。通常、情報ウィンドウはマーカーに関連付けられますが、特定の緯度/経度に関連付けることもできます。
- コメント
TODO: Step 4C
に次のコードを追加して、ビジネスの名前と評価を表示し、そのウィンドウをマーカーに追加するInfoWindow
を作成します。
次のセクションでサイドバーに詳細を表示するための showPanel
を定義します。
step4/index.html
/* TODO: Step 4C: Show place details in an info window */
// Builds an InfoWindow to display details above the marker
function showDetails(placeResult, marker, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
let placeInfowindow = new google.maps.InfoWindow();
placeInfowindow.setContent('<div><strong>' + placeResult.name +
'</strong><br>' + 'Rating: ' + placeResult.rating + '</div>');
placeInfowindow.open(marker.map, marker);
currentInfoWindow.close();
currentInfoWindow = placeInfowindow;
showPanel(placeResult);
} else {
console.log('showDetails failed: ' + status);
}
}
/* TODO: Step 4D: Load place details in a sidebar */
D. サイドバーに場所の詳細を読み込む
PlaceResult
オブジェクトで返された詳細情報を使用して、別の div を入力します。このサンプルでは、infoPane
を使用します。これは、ID が「panel
」の div の任意の変数名です。ユーザーが新しいマーカーをクリックするたびに、このコードはサイドバーを閉じ、すでにある詳細情報を消去し、新しい詳細を追加して、サイドバーを開きます。
- コメント
TODO: Step 4D
の後に次のコードを追加します。
step4/index.html
/* TODO: Step 4D: Load place details in a sidebar */
// Displays place details in a sidebar
function showPanel(placeResult) {
// If infoPane is already open, close it
if (infoPane.classList.contains("open")) {
infoPane.classList.remove("open");
}
// Clear the previous details
while (infoPane.lastChild) {
infoPane.removeChild(infoPane.lastChild);
}
/* TODO: Step 4E: Display a Place Photo with the Place Details */
// Add place details with text formatting
let name = document.createElement('h1');
name.classList.add('place');
name.textContent = placeResult.name;
infoPane.appendChild(name);
if (placeResult.rating != null) {
let rating = document.createElement('p');
rating.classList.add('details');
rating.textContent = `Rating: ${placeResult.rating} \u272e`;
infoPane.appendChild(rating);
}
let address = document.createElement('p');
address.classList.add('details');
address.textContent = placeResult.formatted_address;
infoPane.appendChild(address);
if (placeResult.website) {
let websitePara = document.createElement('p');
let websiteLink = document.createElement('a');
let websiteUrl = document.createTextNode(placeResult.website);
websiteLink.appendChild(websiteUrl);
websiteLink.title = placeResult.website;
websiteLink.href = placeResult.website;
websitePara.appendChild(websiteLink);
infoPane.appendChild(websitePara);
}
// Open the infoPane
infoPane.classList.add("open");
}
E. Place Details で場所の写真を表示する
getDetails
の結果は、placeId
に関連付けられている最大 10 枚の写真の配列を返します。サイドバーにある場所名の上に最初の写真が表示されます。
- サイドバーの上部に写真を表示する場合は、
name
要素を作成する前にこのコードを配置します。
step4/index.html
/* TODO: Step 4E: Display a Place Photo with the Place Details */
// Add the primary photo, if there is one
if (placeResult.photos != null) {
let firstPhoto = placeResult.photos[0];
let photo = document.createElement('img');
photo.classList.add('hero');
photo.src = firstPhoto.getUrl();
infoPane.appendChild(photo);
}
テスト
- ブラウザでページを保存して再読み込みし、位置情報の利用許可を許可します。
- 任意のマーカーをクリックすると、情報ウィンドウがポップアップ表示され、詳細情報が表示され、サイドバーが左側からスライドして詳細が表示されます。
- 位置情報の利用許可を再読み込みして拒否した場合にも、検索が機能するかどうかをテストします。別のクエリの検索キーワードを編集し、その検索結果を返します。
完全なサンプルコード
ここまでのこのプロジェクトの完全なコードは、GitHub で入手できます。
6. 完了
これで、Places
ライブラリなど、Maps JavaScript API のさまざまな機能を使用しました。
学習した内容
- google.maps.Map クラスを使用して地図を作成する
- ユーザーのブラウザを使用して位置情報を取得し、地図に結果を表示する
- 地図にマーカーを追加し、そのクリック イベントに対応する
- ユーザーがマーカーをクリックしたときに詳細情報を表示する情報ウィンドウの追加
- プレイス ライブラリを読み込み、付近の検索を実行する
- 場所の詳細と場所の写真の取得と表示
詳細
地図をさらに活用するには、Maps JavaScript API のドキュメントと Places Library のドキュメントをご覧ください。両方のガイドには、ガイド、チュートリアル、API リファレンス、その他のコードサンプル、サポート チャネルが記載されています。主な機能としては、マップへのデータのインポート、地図のスタイル設定、ストリートビュー サービスなどがあります。
次に最も構築したい Codelab のタイプはどれですか。
ご希望の Codelab が上記にない場合、こちらからリクエストしてください。