このページでは、プログラムでリッスンして処理できるユーザー インターフェース イベントとエラー イベントについて説明します。
ユーザー インターフェース イベント
ブラウザ内の JavaScript はイベント駆動型です。そのため、JavaScript はイベントを生成することでインタラクションに応答し、プログラムが対象のイベントをリスニングするのことを想定しています。イベントには、以下の 2 つのタイプがあります。
- ユーザー イベント(マウスクリック イベントなど)は、DOM から Google Maps JavaScript API に伝えられます。これらのイベントは、標準の DOM イベントとは異なります。
- MVC の状態変化の通知は、Maps JavaScript API オブジェクトの変化を反映しており、これには
property_changed規則に基づいた名前が付けられています。
各 Maps JavaScript API オブジェクトは、多くの名前付きイベントをエクスポートします。特定のイベントに関連するプログラムは、それらのイベントに対して JavaScript のイベントリスナを登録します。そして、オブジェクトで addListener() を呼び出してイベント ハンドラを登録することで、これらのイベントが受信されたときに、コードが実行されるようにします。
以下のサンプルは、マップとインタラクションを行うと、google.maps.Map によって、どのイベントがトリガーされるのかを示します。
全イベントの一覧は Google Maps JavaScript API リファレンスでご確認ください。イベントの一覧は、イベントが属しているオブジェクトごとに収録されています。
UI イベント
Google Maps JavaScript API に含まれるオブジェクトの中には、マウスやキーボード イベントのようなユーザー イベントに応答するよう設計されているものがあります。たとえば、google.maps.Marker オブジェクトの場合にリスニングできるユーザー イベントの一部を次に示します。
'click''dblclick''mouseup''mousedown''mouseover''mouseout'
全リストは、Marker クラスの説明をご覧ください。これらのイベントは標準の DOM イベントに似ていますが、実際は Maps JavaScript API の一部です。ブラウザごとに実装している DOM イベントモデルは違うため、さまざまなクロスブラウザ特性に対応しなくても、DOM イベントをリスニングしたり、応答したりできる仕組みが Maps JavaScript API には備わっています。また、通常、これらのイベントは、UI 状態(マウスの位置など)を通知するイベントの中で引数を渡します。
MVC の状態変化
通常、MVC オブジェクトは状態を保持します。オブジェクトのプロパティが変化するたびに、Google Maps JavaScript API はプロパティが変化したことを通知するイベントを発行します。たとえば API は、地図のズーム レベルが変化すると、地図の zoom_changed イベントを発行します。これらの状態変化をインターセプトするには、オブジェクトで addListener() を呼び出してイベント ハンドラを登録します。
ユーザー イベントと MVC 状態変化イベントは似ていますが、コード内では別々に扱うのが一般的です。たとえば、MVC イベント内では引数を渡しません。MVC の状態変化に応じて変化したプロパティを確認するには、そのオブジェクトの適切な getProperty メソッドを呼び出します。
イベント処理
イベント通知を登録するには、addListener() イベント ハンドラを使用します。このメソッドは引数として、リスニングするイベントと、指定のイベントが発生した際に呼び出す関数を取ります。
例: マップとマーカー イベント
以下のコードには、ユーザー イベントと状態変化イベントが両方含まれています。クリック時にマップをズームするマーカーに対して、イベントハンドラをアタッチします。さらに center プロパティの変化を検出するイベントハンドラもマップに追加し、center_changed イベントを受信すると、その 3 秒後にマップをマーカーの位置へ戻すようにします。
function initMap() {
var myLatlng = {lat: -25.363, lng: 131.044};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: myLatlng
});
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Click to zoom'
});
map.addListener('center_changed', function() {
// 3 seconds after the center of the map has changed, pan back to the
// marker.
window.setTimeout(function() {
map.panTo(marker.getPosition());
}, 3000);
});
marker.addListener('click', function() {
map.setZoom(8);
map.setCenter(marker.getPosition());
});
}
<div id="map"></div>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<!-- Replace the value of the key parameter with your own API key. --> <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap"> </script>
function initMap() {
var myLatlng = {lat: -25.363, lng: 131.044};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: myLatlng
});
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Click to zoom'
});
map.addListener('center_changed', function() {
// 3 seconds after the center of the map has changed, pan back to the
// marker.
window.setTimeout(function() {
map.panTo(marker.getPosition());
}, 3000);
});
marker.addListener('click', function() {
map.setZoom(8);
map.setCenter(marker.getPosition());
});
}
ヒント: ビューポートの変更を検出したい場合は、指定の bounds_changed イベントを使用してください。その構成要素である zoom_changed や center_changed イベントは使用しないでください。Maps JavaScript API は後者の 2 つのイベントを別々に発行するため、ビューポートが正しく変更されるまで、getBounds() は有用な結果を報告しない可能性があります。そのようなイベントの後で getBounds() を使用したい場合は、代わりに bounds_changed イベントをリスニングしてください。
例: 図形の編集とドラッグ イベント
図形が編集されたり、ドラッグされたりすると、アクションの完了時にイベントが発行されます。イベントの一覧とコードスニペットについては、図形の説明をご覧ください。
UI イベントの引数にアクセスする
Google Maps JavaScript API の UI イベントは通常、イベント発生時の UI の状態を通知するイベントの引数を渡します。イベントリスナはこの引数にアクセスできます。たとえば、UI 'click' イベントは通常、マップ上でクリックされた位置を示す latLng プロパティを含む MouseEvent を渡します。この動作は UI イベントに固有で、MVC の状態変化では引数をイベントで渡さないことに注意してください。
イベントリスナ内にあるイベントの引数にアクセスする方法は、オブジェクトのプロパティにアクセスする方法と同じです。以下の例は、マップにイベントリスナを追加して、ユーザーがマップをクリックすると、その位置にマーカーを作成します。
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {lat: -25.363882, lng: 131.044922 }
});
map.addListener('click', function(e) {
placeMarkerAndPanTo(e.latLng, map);
});
}
function placeMarkerAndPanTo(latLng, map) {
var marker = new google.maps.Marker({
position: latLng,
map: map
});
map.panTo(latLng);
}
<div id="map"></div>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<!-- Replace the value of the key parameter with your own API key. --> <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap"> </script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {lat: -25.363882, lng: 131.044922 }
});
map.addListener('click', function(e) {
placeMarkerAndPanTo(e.latLng, map);
});
}
function placeMarkerAndPanTo(latLng, map) {
var marker = new google.maps.Marker({
position: latLng,
map: map
});
map.panTo(latLng);
}
イベント リスナでクロージャを使う
イベント リスナを実行するとき、通常は、オブジェクトにプライベート データと永続データの両方をアタッチするのが有効です。JavaScript は「プライベート」のインスタンス データはサポートしていませんが、内部関数から外部変数へのアクセスを可能にするクロージャはサポートしています。クロージャは、イベントが発生したオブジェクトには通常アタッチされていない変数に、イベントリスナ内でアクセスするのに便利です。
以下の例では、イベントリスナ内で関数クロージャを使用して、マーカーのセットに秘密のメッセージを割り当てています。各マーカーをクリックすると、そのマーカー自体には含まれていない秘密のメッセージの一部が表示されます。
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {lat: -25.363882, lng: 131.044922 }
});
var bounds = {
north: -25.363882,
south: -31.203405,
east: 131.044922,
west: 125.244141
};
// Display the area between the location southWest and northEast.
map.fitBounds(bounds);
// Add 5 markers to map at random locations.
// For each of these markers, give them a title with their index, and when
// they are clicked they should open an infowindow with text from a secret
// message.
var secretMessages = ['This', 'is', 'the', 'secret', 'message'];
var lngSpan = bounds.east - bounds.west;
var latSpan = bounds.north - bounds.south;
for (var i = 0; i < secretMessages.length; ++i) {
var marker = new google.maps.Marker({
position: {
lat: bounds.south + latSpan * Math.random(),
lng: bounds.west + lngSpan * Math.random()
},
map: map
});
attachSecretMessage(marker, secretMessages[i]);
}
}
// Attaches an info window to a marker with the provided message. When the
// marker is clicked, the info window will open with the secret message.
function attachSecretMessage(marker, secretMessage) {
var infowindow = new google.maps.InfoWindow({
content: secretMessage
});
marker.addListener('click', function() {
infowindow.open(marker.get('map'), marker);
});
}
<div id="map"></div>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<!-- Replace the value of the key parameter with your own API key. --> <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap"> </script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {lat: -25.363882, lng: 131.044922 }
});
var bounds = {
north: -25.363882,
south: -31.203405,
east: 131.044922,
west: 125.244141
};
// Display the area between the location southWest and northEast.
map.fitBounds(bounds);
// Add 5 markers to map at random locations.
// For each of these markers, give them a title with their index, and when
// they are clicked they should open an infowindow with text from a secret
// message.
var secretMessages = ['This', 'is', 'the', 'secret', 'message'];
var lngSpan = bounds.east - bounds.west;
var latSpan = bounds.north - bounds.south;
for (var i = 0; i < secretMessages.length; ++i) {
var marker = new google.maps.Marker({
position: {
lat: bounds.south + latSpan * Math.random(),
lng: bounds.west + lngSpan * Math.random()
},
map: map
});
attachSecretMessage(marker, secretMessages[i]);
}
}
// Attaches an info window to a marker with the provided message. When the
// marker is clicked, the info window will open with the secret message.
function attachSecretMessage(marker, secretMessage) {
var infowindow = new google.maps.InfoWindow({
content: secretMessage
});
marker.addListener('click', function() {
infowindow.open(marker.get('map'), marker);
});
}
イベント ハンドラ内でのプロパティの取得と設定
Google Maps JavaScript API イベント システムの MVC 状態変化イベントは、どれもイベントがトリガーされた際に引数を渡しません(ユーザー イベントは検査可能な引数を渡します)。MVC 状態変化のプロパティを検査する必要がある場合は、そのオブジェクトの適切な getProperty() メソッドを明示的に呼び出す必要があります。この検査では常に、MVC オブジェクトの最新状態が取得されますが、これは、イベントが最初に発生したときの状態と一致するとは限りません。
注: ある特定のプロパティの状態変化に応答するイベント ハンドラ内で、プロパティを明示的に設定すると、予想外の動作や期待とは異なる動作が生じることがあります。たとえば、そのようなプロパティを設定すると新しいイベントが発生して、そのイベント ハンドラ内で必ずプロパティを設定していると無限ループに陥ることがあります。
以下の例では、ズームイベントに応答するイベント ハンドラを設定し、そのレベルを情報ウィンドウに表示します。
function initMap() {
var originalMapCenter = new google.maps.LatLng(-25.363882, 131.044922);
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: originalMapCenter
});
var infowindow = new google.maps.InfoWindow({
content: 'Change the zoom level',
position: originalMapCenter
});
infowindow.open(map);
map.addListener('zoom_changed', function() {
infowindow.setContent('Zoom: ' + map.getZoom());
});
}
<div id="map"></div>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<!-- Replace the value of the key parameter with your own API key. --> <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap"> </script>
function initMap() {
var originalMapCenter = new google.maps.LatLng(-25.363882, 131.044922);
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: originalMapCenter
});
var infowindow = new google.maps.InfoWindow({
content: 'Change the zoom level',
position: originalMapCenter
});
infowindow.open(map);
map.addListener('zoom_changed', function() {
infowindow.setContent('Zoom: ' + map.getZoom());
});
}
DOM イベントをリスニングする
Google Maps JavaScript API イベントモデルは、独自のカスタム イベントを作成および管理します。一方、ブラウザ内の DOM(ドキュメント オブジェクト モデル)も、使用している特定のブラウザ イベント モデルに応じて独自のイベントを作成して送信します。これらのイベントを取得し、応答したい場合は、Maps JavaScript API で提供されている addDomListener() 静的メソッドを使用して、DOM イベントのリスニングとバインドを行います。
この便利なメソッドには、以下のシグネチャがあります。
addDomListener(instance:Object, eventName:string, handler:Function)
instance は、ブラウザがサポートする任意の DOM 要素で、次のようなものが含まれます。
windowやdocument.body.myformなどの DOM の階層構造のメンバーdocument.getElementById("foo")などの名前の付いた要素
addDomListener() が指定されたイベントをブラウザに渡すと、ブラウザはそのイベントを、ブラウザの DOM イベント モデルに従って処理します。なお、最新ブラウザの多くは、最低でも DOM レベル 2 をサポートしています。(DOM レベルのイベントの詳細は、Mozilla DOM レベルを参照してください)。
このドキュメントでは、DOM イベントの 1 つである window.onload イベントを <body> タグの中で処理しています。このイベントを以下のように使うと、HTML ページが完全に読み込まれたときに、最初の JavaScript コードがトリガーされます。
<script>
function initialize() {
// Map initialization
}
</script>
<body onload="initialize()">
<div id="map"></div>
</body>
ここでは、このイベントは <body> 要素にアタッチされています。ただし、これは実際には window イベントで、window 要素の下にある DOM 階層の作成とレンダリングが完了したことを示します。
<body> タグ内に onload イベントを含めるとわかりやすくなりますが、そうするとコンテンツと動作が混ざることになります。一般的には、動作コード(JavaScript)からコンテンツ コード(HTML)を分離し、プレゼンテーションのコード(CSS)も別に用意することをお勧めします。そのためには、以下のように Maps JavaScript API コード内にあるインラインの onload イベント ハンドラを DOM リスナで置き換えます。
<script>
function initialize() {
// Map initialization
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<body>
<div id="map"></div>
</body>
上記のコードは Maps JavaScript API のコードですが、addDomListener() メソッドはブラウザの window オブジェクトとバインドされています。そのため API は、API の通常のドメイン外でオブジェクトと情報をやり取りできます。
イベントリスナを削除する
指定したイベントリスナを削除するには、変数を割り当てる必要があります。そして removeListener() を呼び出し、そのリスナに割り当てられた変数名を渡します。
var listener1 = marker.addListener('click', aFunction);
google.maps.event.removeListener(listener1);
特定のインスタンスにあるリスナをすべて削除するには、clearInstanceListeners() を呼び出して、インスタンス名を渡します。
var listener1 = marker.addListener('click', aFunction);
var listener2 = marker.addListener('mouseover', bFunction);
// Remove listener1 and listener2 from marker instance.
google.maps.event.clearInstanceListeners(marker);
特定のインスタンスに対する、指定したイベントタイプのリスナをすべて削除するには、clearListeners() を呼び出して、インスタンス名とイベント名を渡します。
marker.addListener('click', aFunction);
marker.addListener('click', bFunction);
marker.addListener('click', cFunction);
// Remove all click listeners from marker instance.
google.maps.event.clearListeners(marker, 'click');
詳しくは、google.maps.event 名前空間のドキュメントをご覧ください。
認証エラーをリッスンする
プログラムで認証エラーを検出する場合(ビーコンを自動的に送信するなどして)、コールバック関数を用意することができます。グローバル関数 function gm_authFailure() { /* Code */ }; が定義されている場合、認証エラーが発生すると、この関数が呼び出されます。
