Maps JavaScript API では、ラスターとベクターという 2 種類の地図を実装できます。ラスターマップは、Google Maps Platform のサーバーサイドで生成され、ウェブアプリに提供されるピクセルベースのラスター画像タイルのグリッドとして地図を読み込みます。ベクターマップは、ベクターベースのタイルで構成されています。これらのタイルは、ブラウザがユーザーのデバイス上の GPU にアクセスして 2D グラフィックと 3D グラフィックをレンダリングできるようにするウェブ技術である WebGL を使用して、読み込み時にクライアントサイドで描画されます。
ベクターマップは、ユーザーが使い慣れている Google マップと同じですが、デフォルトのラスタータイル マップと比べて多くの利点があります。特に、鮮明なベクターベース画像と、ズームアップすると建物の 3D 表示が追加される機能が有用です。ベクター地図は、次の機能をサポートしています。
- 傾斜と方角のプログラマティック制御
- カメラの操作の強化
- 小数ズームによるスムーズなズーム
div
要素と JavaScript を使用して読み込まれる地図のデフォルトのレンダリング タイプはgoogle.maps.RenderingType.RASTER
です。gmp-map
要素を使用して読み込まれる地図のデフォルトのレンダリング タイプはgoogle.maps.RenderingType.VECTOR
で、傾斜と向きのコントロールが有効になっています。
傾斜と回転
ベクターマップに傾斜と回転(方角)を設定するには、地図の初期化時に heading
プロパティと tilt
プロパティを指定し、地図上で setTilt
メソッドと setHeading
メソッドを呼び出します。次のサンプルでは、プログラマティックに傾斜と方角の角度を 20 度ずつ増加させるボタンを地図に追加します。
TypeScript
function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { center: { lat: 37.7893719, lng: -122.3942, }, zoom: 16, heading: 320, tilt: 47.5, mapId: "90f87356969d889c", } ); const buttons: [string, string, number, google.maps.ControlPosition][] = [ ["Rotate Left", "rotate", 20, google.maps.ControlPosition.LEFT_CENTER], ["Rotate Right", "rotate", -20, google.maps.ControlPosition.RIGHT_CENTER], ["Tilt Down", "tilt", 20, google.maps.ControlPosition.TOP_CENTER], ["Tilt Up", "tilt", -20, google.maps.ControlPosition.BOTTOM_CENTER], ]; buttons.forEach(([text, mode, amount, position]) => { const controlDiv = document.createElement("div"); const controlUI = document.createElement("button"); controlUI.classList.add("ui-button"); controlUI.innerText = `${text}`; controlUI.addEventListener("click", () => { adjustMap(mode, amount); }); controlDiv.appendChild(controlUI); map.controls[position].push(controlDiv); }); const adjustMap = function (mode: string, amount: number) { switch (mode) { case "tilt": map.setTilt(map.getTilt()! + amount); break; case "rotate": map.setHeading(map.getHeading()! + amount); break; default: break; } }; } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
function initMap() { const map = new google.maps.Map(document.getElementById("map"), { center: { lat: 37.7893719, lng: -122.3942, }, zoom: 16, heading: 320, tilt: 47.5, mapId: "90f87356969d889c", }); const buttons = [ ["Rotate Left", "rotate", 20, google.maps.ControlPosition.LEFT_CENTER], ["Rotate Right", "rotate", -20, google.maps.ControlPosition.RIGHT_CENTER], ["Tilt Down", "tilt", 20, google.maps.ControlPosition.TOP_CENTER], ["Tilt Up", "tilt", -20, google.maps.ControlPosition.BOTTOM_CENTER], ]; buttons.forEach(([text, mode, amount, position]) => { const controlDiv = document.createElement("div"); const controlUI = document.createElement("button"); controlUI.classList.add("ui-button"); controlUI.innerText = `${text}`; controlUI.addEventListener("click", () => { adjustMap(mode, amount); }); controlDiv.appendChild(controlUI); map.controls[position].push(controlDiv); }); const adjustMap = function (mode, amount) { switch (mode) { case "tilt": map.setTilt(map.getTilt() + amount); break; case "rotate": map.setHeading(map.getHeading() + amount); break; default: break; } }; } window.initMap = initMap;
CSS
/* * 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; } .ui-button { background-color: #fff; border: 0; border-radius: 2px; box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3); margin: 10px; padding: 0 0.5em; font: 400 18px Roboto, Arial, sans-serif; overflow: hidden; height: 40px; cursor: pointer; } .ui-button:hover { background: rgb(235, 235, 235); }
HTML
<html> <head> <title>Tilt and Rotation</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="map"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly" defer ></script> </body> </html>
サンプルを試す
マウスとキーボードによる傾斜と方角の調整
傾斜と回転(方角)のユーザー操作が有効になっている場合は(プログラマティックまたは Google Cloud コンソール経由)、ユーザーがマウスやキーボードを利用して傾斜と回転を調整できます。
- マウスを使用する場合、Shift キーを押したままクリックし、マウスを上下にドラッグして傾きを調整し、左右にドラックして方角を調整します。
- キーボードを使用する場合、Shift キーを押したまま、上下の矢印キーを使用して傾きを調節し、左右の矢印キーを使用して方角を調整します。
傾斜と方角をプログラムで調整する
setTilt()
メソッドと setHeading()
メソッドを使用すると、ベクターマップの傾斜と方角をプログラマティックに調整できます。方角とは、カメラが向いている方向を北から時計回りの角度で表したものです。したがって、map.setHeading(90)
の場合、東が上向きになるよう地図が回転します。傾斜の角度は頂点から測定されるため、map.setTilt(0)
の場合は真下を向き、map.setTilt(45)
の場合は傾斜ビューになります。
setTilt()
を呼び出して、地図の傾斜の角度を設定します。getTilt()
を使用して、現在の傾斜値を取得します。setHeading()
を呼び出して、地図の方角を設定します。getHeading()
を使用して、現在の方角値を取得します。
傾斜と方角を維持したまま地図の中心を変更するには、map.setCenter()
または map.panBy()
を使用します。
なお、使用できる角度の範囲は、現在のズームレベルによって異なります。この範囲外となる値は、現在許可されている範囲に収められます。
moveCamera
メソッドを使用して、方角、傾斜、中央、ズームをプログラマティックに変更することもできます。詳細
他のメソッドへの影響
傾斜または回転を地図に適用すると、Maps JavaScript API の他のメソッドの動作も影響を受けます。
map.getBounds()
は常に、表示されるリージョンを含む最小の境界ボックスを返します。傾斜が適用されると、返される境界は、地図のビューポートで表示されるリージョンよりも大きなリージョンを表す可能性があります。map.fitBounds()
は、境界に収める前に傾斜と方角を 0 にリセットします。map.panToBounds()
は、境界をパンする前に、傾斜と方角を 0 にリセットします。map.setTilt()
は任意の値を受け入れますが、現在の地図のズームレベルに基づいて最大傾斜が制限されます。map.setHeading()
は任意の値を受け入れますが、範囲 [0, 360] に収まるように変更されます。
カメラを制御する
カメラ プロパティの組み合わせを一括で更新するには、map.moveCamera()
関数を使用します。map.moveCamera()
は、更新するすべてのカメラ プロパティを含む 1 つのパラメータを承認します。次の例では、map.moveCamera()
を呼び出して、center
、zoom
、heading
、tilt
を一度に設定しています。
map.moveCamera({
center: new google.maps.LatLng(37.7893719, -122.3942),
zoom: 16,
heading: 320,
tilt: 47.5
});
次に示すように、アニメーション ループを使用して map.moveCamera()
を呼び出すことで、カメラ プロパティをアニメーション化することができます。
const degreesPerSecond = 3;
function animateCamera(time) {
// Update the heading, leave everything else as-is.
map.moveCamera({
heading: (time / 1000) * degreesPerSecond
});
requestAnimationFrame(animateCamera);
}
// Start the animation.
requestAnimationFrame(animateCamera);
カメラの位置
地図ビューは、平面を見下ろすカメラとしてモデル化されています。カメラの位置は(したがって地図のレンダリングも)、target(緯度と経度の位置)、bearing、tilt、zoom の各プロパティで指定されます。
target(位置)
カメラの target は地図の中心位置で、緯度と経度の座標で指定されます。
緯度は、-85~85 度の範囲で指定できます。この範囲以外の値は、この範囲内の最も近い値に設定されます。たとえば、緯度 100 を指定した場合は、値が 85 に設定されます。経度は -180~180 度の範囲になります。この範囲以外の値は、-180~180 の範囲内に収まるように変換されます。たとえば、480、840、1200 はすべて、120 度に変換されます。bearing(向き)
カメラの bearing は、コンパス方位を真北(地図の上端に対応)からの角度で示したものです。地図の中央から地図上端に向かって垂直線を引いた場合、bearing はカメラの向き(heading)を真北からの相対的な角度で示したものに対応します。
bearing が 0 なら、地図の上端が真北を指していることを意味します。bearing の値が 90 なら、地図の上端は真東(コンパスで 90 度)を指していることを意味します。値が 180 なら、地図の上端は真南を指します。
Maps API では、地図の bearing を変更することが可能です。車を運転する人の多くは、道路地図の向きを進行方向に合わせます。一方、地図とコンパスを使用するハイカーの多くは、垂直線が北を指すように地図の向きを設定します。
tilt(傾斜角、投影角または視角)
tilt は、地図の中心の真上を通る円弧上にあるカメラの位置として定義され、天底(カメラの真下を指す方向)からの度数で示されます。値が 0 なら、カメラが真下を向いていることを意味します。値を 0 より大きくすると、カメラはその角度の分だけ水平線に向かって円弧上を移動し、傾いていきます。角度を変更すると、遠くをより小さく、近くをより大きく描く透視投影法で地図が表示されます。以下の図でこれを示します。
以下の図の傾斜角は 0 度です。最初の図は、これを図解したものです。位置 1 がカメラの位置で、位置 2 が現在の地図の位置です。その下に、生成される地図を示します。
以下の図では、傾斜角が 45 度です。カメラが真上(0 度)と地面(90 度)を結ぶ円弧に沿って、位置 3 まで半分移動している点に注意してください。カメラが地図の中心点を指していることに変わりはありませんが、位置 4 の線で表される領域も視界に入っています。
このスクリーンショットの地図の中心は、元の地図と同じ地点に設定されていますが、地図の上部により多くの対象物が表示されています。角度を 45 度より大きくすると、カメラと地図位置の間にある対象物が相対的に大きく表示され、地図位置より後ろにある対象物は相対的に小さく表示されるようになるため、3 次元効果が生まれます。
zoom(ズームレベル)
カメラのズームレベルにより、地図の縮尺が決まります。ズームレベルが大きいほど画面の表示はより詳細になり、ズームレベルが小さいほど表示される地域が広くなります。
ズームレベルを整数にする必要はありません。地図で許可されるズームレベルの範囲は、target、地図タイプ、画面サイズといった複数の要因によって決まります。範囲外の数値は、それに最も近い有効な値(最小ズームレベルまたは最大ズームレベル)に変換されます。次のリストは、各ズームレベルで表示されるおおよその詳細度を示しています。
- 1: 世界
- 5: 大陸
- 10: 都市
- 15: 通り
- 20: 建物
小数ズーム
ベクター地図は小数ズームに対応しているため、整数ではなく小数値を使用してズームできます。ラスター地図とベクター地図はどちらも小数ズームに対応していますが、ベクター地図はデフォルトでオン、ラスター地図はデフォルトでオフになっています。小数ズームのオン、オフを切り替えるには、地図オプションの isFractionalZoomEnabled
を使用します。
次の例では、地図を初期化する際に小数ズームを有効にしています。
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8,
isFractionalZoomEnabled: true
});
以下のように地図オプションの isFractionalZoomEnabled
を設定することで、小数ズームのオンとオフを切り替えることもできます。
// Using map.set
map.set('isFractionalZoomEnabled', true);
// Using map.setOptions
map.setOptions({isFractionalZoomEnabled: true});
小数ズームがオンかオフかを検出するようにリスナーを設定できます。この設定は、isFractionalZoomEnabled
を true
または false
に明示的に設定していない場合に特に便利です。次のコード例は、小数ズームが有効になっているかどうかを確認します。
map.addListener('isfractionalzoomenabled_changed', () => {
const isFractionalZoomEnabled = map.get('isFractionalZoomEnabled');
if (isFractionalZoomEnabled === false) {
console.log('not using fractional zoom');
} else if (isFractionalZoomEnabled === true) {
console.log('using fractional zoom');
} else {
console.log('map not done initializing yet');
}
});