マップタイプ
このドキュメントは、Google Maps JavaScript API を使用して表示できるマップのタイプについて説明します。この API は、MapType オブジェクトを使用してこれらのマップに関する情報を保持します。MapType は、マップタイルの表示や使用、またスクリーン座標から世界座標(マップ上の)への座標系の変換を定義するインターフェースです。各 MapType は、タイルの取得と解放を処理するためのメソッド、およびその視覚動作を定義するプロパティをいくつか含んでいる必要があります。
Maps JavaScript API 内のマップタイプの内部動作は高度なトピックです。多くのデベロッパーは、以下に説明する基本マップタイプを使用するだけで大丈夫です。一方、カスタム マップタイプを使用して独自のマップタイルを定義したり、スタイル化されたマップを使用して既存のマップタイプの表示方法を変更することも可能です。カスタム マップタイプを提供する場合、マップのマップタイプ レジストリを修正する方法を理解する必要があります。
基本マップタイプ
Google Maps JavaScript API では、4 種類のマップを使用できます。一般的なペイント道路地図タイルに加え、Maps JavaScript API ではその他のマップタイプもサポートされます。
以下のマップタイプを、Maps JavaScript API で使用できます。
roadmapは、デフォルトの道路地図ビューを表示します。これは、デフォルトのマップタイプです。satelliteは、Google Earth 航空写真を表示します。hybridは、通常のビューと航空写真ビューの複合ビューを表示します。terrainは、地形情報に基づいた物理地図を表示します。
Map が使用中のマップタイプを変更するには、コンストラクタ内でその Map options オブジェクトを設定するか、マップの setMapTypeId() メソッドを呼び出して、マップタイプの mapTypeId プロパティを設定します。mapTypeID プロパティの既定値は roadmap です。
構築時の mapTypeId の設定:
var myLatlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions = {
zoom: 8,
center: myLatlng,
mapTypeId: 'satellite'
};
var map = new google.maps.Map(document.getElementById('map'),
mapOptions);
mapTypeId の動的な変更:
map.setMapTypeId('terrain');
実際には、マップのマップタイプは直接設定するのではなく、マップの mapTypeId を設定し、ID を使用して MapType を参照します。Maps JavaScript API では、下で説明するマップタイプ レジストリを使用してこれらの参照を管理します。
45° 画像
Google Maps JavaScript API は、特定の場所の 45° 画像をサポートします。この高解像度画像は、各基本方角(北、南、東、西)への展望ビューを提供します。これらの画像は、サポート対象のマップタイプで高いズームレベルで利用可能です。
次の図は、カリフォルニア州サンタクルーズの遊歩道の 45° 展望ビューを示しています。
satellite および hybrid マップタイプは、高ズームレベルの 45° 画像をサポートします(利用可能な場合)。ユーザーがこのような画像が存在する場所にズームインすると、これらのマップタイプでは次の方法で自動的にビューが変更します。
- 衛星またはハイブリッド画像は、45° 展望を提供する画像に置き換わり、現在の場所が中央に配置されます。デフォルトでは、このようなビューは北を向きます。ユーザーがズームアウトすると、デフォルトの衛星またはハイブリッド画像が再び表示されます。
- 回転コントロールを使うと、傾きと回転のオプションを組み合わせて制御できます。
rotateControlがtrueである場合、45° 画像が利用可能な場合に傾きコントロールが表示されます。ユーザーは、傾きコントロールを使用して画像を 45° 傾けることができます。 - 画像が傾くと、フックが表示され、ユーザーは時計回りに 90° ビューを回転できます。
45° 画像を表示しているマップタイプからズームアウトすると、これらの変更がすべて元に戻り、元のマップタイプに復帰します。
45° 画像の有効化と無効化
45° 画像の無効化は、Map オブジェクト上で setTilt(0) を呼び出すことで実行できます。サポート対象マップタイプの 45° 画像を有効化するには、setTilt(45) を呼び出します。
Map の getTilt() は、常にマップ上に表示されている現在の傾きを反映します。マップ上で傾きを設定して後でその傾きを取り消すと(たとえばマップのズームアウトなど)、マップの getTilt() メソッドは 0 を返します。
次の例は、オレゴン州ポートランド中心街の 45° ビューを表示します。
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 36.964, lng: -122.015},
zoom: 18,
mapTypeId: 'satellite'
});
map.setTilt(45);
}
<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'), {
center: {lat: 36.964, lng: -122.015},
zoom: 18,
mapTypeId: 'satellite'
});
map.setTilt(45);
}
45° 画像の回転
45° 画像は、実際には各基本方角(北、南、東、西)の画像の集合で構成されています。マップで 45° 画像が表示されると、画像をいずれかの基本方角に向けることができます。これは、Map オブジェクト上で setHeading() を呼び出して、北からの角度として表される数値を渡すことで行います。
次の例は、航空写真を表示し、ボタンがクリックされると 3 秒ごとにマップを自動的に回転します。
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 45.518, lng: -122.672},
zoom: 18,
mapTypeId: 'satellite',
heading: 90,
tilt: 45
});
}
function rotate90() {
var heading = map.getHeading() || 0;
map.setHeading(heading + 90);
}
function autoRotate() {
// Determine if we're showing aerial imagery.
if (map.getTilt() !== 0) {
window.setInterval(rotate90, 3000);
}
}
<div id="floating-panel"><input type="button" value="Auto Rotate" onclick="autoRotate();"></div> <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;
}
#floating-panel {
position: absolute;
top: 10px;
left: 25%;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
text-align: center;
font-family: 'Roboto','sans-serif';
line-height: 30px;
padding-left: 10px;
}
<!-- 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>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 45.518, lng: -122.672},
zoom: 18,
mapTypeId: 'satellite',
heading: 90,
tilt: 45
});
}
function rotate90() {
var heading = map.getHeading() || 0;
map.setHeading(heading + 90);
}
function autoRotate() {
// Determine if we're showing aerial imagery.
if (map.getTilt() !== 0) {
window.setInterval(rotate90, 3000);
}
}
マップタイプ レジストリの修正
マップの mapTypeId は、MapType を一意の値に関連付ける文字列 ID です。各 Map オブジェクトは、そのマップで使用可能な MapTypeの集合を含む MapTypeRegistry を保持します。このレジストリは、例えばマップの MapType コントロールで使用可能なマップのタイプを選択するために使用されます。
マップタイプ レジストリから直接読み取りは行いません。その代り、カスタム マップタイプを追加してこれらを任意の文字列 ID と関連付けることで、レジストリを修正します。基本マップタイプの修正や変更はできません(ただし、マップの関連 mapTypeControlOptions の外観を変更することで、基本マップタイプをマップから除去できます)。
次のコードは、マップの mapTypeControlOptions でマップが 2 つのマップタイプのみを表示するように設定し、レジストリを修正してこの ID と MapType インターフェースの実際の実装の関連付けを追加します。注: 以前のコードでは、カスタム マップタイプ自体の作成はあえて説明しませんでした。マップタイプの構築については、下記のスタイル化されたマップまたはカスタム マップタイプをご覧ください。
// Modify the control to only display two maptypes, the
// default ROADMAP and the custom 'mymap'.
// Note that because this is simply an association, we
// don't need to modify the MapTypeRegistry beforehand.
var MY_MAPTYPE_ID = 'mymaps';
var mapOptions = {
zoom: 12,
center: brooklyn,
mapTypeControlOptions: {
mapTypeIds: ['roadmap', MY_MAPTYPE_ID]
},
mapTypeId: MY_MAPTYPE_ID
};
// Create our map. This creation will implicitly create a
// map type registry.
map = new google.maps.Map(document.getElementById('map'),
mapOptions);
// Create your custom map type using your own code.
// (See below.)
var myMapType = new MyMapType();
// Set the registry to associate 'mymap' with the
// custom map type we created, and set the map to
// show that map type.
map.mapTypes.set(MY_MAPTYPE_ID, myMapType);
スタイル化されたマップ
StyledMapType は、標準の Google 基本マップの表示方法のカスタマイズを可能にし、道路、公園、市街地などの要素の視覚表示を変更して、デフォルトのマップタイプで使用されているスタイルとは異なるスタイルを反映します。
StyledMapType の詳細については、スタイル化されたマップのガイドをご覧ください。
カスタム マップタイプ
Google Maps JavaScript API は、カスタム マップタイプの表示と管理をサポートしており、独自のマップ画像またはタイル オーバーレイの実装が可能です。
マップタイプの複数の実装例が Maps JavaScript API に含まれています。
- 標準タイルセット。集めると地図作製法に従った完全なマップになる画像で構成されています。これらのタイルセットは、ベース マップタイプとも呼ばれます。これらのマップタイプは、既存のデフォルト マップタイプの
roadmap、satellite、hybrid、terrainと同様に動作します。カスタム マップタイプをマップのmapTypes配列に追加すると、Maps JavaScript API 内の UI でカスタム マップタイプを標準マップタイプのように扱うことができます(MapType コントロールに含めるなどの方法を使用)。 - 画像タイル オーバーレイ。既存のベース マップタイプの上に表示されます。通常、これらのマップタイプは、既存のマップタイプを拡張して追加情報を表示するために使用され、特定の場所やズームレベルに制限されます。これらのタイルは透明化できるため、既存のマップに地物を追加することができます。
- 非画像マップタイプ。マップ情報の表示を、その最も基本的なレベルで操作できます。
これらのオプションはすべて、MapType インターフェースを実装するクラスの作成に依存しています。また、ImageMapType クラスは、画像 MapType の作成を簡素化するためのいくつかの組み込み動作を提供します。
MapType を実装するクラスを説明する前に、Google マップが座標を判別して表示する部分を決定する方法を理解することが重要です。すべてのベースまたはオーバーレイ MapType に、同様なロジックを実装する必要があります。
マップ座標
Google Maps JavaScript API は、複数の座標系を使用します。
- 緯度および経度値。地球上のポイントを一意に参照します(Google では世界測地系 WGS84 標準を使用しています)。
- 世界座標。地図上のポイントを一意に参照します。
- タイル座標。特定のズームレベルでマップ上の特定のタイルを参照します。
世界座標
Google Maps JavaScript API が地球上の場所を地図(画面)上の場所に変換する必要がある場合は、必ず初めに緯度と経度の値を「世界」座標に変換する必要があります。この変換は、地図投影を使用して実施されます。Google マップでは、この目的のためにメルカトル図法を使用しています。また、google.maps.Projection インターフェースを実装して、独自の投影法を定義できます(Maps JavaScript API 内のインターフェースは、「サブクラス」化するクラスではなく、独自に定義するクラスの指定にすぎません)。
ピクセル座標(下記参照)の計算における便宜上、ズームレベル 0 のマップはベース タイルサイズの単一タイルであると想定されています。次に、ズームレベル 0 のピクセル座標に対応する世界座標を定義します。これを行うには、投影法を使用して緯度と経度をこのベースタイル上のピクセル位置に変換します。この世界座標は、マップの投影法の原点から特定の位置までを計測した浮動小数点値です。この値は浮動小数点値であるため、表示されているマップ画像の現在の解像度より高精度にできます。世界座標は、現在のズームレベルから独立しているとも言えます。
Google マップの世界座標は、メルカトル図法の原点(経度 180 度、緯度約 85 度のマップの北西隅)から計測され、東(右)に向かって x 方向が増分し、南(下)に向かって y 方向が増分します。基本メルカトル Google マップは 256 x 256 ピクセルであるため、使用可能な世界座標空間は {0-256}, {0-256} です(下記参照)。
![]()
メルカトル図法では、経度を表す幅は有限ですが、緯度を表す高さは無限です。そこで、メルカトル図法を利用して約 +/- 85 度でベース マップ画像を切り取り、その結果マップ形状を正方形にしています。これにより、タイル選択が簡単になります。北極や南極に非常に近い位置をプロットした場合など、投影法により基本マップの使用可能座標外の世界座標が生成される可能性があります。
ピクセル座標
世界座標は、所定の投影法の絶対位置を反映しますが、これらの座標はピクセル座標に変換して、指定されたズームレベルでの「ピクセル」オフセットを決定する必要があります。これらのピクセル座標は、次の式を使用して計算されます。
pixelCoordinate = worldCoordinate * 2zoomLevel
上記の式で示すように、ズームレベルが 1 つ増えるごとに x と y 方向が 2 倍大きくなります。したがって、ズームレベルが 1 つ上がると、前のレベルの 4 倍の解像度を持つことになります。たとえば、ズームレベル 1 のマップは 256x256 ピクセルのタイル 4 枚で構成されており、512x512 のピクセル空間が生成されます。ズームレベル 19 では、マップ上の各 x および y ピクセルは、0 から 256 * 219 の間の値を使用して参照できます。
世界座標はマップのタイルサイズに基づいているため、ピクセル座標の整数部を使用して現在のズームレベルによる該当場所の正確なピクセルを特定できます。ズームレベル 0 の場合、ピクセル座標は世界座標と等しくなります。
これで、各ズームレベルのマップ上の各位置を正確に示すことができるようになりました。Google Maps JavaScript API は、ズームレベル、マップの中心(LatLng として)、および含まれる DOM 要素のサイズが指定されるとビューポートを構成し、この境界ボックスをピクセル座標に変換します。次に、API は指定されたピクセル境界内に入るすべてのマップタイルを論理的に決定します。これらの各マップタイルは、タイル座標を使用して参照されます。これにより、マップ画像の表示が大幅に簡素化されます。
タイル座標
Google Maps JavaScript API は、最も有用な高いズームレベルですべてのマップ画像をロードすることはできません。その代り、Maps JavaScript API は各ズームレベルの画像を一連のマップタイルに分割します。これらのタイルは、アプリケーションが判別する順序で論理的に配置されます。マップが新しい場所にスクロールしたり、ズームレベルが変わったりすると、Maps JavaScript API はピクセル座標を使用して必要なタイルを判別し、これらの値を取得する一連のタイルに変換します。これらのタイル座標は、指定されたポイントの画像を含むタイルを論理的に判別しやすくするスキームを使用して割り当てられます。
Google マップのタイルは、ピクセルの原点と同じ原点から番号が振られます。Google によるメルカトル図法の実装では、原点タイルは常にマップの北西隅であり、西から東に x 値が増分し、北から南に y 値が増分します。タイルは、この原点からの x,y 座標を使用してインデックスが付けられます。たとえば、ズームレベル 2 で地球が 16 枚のタイルに分割されている場合、各タイルは一意の x,y ペアにより参照できます。

ピクセル座標をタイルサイズで除算した結果の整数部分を使用することで、副産物として現在のズームレベルでのタイル座標を生成することができます。
次の例は、さまざまなズームレベルで、イリノイ州シカゴの LatLng 値、世界座標、ピクセル座標、およびタイル座標を示します。
MapType インターフェース
カスタム マップタイプは MapType インターフェースを実装する必要があります。このインターフェースは、API が現在のビューポートとズームレベルでマップタイルの表示が必要であると判断した場合に、API がマップタイプへのリクエストを開始できるようにする特定のプロパティとメソッドを指定します。これらのリクエストを処理して、ロードするタイルを決定します。
注: 独自のクラスを作成してこのインターフェースを実装できます。または、互換性のある画像がある場合は、このインターフェースを実装済みの ImageMapType クラスを使用できます。
MapType インターフェースを実装しているクラスでは、次のプロパティの定義と指定が必要です。
tileSize(必須)は、(タイプgoogle.maps.Sizeの)タイルのサイズを指定します。サイズは、長方形である必要がありますが、正方形である必要はありません。maxZoom(必須)は、このマップタイプのタイルを表示する最大ズームレベルを指定します。minZoom(オプション)は、このマップタイプのタイルを表示する最小ズームレベルを指定します。デフォルトでは、この値は0であり、最小ズームレベルが存在しないことを示しています。name(オプション)は、このマップタイプの名前を指定します。このプロパティは、このマップタイプを MapType コントロールで選択可能にする場合のみ必要です(下記のMapTypeコントロールの追加をご覧ください)。alt(オプション)は、ホバーテキストとして表示されるこのマップタイプの代替テキストを指定します。このプロパティは、このマップタイプを MapType コントロールで選択可能にする場合のみ必要です(下記のMapTypeコントロールの追加をご覧ください)。
また、MapType インターフェースを実装しているクラスは、次のメソッドを実装する必要があります。
-
getTile()(必須)は、API が指定のビューポートに新しいタイルを表示する必要があると判断した場合に必ず呼び出されます。getTile()メソッドは、次のシグネチャを持つ必要があります。getTile(tileCoord:Point,zoom:number,ownerDocument:Document):NodeAPI は、
MapTypeのtileSize、minZoom、およびmaxZoomの各プロパティと、マップの現在のビューポートとズームレベルに基づいて、getTile()の呼び出しが必要かどうかを判断します。このメソッドのハンドラは、渡された座標、ズームレベル、およびタイル画像を付加する DOM 要素を受け取り、HTML 要素を返す必要があります。 -
releaseTile()(オプション)は、タイルがビューの範囲外になった場合に、マップで該当タイルを削除する必要があると API が判断した場合に必ず呼び出されます。このメソッドは、次のシグネチャを持つ必要があります。releaseTile(tile:Node)通常、マップに加え、マップタイルに付加したすべての要素の除去を処理する必要がありますたとえば、マップタイル オーバーレイにイベントリスナを付加した場合、これらもここで除去する必要があります。
getTile() メソッドは、所定のビューポート内にロードするタイルを決定するためのメイン コントローラとして機能します。
ベース マップタイプ
この方法で作成したマップタイプは、スタンドアロンにするか、オーバーレイとして他のマップタイプと組み合わせることができます。スタンドアロン マップタイプは、ベース マップタイプと呼ばれます。このようなカスタム MapType を、その他の既存のベース マップタイプ(ROADMAP、TERRAIN など)のように API で扱われるようにする必要のある場合があります。これを行うには、カスタム MapType を Map の mapTypes プロパティに追加します。このプロパティは、MapTypeRegistry タイプです。
次のコードは、ベース MapType を作成して、マップのタイル座標を表示し、タイルの外周を描画します。
/*
* This demo demonstrates how to replace default map tiles with custom imagery.
* In this case, the CoordMapType displays gray tiles annotated with the tile
* coordinates.
*
* Try panning and zooming the map to see how the coordinates change.
*/
/**
* @constructor
* @implements {google.maps.MapType}
*/
function CoordMapType(tileSize) {
this.tileSize = tileSize;
}
CoordMapType.prototype.maxZoom = 19;
CoordMapType.prototype.name = 'Tile #s';
CoordMapType.prototype.alt = 'Tile Coordinate Map Type';
CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
var div = ownerDocument.createElement('div');
div.innerHTML = coord;
div.style.width = this.tileSize.width + 'px';
div.style.height = this.tileSize.height + 'px';
div.style.fontSize = '10';
div.style.borderStyle = 'solid';
div.style.borderWidth = '1px';
div.style.borderColor = '#AAAAAA';
div.style.backgroundColor = '#E5E3DF';
return div;
};
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: {lat: 41.850, lng: -87.650},
streetViewControl: false,
mapTypeId: 'coordinate',
mapTypeControlOptions: {
mapTypeIds: ['coordinate', 'roadmap'],
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
}
});
map.addListener('maptypeid_changed', function() {
var showStreetViewControl = map.getMapTypeId() !== 'coordinate';
map.setOptions({
streetViewControl: showStreetViewControl
});
});
// Now attach the coordinate map type to the map's registry.
map.mapTypes.set('coordinate',
new CoordMapType(new google.maps.Size(256, 256)));
}
<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>
/*
* This demo demonstrates how to replace default map tiles with custom imagery.
* In this case, the CoordMapType displays gray tiles annotated with the tile
* coordinates.
*
* Try panning and zooming the map to see how the coordinates change.
*/
/**
* @constructor
* @implements {google.maps.MapType}
*/
function CoordMapType(tileSize) {
this.tileSize = tileSize;
}
CoordMapType.prototype.maxZoom = 19;
CoordMapType.prototype.name = 'Tile #s';
CoordMapType.prototype.alt = 'Tile Coordinate Map Type';
CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
var div = ownerDocument.createElement('div');
div.innerHTML = coord;
div.style.width = this.tileSize.width + 'px';
div.style.height = this.tileSize.height + 'px';
div.style.fontSize = '10';
div.style.borderStyle = 'solid';
div.style.borderWidth = '1px';
div.style.borderColor = '#AAAAAA';
div.style.backgroundColor = '#E5E3DF';
return div;
};
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: {lat: 41.850, lng: -87.650},
streetViewControl: false,
mapTypeId: 'coordinate',
mapTypeControlOptions: {
mapTypeIds: ['coordinate', 'roadmap'],
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
}
});
map.addListener('maptypeid_changed', function() {
var showStreetViewControl = map.getMapTypeId() !== 'coordinate';
map.setOptions({
streetViewControl: showStreetViewControl
});
});
// Now attach the coordinate map type to the map's registry.
map.mapTypes.set('coordinate',
new CoordMapType(new google.maps.Size(256, 256)));
}
オーバーレイ マップタイプ
一部のマップタイプは、既存のマップタイプの上で動作するように意図されています。このようなマップタイプは、透明なレイヤーを持つことができ、有名スポットを示したり、ユーザーに追加データを示したりします
このような場合、マップタイプを別のエンティティとして扱うのは好都合ではありません。代わりに、Map の overlayMapTypes プロパティを使用して、このマップタイプを既存の MapType に直接追加できます。このプロパティには、MapType の MVCArray が含まれます。すべてのマップタイプ(ベースおよびオーバーレイ)は、mapPane レイヤー内でレンダリングされます。オーバーレイ マップタイプは、関連付けられている任意のベース マップタイプの上に表示され、その順序は Map.overlayMapTypes 配列での記述順序です。
次の例は前の例と同じですが、タイル オーバーレイ MapType を ROADMAP マップタイプの上に作成した点が異なります。
/*
* This demo illustrates the coordinate system used to display map tiles in the
* API.
*
* Tiles in Google Maps are numbered from the same origin as that for
* pixels. For Google's implementation of the Mercator projection, the origin
* tile is always at the northwest corner of the map, with x values increasing
* from west to east and y values increasing from north to south.
*
* Try panning and zooming the map to see how the coordinates change.
*/
/** @constructor */
function CoordMapType(tileSize) {
this.tileSize = tileSize;
}
CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
var div = ownerDocument.createElement('div');
div.innerHTML = coord;
div.style.width = this.tileSize.width + 'px';
div.style.height = this.tileSize.height + 'px';
div.style.fontSize = '10';
div.style.borderStyle = 'solid';
div.style.borderWidth = '1px';
div.style.borderColor = '#AAAAAA';
return div;
};
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: {lat: 41.850, lng: -87.650}
});
// Insert this overlay map type as the first overlay map type at
// position 0. Note that all overlay map types appear on top of
// their parent base map.
map.overlayMapTypes.insertAt(
0, new CoordMapType(new google.maps.Size(256, 256)));
}
<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>
/*
* This demo illustrates the coordinate system used to display map tiles in the
* API.
*
* Tiles in Google Maps are numbered from the same origin as that for
* pixels. For Google's implementation of the Mercator projection, the origin
* tile is always at the northwest corner of the map, with x values increasing
* from west to east and y values increasing from north to south.
*
* Try panning and zooming the map to see how the coordinates change.
*/
/** @constructor */
function CoordMapType(tileSize) {
this.tileSize = tileSize;
}
CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
var div = ownerDocument.createElement('div');
div.innerHTML = coord;
div.style.width = this.tileSize.width + 'px';
div.style.height = this.tileSize.height + 'px';
div.style.fontSize = '10';
div.style.borderStyle = 'solid';
div.style.borderWidth = '1px';
div.style.borderColor = '#AAAAAA';
return div;
};
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: {lat: 41.850, lng: -87.650}
});
// Insert this overlay map type as the first overlay map type at
// position 0. Note that all overlay map types appear on top of
// their parent base map.
map.overlayMapTypes.insertAt(
0, new CoordMapType(new google.maps.Size(256, 256)));
}
画像マップタイプ
MapType をベース マップタイプとして動作するように実装することは、多くの時間と労力を要します。この API は、最も一般的なマップタイプに対して、つまり単一の画像ファイルからなる複数のタイルで構成されるマップタイプ用に、MapType インターフェースを実装している特別なクラスを提供します。
この ImageMapType クラスは、次の必須プロパティを定義している ImageMapTypeOptions オブジェクト仕様を使用して作成されています。
tileSize(必須)は、(タイプgoogle.maps.Sizeの)タイルのサイズを指定します。サイズは、長方形である必要がありますが、正方形である必要はありません。getTileUrl(必須)は、通常インライン関数リテラルとして提供され、指定された世界座標とズームレベルに基づいて適切な画像タイルの選択を処理する関数を指定します。
次のコードは、Google のムーンタイルを使用して基本 ImageMapType を実装しています。この例は、正規化関数を利用して、タイルがマップの x 軸に沿って繰り返され、y 軸に沿っては繰り返されないようにしています。
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 0, lng: 0},
zoom: 1,
streetViewControl: false,
mapTypeControlOptions: {
mapTypeIds: ['moon']
}
});
var moonMapType = new google.maps.ImageMapType({
getTileUrl: function(coord, zoom) {
var normalizedCoord = getNormalizedCoord(coord, zoom);
if (!normalizedCoord) {
return null;
}
var bound = Math.pow(2, zoom);
return '//mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw' +
'/' + zoom + '/' + normalizedCoord.x + '/' +
(bound - normalizedCoord.y - 1) + '.jpg';
},
tileSize: new google.maps.Size(256, 256),
maxZoom: 9,
minZoom: 0,
radius: 1738000,
name: 'Moon'
});
map.mapTypes.set('moon', moonMapType);
map.setMapTypeId('moon');
}
// Normalizes the coords that tiles repeat across the x axis (horizontally)
// like the standard Google map tiles.
function getNormalizedCoord(coord, zoom) {
var y = coord.y;
var x = coord.x;
// tile range in one direction range is dependent on zoom level
// 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
var tileRange = 1 << zoom;
// don't repeat across y-axis (vertically)
if (y < 0 || y >= tileRange) {
return null;
}
// repeat across x-axis
if (x < 0 || x >= tileRange) {
x = (x % tileRange + tileRange) % tileRange;
}
return {x: x, y: y};
}
<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'), {
center: {lat: 0, lng: 0},
zoom: 1,
streetViewControl: false,
mapTypeControlOptions: {
mapTypeIds: ['moon']
}
});
var moonMapType = new google.maps.ImageMapType({
getTileUrl: function(coord, zoom) {
var normalizedCoord = getNormalizedCoord(coord, zoom);
if (!normalizedCoord) {
return null;
}
var bound = Math.pow(2, zoom);
return '//mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw' +
'/' + zoom + '/' + normalizedCoord.x + '/' +
(bound - normalizedCoord.y - 1) + '.jpg';
},
tileSize: new google.maps.Size(256, 256),
maxZoom: 9,
minZoom: 0,
radius: 1738000,
name: 'Moon'
});
map.mapTypes.set('moon', moonMapType);
map.setMapTypeId('moon');
}
// Normalizes the coords that tiles repeat across the x axis (horizontally)
// like the standard Google map tiles.
function getNormalizedCoord(coord, zoom) {
var y = coord.y;
var x = coord.x;
// tile range in one direction range is dependent on zoom level
// 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
var tileRange = 1 << zoom;
// don't repeat across y-axis (vertically)
if (y < 0 || y >= tileRange) {
return null;
}
// repeat across x-axis
if (x < 0 || x >= tileRange) {
x = (x % tileRange + tileRange) % tileRange;
}
return {x: x, y: y};
}
投影
地球は、3 次元の(ほぼ)球体ですが、地図は 2 次元の平面です。Google Maps JavaScript API で表示されているマップは、その他の平面地球地図と同様に、球体を平面に投影したものです。簡単に言うと、投影は緯度/経度値の投影地図上の座標へのマッピングとして定義できます。
Maps JavaScript API での投影には、Projection インターフェースを実装する必要があります。Projection 実装は、ある座標システムから別の座標システムへのマッピングに加え、双方向のマッピングも提供する必要があります。つまり、地球座標(LatLng)から Projection の世界座標系への変換方法およびその逆変換を定義する必要があります。Google マップは、メルカトル図法を使用して地理データからマップを作成し、マップ上のイベントを地理座標に変換します。この投影は、Map(または任意の標準ベース MapType)上で getProjection() を呼び出すことで取得できます。通常は、この標準の Projection で充分ですが、独自のカスタム投影を定義して使用することも可能です。
投影を実装する
カスタム投影を実装する場合、いくつかの定義が必要になります。
- 緯度と経度の座標をデカルト平面にマッピングするかその逆を行う式。(
Projectionインターフェースは直線座標への変換のみをサポートします)。 - ベース タイルサイズ。タイルはすべて長方形にする必要があります。
- ズームレベル 0 に設定したベース タイルを使用したマップの「世界サイズ」。ズームが 0 の場合に 1 つのタイルで構成されるマップでは、世界サイズとベース タイルサイズは同一になります。
投影における座標変換
すべての投影は、これらの 2 つの座標系間の変換を行う 2 つのメソッドを提供し、地理的座標と世界座標間の変換を可能にしています。
Projection.fromLatLngToPoint()メソッドは、LatLng値を世界座標に変換します。このメソッドは、マップ上のオーバーレイの位置を決めるために(またマップ自体の位置を決めるために)使用されます。Projection.fromPointToLatLng()メソッドは、世界座標をLatLng値に変換します。このメソッドは、マップ上で発生するクリックなどのイベントを地理的座標に変換するために使います。
Google マップでは、投影が直線的であると想定しています。
一般的に、投影は 2 つの場合に使用されます。それは、世界地図を作成する場合と特定の地域の地図を作成する場合です。前者の場合は、使用している投影も直線的であり、すべての経度で垂直に投影されている必要があります。一部の投影(特に円錐投影)では、一部の地域で垂直に投影されますが(真上が北になる)、例えばある基準経度から相対的に遠い位置の地図では、真上が北を指さなくなります。このような投影法は限られた地域では使用できますが、投影は必然的に不正確となり、基準経度から離れるほど変換の誤差が徐々に顕著になります。
投影におけるマップタイルの選択
投影は、場所やオーバーレイの位置の決定に便利なだけではなく、マップタイル自体の位置決めにも有用です。Google Maps JavaScript API は、MapType インターフェースを使用してベースマップをレンダリングします。このインターフェースでは、マップの投影を識別する projection プロパティと、タイル座標値に基づいてマップタイルを取得するための getTile() メソッドを宣言する必要があります。タイル座標は、基本タイルサイズ(長方形である必要がある)とズームレベル 0 での地図世界のピクセルサイズであるマップの「世界サイズ」の両方に基づきます(ズーム 0 で 1 つのタイルで構成されるマップでは、タイルサイズと世界サイズは同一です)。
ベース タイルサイズは、MapType の tileSize プロパティで定義します。世界サイズは、投影の fromLatLngToPoint() と fromPointToLatLng() メソッドで暗黙的に定義します。
画像の選択はこれらの渡される値に依存するため、これらの渡される値を使って map_zoom_tileX_tileY.png などの名前を画像に付けると、プログラムで選択するときに便利です。
次の例は、ガル - ピーターズ図法を使用して ImageMapType を定義しています。
// This example defines an image map type using the Gall-Peters
// projection.
// https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection
function initMap() {
// Create a map. Use the Gall-Peters map type.
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 0,
center: {lat: 0, lng: 0},
mapTypeControl: false
});
initGallPeters();
map.mapTypes.set('gallPeters', gallPetersMapType);
map.setMapTypeId('gallPeters');
// Show the lat and lng under the mouse cursor.
var coordsDiv = document.getElementById('coords');
map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv);
map.addListener('mousemove', function(event) {
coordsDiv.textContent =
'lat: ' + Math.round(event.latLng.lat()) + ', ' +
'lng: ' + Math.round(event.latLng.lng());
});
// Add some markers to the map.
map.data.setStyle(function(feature) {
return {
title: feature.getProperty('name'),
optimized: false
};
});
map.data.addGeoJson(cities);
}
var gallPetersMapType;
function initGallPeters() {
var GALL_PETERS_RANGE_X = 800;
var GALL_PETERS_RANGE_Y = 512;
// Fetch Gall-Peters tiles stored locally on our server.
gallPetersMapType = new google.maps.ImageMapType({
getTileUrl: function(coord, zoom) {
var scale = 1 << zoom;
// Wrap tiles horizontally.
var x = ((coord.x % scale) + scale) % scale;
// Don't wrap tiles vertically.
var y = coord.y;
if (y < 0 || y >= scale) return null;
return 'https://developers.google.com/maps/documentation/' +
'javascript/examples/full/images/gall-peters_' + zoom +
'_' + x + '_' + y + '.png';
},
tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y),
isPng: true,
minZoom: 0,
maxZoom: 1,
name: 'Gall-Peters'
});
// Describe the Gall-Peters projection used by these tiles.
gallPetersMapType.projection = {
fromLatLngToPoint: function(latLng) {
var latRadians = latLng.lat() * Math.PI / 180;
return new google.maps.Point(
GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)));
},
fromPointToLatLng: function(point, noWrap) {
var x = point.x / GALL_PETERS_RANGE_X;
var y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y));
return new google.maps.LatLng(
Math.asin(1 - 2 * y) * 180 / Math.PI,
-180 + 360 * x,
noWrap);
}
};
}
// GeoJSON, describing the locations and names of some cities.
var cities = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {type: 'Point', coordinates: [-87.650, 41.850]},
properties: {name: 'Chicago'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [-149.900, 61.218]},
properties: {name: 'Anchorage'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [-99.127, 19.427]},
properties: {name: 'Mexico City'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [-0.126, 51.500]},
properties: {name: 'London'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [28.045, -26.201]},
properties: {name: 'Johannesburg'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [15.322, -4.325]},
properties: {name: 'Kinshasa'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [151.207, -33.867]},
properties: {name: 'Sydney'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [0, 0]},
properties: {name: '0°N 0°E'}
}]
};
<div id="map"></div> <div id="coords"></div>
#coords {
background-color: black;
color: white;
padding: 5px;
}
<!-- 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>
// This example defines an image map type using the Gall-Peters
// projection.
// https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection
function initMap() {
// Create a map. Use the Gall-Peters map type.
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 0,
center: {lat: 0, lng: 0},
mapTypeControl: false
});
initGallPeters();
map.mapTypes.set('gallPeters', gallPetersMapType);
map.setMapTypeId('gallPeters');
// Show the lat and lng under the mouse cursor.
var coordsDiv = document.getElementById('coords');
map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv);
map.addListener('mousemove', function(event) {
coordsDiv.textContent =
'lat: ' + Math.round(event.latLng.lat()) + ', ' +
'lng: ' + Math.round(event.latLng.lng());
});
// Add some markers to the map.
map.data.setStyle(function(feature) {
return {
title: feature.getProperty('name'),
optimized: false
};
});
map.data.addGeoJson(cities);
}
var gallPetersMapType;
function initGallPeters() {
var GALL_PETERS_RANGE_X = 800;
var GALL_PETERS_RANGE_Y = 512;
// Fetch Gall-Peters tiles stored locally on our server.
gallPetersMapType = new google.maps.ImageMapType({
getTileUrl: function(coord, zoom) {
var scale = 1 << zoom;
// Wrap tiles horizontally.
var x = ((coord.x % scale) + scale) % scale;
// Don't wrap tiles vertically.
var y = coord.y;
if (y < 0 || y >= scale) return null;
return 'https://developers.google.com/maps/documentation/' +
'javascript/examples/full/images/gall-peters_' + zoom +
'_' + x + '_' + y + '.png';
},
tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y),
isPng: true,
minZoom: 0,
maxZoom: 1,
name: 'Gall-Peters'
});
// Describe the Gall-Peters projection used by these tiles.
gallPetersMapType.projection = {
fromLatLngToPoint: function(latLng) {
var latRadians = latLng.lat() * Math.PI / 180;
return new google.maps.Point(
GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)));
},
fromPointToLatLng: function(point, noWrap) {
var x = point.x / GALL_PETERS_RANGE_X;
var y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y));
return new google.maps.LatLng(
Math.asin(1 - 2 * y) * 180 / Math.PI,
-180 + 360 * x,
noWrap);
}
};
}
// GeoJSON, describing the locations and names of some cities.
var cities = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {type: 'Point', coordinates: [-87.650, 41.850]},
properties: {name: 'Chicago'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [-149.900, 61.218]},
properties: {name: 'Anchorage'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [-99.127, 19.427]},
properties: {name: 'Mexico City'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [-0.126, 51.500]},
properties: {name: 'London'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [28.045, -26.201]},
properties: {name: 'Johannesburg'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [15.322, -4.325]},
properties: {name: 'Kinshasa'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [151.207, -33.867]},
properties: {name: 'Sydney'}
}, {
type: 'Feature',
geometry: {type: 'Point', coordinates: [0, 0]},
properties: {name: '0°N 0°E'}
}]
};
