ストリート ビュー サービス

概要

プラットフォームを選択: Android iOS JavaScript

Google ストリートビューは、対象地域全体について、指定された道路からの 360 度のパノラマビューを提供します。ストリートビューの API の対象地域は、Google マップ アプリケーション(https://maps.google.com/)の対象地域と同じです。ストリートビューを現在利用できる都市の一覧については、Google マップのウェブサイトをご覧ください。

ストリートビュー画像の例は次のとおりです。


Maps JavaScript API には、Google マップのストリートビューで使用される画像を取得および操作するためのストリートビュー サービスが用意されています。ストリートビュー サービスは、ブラウザ内でネイティブにサポートされています。

ストリートビュー地図の用途

ストリートビューは、スタンドアロンの DOM 要素内で使用できますが、用途として最も便利なのは地図上で場所を特定したいときです。地図でストリートビューはデフォルトで有効になっており、ズームや移動に使用するナビゲーション コントロールには、ストリートビューの「ペグマン コントロール」が統合されています。このコントロールを非表示にするには、地図の MapOptionsstreetViewControlfalse に設定します。ストリートビュー コントロールのデフォルトの位置を変更することもできます。その場合は、MapstreetViewControlOptions.position プロパティを新しい ControlPosition に設定します。

ストリートビューのペグマン コントロールを使用して、地図内で直接ストリートビューのパノラマ画像を表示できます。ユーザーがペグマンを長押しすると地図が更新され、ストリートビューが有効な道路の周りに青い輪郭線が表示されて、Google マップアプリと同様の機能が提供されます。

ユーザーがペグマン マーカーを道路にドロップすると、地図が更新されて、指定された場所のストリートビュー パノラマが表示されます。

ストリートビュー パノラマ

ストリートビュー画像は、StreetViewPanorama オブジェクトを使用することでサポートされます。このオブジェクトがストリートビュー「ビューア」への API インターフェースとなります。各地図にはデフォルトのストリートビュー パノラマがあり、これは地図の getStreetView() メソッドを呼び出して取得できます。streetViewControl オプションを true に設定してストリートビュー コントロールを地図に追加すると、ペグマン コントロールがこのデフォルトのストリートビュー パノラマに自動的に接続されます。

独自の StreetViewPanorama オブジェクトを作成して、地図の streetView プロパティを明示的にこの作成したオブジェクトに設定することで、地図でデフォルトのオブジェクトを使わずに、作成したオブジェクトを使用することもできます。地図とパノラマ画像間のオーバーレイの自動共有など、デフォルトの動作を変更する場合、デフォルトのパノラマ画像をオーバーライドすることをおすすめします(下記のストリートビュー内のオーバーレイを参照してください)。

ストリートビュー コンテナ

別の DOM 要素(一般には <div> 要素)内の StreetViewPanorama を表示する場合は、StreetViewPanorama のコンストラクタ内で DOM 要素を渡します。画像の表示を最適化するために、最小サイズの 200 x 200 ピクセルを推奨します。

注: ストリートビュー機能は地図との併用を念頭に設計されていますが、地図の使用が必須であるというわけではありません。地図を使用せずに、ストリートビュー オブジェクトを単独で使用することもできます。

ストリートビューの位置情報と視点(POV)

StreetViewPanorama コンストラクタで StreetViewOptions パラメータを使用して、ストリートビューの場所と視点を設定することもできます。場所と視点を変更するには、オブジェクト作成後にそのオブジェクトの setPosition()setPov() を呼び出します。

ストリートビューではカメラで何を写すかが「場所」として定義されますが、このときカメラ画像の向きは指定されません。向きを指定するには、StreetViewPov オブジェクトで次の 2 つのプロパティを指定します。

  • heading(デフォルトは 0)は、カメラ中心の回転角度を、真北からの相対角度で定義します。方角の相対角度は時計回りで定義します(90 度に設定すると東向きになります)。
  • pitch(デフォルトは 0)は、カメラの初期デフォルト ピッチからの「上」または「下」向きの角度を定義します。通常は水平です(常に水平とは限りません。たとえば、山で撮影された画像は、水平ではないデフォルトの初期ピッチで表示される場合があります)。ピッチ角度は、見上げる方向を正の値(デフォルトのピッチと直行する真上方向が +90 度)で、下を向く方向を負の値(デフォルトのピッチと直交する真下の方向が -90 度)として指定します。

StreetViewPov オブジェクトは、ほとんどの場合、ストリートビュー カメラの視点の特定に使用されます。StreetViewPanorama.getPhotographerPov() メソッドを使用して、撮影者の視点(通常は車やトライクが向いていた方向)を特定することもできます。

次のコードは、ボストンの地図とフェンウェイ パークの初期ビューです。ペグマンを選択して地図上のサポート対象の場所にドラッグすると、ストリートビュー パノラマが変化します。

TypeScript

function initialize() {
  const fenway = { lat: 42.345573, lng: -71.098326 };
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      center: fenway,
      zoom: 14,
    }
  );
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano") as HTMLElement,
    {
      position: fenway,
      pov: {
        heading: 34,
        pitch: 10,
      },
    }
  );

  map.setStreetView(panorama);
}

declare global {
  interface Window {
    initialize: () => void;
  }
}
window.initialize = initialize;

JavaScript

function initialize() {
  const fenway = { lat: 42.345573, lng: -71.098326 };
  const map = new google.maps.Map(document.getElementById("map"), {
    center: fenway,
    zoom: 14,
  });
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano"),
    {
      position: fenway,
      pov: {
        heading: 34,
        pitch: 10,
      },
    },
  );

  map.setStreetView(panorama);
}

window.initialize = initialize;

CSS

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#map,
#pano {
  float: left;
  height: 100%;
  width: 50%;
}

HTML

<html>
  <head>
    <title>Street View split-map-panes</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map"></div>
    <div id="pano"></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=initialize&v=weekly"
      defer
    ></script>
  </body>
</html>
サンプルを表示

サンプルを試す

モバイル デバイスでのモーション トラッキング

デバイスの画面の向きイベントに対応するデバイスでは、この API により、デバイスの動きに連動して視点が変わるストリートビューをユーザーに表示できます。ユーザーは、デバイスを動かすことで周囲を見回すことができます。この機能は、モーション トラッキングまたはデバイス ローテーション トラッキングと呼ばれます。

アプリの開発者は、デフォルトの動作を次のように変更できます。

  • モーション トラッキングの機能を有効または無効にする。モーション トラッキングに対応するデバイスでは、この機能がデフォルトで有効になります。次のサンプルは、モーション トラッキングを無効にしますが、モーション トラッキングのコントロールは表示されたままにしています(ユーザーは、コントロールをタップしてモーション トラッキングをオンにできます)。
    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTracking: false
        });
  • モーション トラッキングのコントロールを表示または非表示にする。モーション トラッキングに対応するデバイス上では、このコントロールがデフォルトで表示されます。ユーザーはコントロールをタップして、モーション トラッキングを有効または無効にできます。なお、motionTrackingControl の値にかかわらず、デバイスがモーション トラッキングに対応しない場合、コントロールは表示されません。

    次のサンプルでは、モーション トラッキングとモーション トラッキング コントロールの両方を無効にします。この場合、ユーザーはモーション トラッキングをオンにできません。

    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTracking: false,
          motionTrackingControl: false
        });
  • モーション トラッキング コントロールのデフォルト位置を変更する。デフォルトでは、コントロールはパノラマの右下に表示されます(位置は RIGHT_BOTTOM)。次のサンプルでは、コントロールの位置を左下に設定しています。
    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTrackingControlOptions: {
            position: google.maps.ControlPosition.LEFT_BOTTOM
          }
        });

実際のモーション トラッキングの動作を確認するには、モバイル デバイス(またはデバイスの画面の向きイベントをサポートする任意のデバイス)で次のサンプルを表示してください。


サンプルを表示

ストリートビュー内のオーバーレイ

デフォルトの StreetViewPanorama オブジェクトは地図オーバーレイの表示をネイティブにサポートします。オーバーレイは一般に、LatLng の位置に固定された「ストリート レベル」で表示されます(たとえば、マーカーは、その尾の部分がストリートビュー パノラマ内で場所の水平面に固定されて表示されます)。

現在、ストリートビュー パノラマでサポートされているオーバーレイのタイプは、MarkerInfoWindow、カスタムの OverlayView に制限されています。地図上に表示するオーバーレイは、ストリートビュー パノラマ上でも表示できます。その場合は、パノラマ画像を Map オブジェクトの代替として扱い、setMap() を呼び出して引数に地図の代わりに StreetViewPanorama を渡します。情報ウィンドウも同様に、open() を呼び出して、地図の代わりに StreetViewPanorama() を渡すことで、ストリートビュー パノラマ内で開くことができます。

また、デフォルトの StreetViewPanorama で地図を作成する場合、地図上にマーカーが作成されると、地図の関連付けられたストリートビュー パノラマと自動的に共有されます(パノラマが表示されている場合)。デフォルトのストリートビュー パノラマを取得するには、Map オブジェクトの getStreetView() を呼び出します。地図の streetView プロパティを明示的に独自構成の StreetViewPanorama に設定する場合、デフォルトのパノラマ画像をオーバーライドすることになります。

次の例は、ニューヨーク市アスター プレイス周辺のさまざまな場所を表すマーカーを表示します。ストリートビューに表示を切り替えると、共有マーカーが StreetViewPanorama 内に表示されます。

TypeScript

let panorama: google.maps.StreetViewPanorama;

function initMap(): void {
  const astorPlace = { lat: 40.729884, lng: -73.990988 };

  // Set up the map
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      center: astorPlace,
      zoom: 18,
      streetViewControl: false,
    }
  );

  document
    .getElementById("toggle")!
    .addEventListener("click", toggleStreetView);

  const cafeIcon = document.createElement("img");
  cafeIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/cafe_icon.svg";

  const dollarIcon = document.createElement("img");
  dollarIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bank_icon.svg";

  const busIcon = document.createElement("img");
  busIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bus_icon.svg";


  // Set up the markers on the map
  const cafeMarker = new google.maps.Marker({
    position: { lat: 40.730031, lng: -73.991428 },
    map,
    title: "Cafe",
    icon: cafeIcon.src,
  });

  const bankMarker = new google.maps.Marker({
    position: { lat: 40.729681, lng: -73.991138 },
    map,
    title: "Bank",
    icon: dollarIcon.src,
  });

  const busMarker = new google.maps.Marker({
    position: { lat: 40.729559, lng: -73.990741 },
    map,
    title: "Bus Stop",
    icon: busIcon.src,
  });

  // We get the map's default panorama and set up some defaults.
  // Note that we don't yet set it visible.
  panorama = map.getStreetView()!; // TODO fix type
  panorama.setPosition(astorPlace);
  panorama.setPov(
    /** @type {google.maps.StreetViewPov} */ {
      heading: 265,
      pitch: 0,
    }
  );
}

function toggleStreetView(): void {
  const toggle = panorama.getVisible();

  if (toggle == false) {
    panorama.setVisible(true);
  } else {
    panorama.setVisible(false);
  }
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

let panorama;

function initMap() {
  const astorPlace = { lat: 40.729884, lng: -73.990988 };
  // Set up the map
  const map = new google.maps.Map(document.getElementById("map"), {
    center: astorPlace,
    zoom: 18,
    streetViewControl: false,
  });

  document.getElementById("toggle").addEventListener("click", toggleStreetView);

  const cafeIcon = document.createElement("img");

  cafeIcon.src =
    "https://developers.google.com/maps/documentation/javascript/examples/full/images/cafe_icon.svg";

  const dollarIcon = document.createElement("img");

  dollarIcon.src =
    "https://developers.google.com/maps/documentation/javascript/examples/full/images/bank_icon.svg";

  const busIcon = document.createElement("img");

  busIcon.src =
    "https://developers.google.com/maps/documentation/javascript/examples/full/images/bus_icon.svg";

  // Set up the markers on the map
  const cafeMarker = new google.maps.Marker({
    position: { lat: 40.730031, lng: -73.991428 },
    map,
    title: "Cafe",
    icon: cafeIcon.src,
  });
  const bankMarker = new google.maps.Marker({
    position: { lat: 40.729681, lng: -73.991138 },
    map,
    title: "Bank",
    icon: dollarIcon.src,
  });
  const busMarker = new google.maps.Marker({
    position: { lat: 40.729559, lng: -73.990741 },
    map,
    title: "Bus Stop",
    icon: busIcon.src,
  });

  // We get the map's default panorama and set up some defaults.
  // Note that we don't yet set it visible.
  panorama = map.getStreetView(); // TODO fix type
  panorama.setPosition(astorPlace);
  panorama.setPov(
    /** @type {google.maps.StreetViewPov} */ {
      heading: 265,
      pitch: 0,
    },
  );
}

function toggleStreetView() {
  const toggle = panorama.getVisible();

  if (toggle == false) {
    panorama.setVisible(true);
  } else {
    panorama.setVisible(false);
  }
}

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;
}

#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;
}

#floating-panel {
  margin-left: -100px;
}

HTML

<html>
  <head>
    <title>Overlays Within Street View</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="floating-panel">
      <input type="button" value="Toggle Street View" id="toggle" />
    </div>
    <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&libraries=marker&v=weekly"
      defer
    ></script>
  </body>
</html>
サンプルを表示

サンプルを試す

ストリートビューのイベント

ストリートビューの表示を切り替えたり方向を操作しているとき、StreetViewPanorama の状態の変化を示すイベントを監視できます。

  • pano_changed は、個々のパノラマ ID が変更されたときに起動されます。このイベントは、イベントがトリガーされたときにパノラマ画像内のいずれかの関連データ(リンクなど)も変更されたことを保証するものではありません。このイベントは、パノラマ ID の変更のみを示します。パノラマ ID(該当パノラマを参照するために使用できる)は、現在のブラウザ セッション内のみで不変です。
  • position_changed は、パノラマの基準(LatLng)位置が変更されたときに起動されます。パノラマ画像を回転しても、このイベントはトリガーされません。関連パノラマ ID を変更しなくても、パノラマ画像の基本位置を変更できます。API が最も近いパノラマ ID をそのパノラマの位置と自動的に関連付けるためです。
  • pov_changed は、ストリートビューの StreetViewPov が変更されたときに起動されます。このイベントは、位置とパノラマ ID が変わらない間に発行される場合があります。
  • links_changed は、ストリートビューのリンクが変更されると起動されます。このイベントは、pano_changed で指定されたパノラマ ID が変更された後、非同期的に起動される場合があります。
  • visible_changed は、ストリートビューの表示状態が変更されると起動されます。このイベントは、pano_changed で指定されたパノラマ ID が変更された後、非同期的に起動される場合があります。

次のコードは、これらのイベントを処理して基準の StreetViewPanorama のデータを収集します。

TypeScript

function initPano() {
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano") as HTMLElement,
    {
      position: { lat: 37.869, lng: -122.255 },
      pov: {
        heading: 270,
        pitch: 0,
      },
      visible: true,
    }
  );

  panorama.addListener("pano_changed", () => {
    const panoCell = document.getElementById("pano-cell") as HTMLElement;

    panoCell.innerHTML = panorama.getPano();
  });

  panorama.addListener("links_changed", () => {
    const linksTable = document.getElementById("links_table") as HTMLElement;

    while (linksTable.hasChildNodes()) {
      linksTable.removeChild(linksTable.lastChild as ChildNode);
    }

    const links = panorama.getLinks();

    for (const i in links) {
      const row = document.createElement("tr");

      linksTable.appendChild(row);

      const labelCell = document.createElement("td");

      labelCell.innerHTML = "<b>Link: " + i + "</b>";

      const valueCell = document.createElement("td");

      valueCell.innerHTML = links[i].description as string;
      linksTable.appendChild(labelCell);
      linksTable.appendChild(valueCell);
    }
  });

  panorama.addListener("position_changed", () => {
    const positionCell = document.getElementById(
      "position-cell"
    ) as HTMLElement;

    (positionCell.firstChild as HTMLElement).nodeValue =
      panorama.getPosition() + "";
  });

  panorama.addListener("pov_changed", () => {
    const headingCell = document.getElementById("heading-cell") as HTMLElement;
    const pitchCell = document.getElementById("pitch-cell") as HTMLElement;

    (headingCell.firstChild as HTMLElement).nodeValue =
      panorama.getPov().heading + "";
    (pitchCell.firstChild as HTMLElement).nodeValue =
      panorama.getPov().pitch + "";
  });
}

declare global {
  interface Window {
    initPano: () => void;
  }
}
window.initPano = initPano;

JavaScript

function initPano() {
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano"),
    {
      position: { lat: 37.869, lng: -122.255 },
      pov: {
        heading: 270,
        pitch: 0,
      },
      visible: true,
    },
  );

  panorama.addListener("pano_changed", () => {
    const panoCell = document.getElementById("pano-cell");

    panoCell.innerHTML = panorama.getPano();
  });
  panorama.addListener("links_changed", () => {
    const linksTable = document.getElementById("links_table");

    while (linksTable.hasChildNodes()) {
      linksTable.removeChild(linksTable.lastChild);
    }

    const links = panorama.getLinks();

    for (const i in links) {
      const row = document.createElement("tr");

      linksTable.appendChild(row);

      const labelCell = document.createElement("td");

      labelCell.innerHTML = "<b>Link: " + i + "</b>";

      const valueCell = document.createElement("td");

      valueCell.innerHTML = links[i].description;
      linksTable.appendChild(labelCell);
      linksTable.appendChild(valueCell);
    }
  });
  panorama.addListener("position_changed", () => {
    const positionCell = document.getElementById("position-cell");

    positionCell.firstChild.nodeValue = panorama.getPosition() + "";
  });
  panorama.addListener("pov_changed", () => {
    const headingCell = document.getElementById("heading-cell");
    const pitchCell = document.getElementById("pitch-cell");

    headingCell.firstChild.nodeValue = panorama.getPov().heading + "";
    pitchCell.firstChild.nodeValue = panorama.getPov().pitch + "";
  });
}

window.initPano = initPano;

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;
}

#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;
}

#pano {
  width: 50%;
  height: 100%;
  float: left;
}

#floating-panel {
  width: 45%;
  height: 100%;
  float: right;
  text-align: left;
  overflow: auto;
  position: static;
  border: 0px solid #999;
}

HTML

<html>
  <head>
    <title>Street View Events</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="pano"></div>
    <div id="floating-panel">
      <table>
        <tr>
          <td><b>Position</b></td>
          <td id="position-cell">&nbsp;</td>
        </tr>
        <tr>
          <td><b>POV Heading</b></td>
          <td id="heading-cell">270</td>
        </tr>
        <tr>
          <td><b>POV Pitch</b></td>
          <td id="pitch-cell">0.0</td>
        </tr>
        <tr>
          <td><b>Pano ID</b></td>
          <td id="pano-cell">&nbsp;</td>
        </tr>
        <table id="links_table"></table>
      </table>
    </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=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
サンプルを表示

サンプルを試す

ストリートビューのコントロール

StreetViewPanorama を表示するとき、デフォルトでさまざまなコントロールがパノラマに表示されます。これらのコントロールは、ストリートビューの StreetViewPanoramaOptions 内にある該当のフィールドを true または false に設定して、有効または無効にできます。

  • panControl は、パノラマを回転させるために使用します。このコントロールは、デフォルトでコンパスとパンが統合された標準コントロールとして表示されます。panControlOptions フィールドの PanControlOptions を指定して、コントロールの位置を変更できます。
  • zoomControl は、画像内をズームするために使用します。このコントロールは、デフォルトでパノラマ画像の右下に表示されます。コントロールの外観を変更するには、zoomControlOptions フィールド内で ZoomControlOptions を指定します。
  • addressControl は、関連する場所の住所を示すテキスト オーバーレイと、Google マップでその場所を開くためのリンクを提供します。コントロールの外観を変更するには、addressControlOptions フィールド内で StreetViewAddressControlOptions を指定します。
  • fullscreenControl は、ストリートビューを全画面モードで開くオプションを提供します。コントロールの外観を変更するには、fullscreenControlOptions フィールド内で FullscreenControlOptions を指定します。
  • motionTrackingControl は、モバイル デバイスでモーション トラッキングを有効または無効にするオプションを提供します。このコントールは、デバイスの画面の向きイベントをサポートするデバイスでのみ表示されます。このコントロールは、デフォルトでパノラマ画像の右下に表示されます。コントロールの位置を変更するには、MotionTrackingControlOptions を指定します。詳しくは、モーション トラッキングのセクションをご覧ください。
  • linksControl は、隣接するパノラマ画像に移動するためのガイド矢印を画面上に表示します。
  • クローズ コントロールがあると、ユーザーがストリートビューのビューアを閉じることができます。クローズ コントロールは、enableCloseButtontrue または false に設定することで有効または無効にできます。

次の例は、関連するストリートビュー内に表示されるコントロールを変更して、ビューのリンクを削除しています。

TypeScript

function initPano() {
  // Note: constructed panorama objects have visible: true
  // set by default.
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("map") as HTMLElement,
    {
      position: { lat: 42.345573, lng: -71.098326 },
      addressControlOptions: {
        position: google.maps.ControlPosition.BOTTOM_CENTER,
      },
      linksControl: false,
      panControl: false,
      enableCloseButton: false,
    }
  );
}

declare global {
  interface Window {
    initPano: () => void;
  }
}
window.initPano = initPano;

JavaScript

function initPano() {
  // Note: constructed panorama objects have visible: true
  // set by default.
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("map"),
    {
      position: { lat: 42.345573, lng: -71.098326 },
      addressControlOptions: {
        position: google.maps.ControlPosition.BOTTOM_CENTER,
      },
      linksControl: false,
      panControl: false,
      enableCloseButton: false,
    },
  );
}

window.initPano = initPano;

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;
}

HTML

<html>
  <head>
    <title>Street View Controls</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=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
サンプルを表示

サンプルを試す

ストリートビューのデータへの直接アクセス

地図やパノラマ画像を直接操作する必要なく、プログラムを使用してストリートビュー データの利用可否を判断したり、特定のパノラマ画像に関する情報を返したりすることが必要な場合があります。StreetViewService オブジェクトを使用して、これを実行できます。このオブジェクトには Google のストリートビュー サービスに保存されているデータへのインターフェースがあります。

ストリートビュー サービスのリクエスト

ストリートビュー サービスにアクセスすると、Google Maps API は外部サーバーに対して呼び出しを行うので、処理が非同期になります。このため、コールバック メソッドを渡してリクエストの完了時に実行し、このコールバック メソッドで結果を処理する必要があります。

StreetViewService へのリクエストは、StreetViewPanoRequest または StreetViewLocationRequest を使用して実行できます。

StreetViewPanoRequest を使用したリクエストは、パノラマ画像を一意に識別する参照 ID が指定されたパノラマデータを返します。これらの参照 ID は、該当のパノラマ画像の使用期間のみ不変です。

StreetViewLocationRequest を使用するリクエストは、次のパラメータを使用して、指定された場所のパノラマデータを検索します。

  • location は、パノラマを検索する場所(緯度と経度)を指定します。
  • preference は、指定された場所に最も近い位置にあるパノラマや、半径内で最適なパノラマなど、半径内でどのようなパノラマを優先して検索するかを設定します。
  • radius は、パノラマを検索する半径(メートル単位)を設定します。指定された緯度と経度の地点を中心とした半径になります。指定しない場合のデフォルトは 50 です。
  • source は、検索するパノラマのソースを指定します。有効な値は次のとおりです。
    • default は、ストリートビューのデフォルトのソースを使用します。検索対象が特定のソースに限定されません。
    • outdoor は、検索対象を屋外のパノラマのみに限定します。 なお、指定された場所の屋外のパノラマが存在しない場合があります。

ストリートビュー サービスのレスポンス

getPanorama() 関数には、ストリートビュー サービスからの結果の取得時に実行されるコールバック関数が必要です。 このコールバック関数は StreetViewPanoramaData オブジェクト内にパノラマデータのセットを返し、次にリクエストのステータスを示す StreetViewStatus コードを返します。

StreetViewPanoramaData オブジェクト仕様には、次の形式のストリートビュー パノラマについてのメタデータが含まれています。

{
  "location": {
    "latLng": LatLng,
    "description": string,
    "pano": string
  },
  "copyright": string,
  "links": [{
      "heading": number,
      "description": string,
      "pano": string,
      "roadColor": string,
      "roadOpacity": number
    }],
  "tiles": {
    "worldSize": Size,
    "tileSize": Size,
    "centerHeading": number
  }
}

このデータ オブジェクトは StreetViewPanorama オブジェクトそのものではありません。このデータを使用してストリートビュー オブジェクトを作成するには、StreetViewPanorama を作成して setPano() を呼び出し、返された location.pano フィールドで指定された ID を渡します。

status コードは次の値のいずれかを返します。

  • OK: 一致するパノラマをサービスが見つけたことを示します。
  • ZERO_RESULTS: 渡された条件に一致するパノラマをサービスが見つけられなかったことを示します。
  • UNKNOWN_ERROR: ストリートビュー リクエストが処理できず、正確な理由が不明であることを示します。

次のコードは、マーカーを作成し、地図上でのユーザーのクリックに応答する StreetViewService を作成します。このマーカーをクリックすると、その場所の StreetViewPanorama を表示します。コードはサービスから返された StreetViewPanoramaData のコンテンツを使用します。

TypeScript

/*
 * Click the map to set a new location for the Street View camera.
 */

let map: google.maps.Map;

let panorama: google.maps.StreetViewPanorama;

function initMap(): void {
  const berkeley = { lat: 37.869085, lng: -122.254775 };
  const sv = new google.maps.StreetViewService();

  panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano") as HTMLElement
  );

  // Set up the map.
  map = new google.maps.Map(document.getElementById("map") as HTMLElement, {
    center: berkeley,
    zoom: 16,
    streetViewControl: false,
  });

  // Set the initial Street View camera to the center of the map
  sv.getPanorama({ location: berkeley, radius: 50 }).then(processSVData);

  // Look for a nearby Street View panorama when the map is clicked.
  // getPanorama will return the nearest pano when the given
  // radius is 50 meters or less.
  map.addListener("click", (event) => {
    sv.getPanorama({ location: event.latLng, radius: 50 })
      .then(processSVData)
      .catch((e) =>
        console.error("Street View data not found for this location.")
      );
  });
}

function processSVData({ data }: google.maps.StreetViewResponse) {
  const location = data.location!;

  const marker = new google.maps.Marker({
    position: location.latLng,
    map,
    title: location.description,
  });

  panorama.setPano(location.pano as string);
  panorama.setPov({
    heading: 270,
    pitch: 0,
  });
  panorama.setVisible(true);

  marker.addListener("click", () => {
    const markerPanoID = location.pano;

    // Set the Pano to use the passed panoID.
    panorama.setPano(markerPanoID as string);
    panorama.setPov({
      heading: 270,
      pitch: 0,
    });
    panorama.setVisible(true);
  });
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

/*
 * Click the map to set a new location for the Street View camera.
 */
let map;
let panorama;

function initMap() {
  const berkeley = { lat: 37.869085, lng: -122.254775 };
  const sv = new google.maps.StreetViewService();

  panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano"),
  );
  // Set up the map.
  map = new google.maps.Map(document.getElementById("map"), {
    center: berkeley,
    zoom: 16,
    streetViewControl: false,
  });
  // Set the initial Street View camera to the center of the map
  sv.getPanorama({ location: berkeley, radius: 50 }).then(processSVData);
  // Look for a nearby Street View panorama when the map is clicked.
  // getPanorama will return the nearest pano when the given
  // radius is 50 meters or less.
  map.addListener("click", (event) => {
    sv.getPanorama({ location: event.latLng, radius: 50 })
      .then(processSVData)
      .catch((e) =>
        console.error("Street View data not found for this location."),
      );
  });
}

function processSVData({ data }) {
  const location = data.location;
  const marker = new google.maps.Marker({
    position: location.latLng,
    map,
    title: location.description,
  });

  panorama.setPano(location.pano);
  panorama.setPov({
    heading: 270,
    pitch: 0,
  });
  panorama.setVisible(true);
  marker.addListener("click", () => {
    const markerPanoID = location.pano;

    // Set the Pano to use the passed panoID.
    panorama.setPano(markerPanoID);
    panorama.setPov({
      heading: 270,
      pitch: 0,
    });
    panorama.setVisible(true);
  });
}

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;
}

HTML

<html>
  <head>
    <title>Directly Accessing Street View Data</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map" style="width: 45%; height: 100%; float: left"></div>
    <div id="pano" style="width: 45%; height: 100%; float: left"></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>
サンプルを表示

サンプルを試す

カスタム ストリートビュー パノラマの指定

Maps JavaScript API は、StreetViewPanorama オブジェクト内のカスタム パノラマの表示に対応しています。カスタムのパノラマ画像を使用すると、ビルの内部や風光明媚な場所の景色、その他にも考えられるあらゆる画像を表示できます。これらのカスタム パノラマ画像から Google の既存のストリートビュー パノラマ画像へのリンクも設定できます。

一連のカスタム パノラマ画像を設定するには、次の手順に従います。

  • 各カスタム パノラマの基本パノラマ画像を作成します。この基本画像はズームイン画像を提供するため、最高解像度の画像である必要があります。
  • (オプション、推奨)基本画像から、異なるズームレベルの一連のパノラマタイルを作成します。
  • カスタム パノラマ画像間のリンクを作成します。
  • (省略可能)Google の既存のストリートビュー画像の中から「エントリ」パノラマを指定し、カスタムセットと標準セット間のリンクをカスタマイズします。
  • StreetViewPanoramaData オブジェクト内で、各パノラマ画像のメタデータを定義します。
  • カスタム パノラマのデータと画像を特定するためのメソッドを実装し、そのメソッドを StreetViewPanorama オブジェクト内でカスタム ハンドラとして指定します。

以降のセクションでこの処理について説明します。

カスタム パノラマを作成する

各ストリートビュー パノラマは、単一地点からの 360 度ビューを提供する 1 枚の画像または画像のセットです。StreetViewPanorama オブジェクトは、正距円筒図法(Plate Carrée 図法)に準拠した画像を使用します。このような図法では、360 度の水平ビュー(周囲全体)と 180 度の垂直ビュー(真上から真下)が含まれています。これらの視野を合わせてアスペクト比 2:1 の画像にします。湾曲したパノラマの全体画像は次のようになります。

市街地のパノラマビュー

通常、パノラマ画像は、1 か所から複数の写真を撮影して、パノラマ ソフトウェアを使用してそれらをスティッチする(つなぎ合わせる)ことで取得します(詳しくは、写真のスティッチ用アプリケーションの比較に関する Wikipedia をご覧ください)。これらのパノラマ画像は、カメラを 1 地点に固定して撮影する必要があります。そうすることで、2 次元平面画像を 360 度パノラマの球体に投影することができます。

道路のパノラマビューをその表面に投影した球体

パノラマを直線座標系で球体に投影しておくと、画像を直線的な「タイル」に分割する場合や、計算上のタイル座標に基づいて画像を提供する場合に便利です。

カスタムのパノラマタイルを作成する

ストリートビューでは、ズームレベルが異なる画像を用意し、ズーム コントロールを使ってデフォルト ビューからズームインしたりズームアウトしたりできます。通常、ストリートビューでは所定のパノラマ画像に対して 5 レベルのズーム解像度が提供されます。単一のパノラマ画像を使用してすべてのズームレベルを提供しようとすると、このような画像は必然的に大きなものになりアプリケーションを著しく低速化するか、高ズームレベルで非常に粗い解像度となりピクセル化された見劣りする画像を提供することになります。ただし、ズームレベルごとに解像度を変えた画像は、Google の地図タイルをズームレベル別に作成するのと同じような方法で簡単に作成できます。

StreetViewPanorama を初めて読み込むと、デフォルトでは全横幅の 25%(円弧の 90 度分)のパノラマがズームレベル 1 で表示されます。このビューは、標準的な人間の視野とほぼ同じです。基本的には、デフォルト ビューからズームアウトすると円弧(つまり視界)の角度が広がり、ズームインすると円弧の角度が狭まります。StreetViewPanorama では、選択したズームレベルでのおおよその視野が自動的に計算され、その水平方向の視野にほぼ一致するタイル セットを選ぶ形でその解像度に最適な画像が選択されます。次に視界とストリートビューのズームレベルの対応を示します。

ストリートビューのズームレベル 視界(度)
0 180
1(デフォルト) 90
2 45
3 22.5
4 11.25

ストリートビュー内に表示される画像のサイズは、ストリートビュー コンテナの画面サイズ(幅)に完全に依存します。より広いコンテナを表示しても指定のズームレベルの同じ視界が提供されますが、その解像度により適したタイルが代わって選択される場合があります。

各パノラマ画像は正距円筒図法で構成されているため、パノラマタイルの作成は比較的簡単です。この図法ではアスペクト比が 2:1 の画像が提供されるため、2:1 の比率のタイルは使い勝手が良いですが、正方形のタイルが正方形の地図でより高いパフォーマンスを発揮する場合があります(視界が正方形であるため)。

2:1 タイルの場合、ズームレベル 0 ではパノラマの全範囲を含んだ 1 つの画像(基本画像)がパノラマ全体を表し、ズームレベルを上げると全体が 4 zoomLevel 個分のタイルで表示されます(たとえば、ズームレベル 2 ではパノラマ全体が 16 枚のタイルで構成されます)。注: ストリートビューのズームレベルのタイルは、ストリートビュー コントロールで指定したズームレベルと完全に一致するわけではありません。ストリートビュー コントロールのズームレベルの場合は、指定された視野(FoV)に基づいて適切なタイルが選択されます。

タイルに分割された市街地のパノラマビュー

通常は、画像タイルに名前を付けて、プログラムによって選択できるようにします。このような場合の命名規則については、カスタム パノラマ リクエストの処理をご覧ください。

カスタム パノラマ リクエストの処理

カスタム パノラマを使用するには、StreetViewPanorama.registerPanoProvider() を呼び出してカスタム パノラマ プロバイダのメソッドの名前を指定します。パノラマ プロバイダのメソッドは StreetViewPanoramaData オブジェクトを返し、次のシグネチャを持つ必要があります。

Function(pano):StreetViewPanoramaData

StreetViewPanoramaData は次の形式のオブジェクトです。

{
  copyright: string,
  location: {
    description: string,
    latLng: google.maps.LatLng,
    pano: string
  },
  tiles: {
    tileSize: google.maps.Size,
    worldSize: google.maps.Size,
    heading: number,
    getTileUrl: Function
  },
  links: [
    description: string,
    heading: number,
    pano: string,
    roadColor: string,
    roadOpacity: number
  ]
}

カスタム パノラマを次のように表示します。

  • StreetViewPanoramaOptions.pano プロパティにカスタム値を設定します。
  • StreetViewPanorama.registerPanoProvider() を呼び出して、カスタム パノラマのプロバイダ関数を指定します。
  • 指定された pano 値を処理するカスタム パノラマのプロバイダ関数を実装します。
  • StreetViewPanoramaData オブジェクトを作成します。
  • StreetViewTileData.getTileUrl プロパティを、指定するカスタムタイルのプロバイダ関数の名前に設定します(例: getCustomPanoramaTileUrl)。
  • 次のサンプルのように、カスタムタイルのプロバイダ関数を実装します。
  • StreetViewPanoramaData オブジェクトを返します。

注: カスタム パノラマを表示したい場合は、position を直接 StreetViewPanorama で設定しないようにしてください。位置を直接設定すると、その場所に一番近いデフォルトのストリートビュー画像がリクエストされてしまいます。その代わりに、この位置は、カスタム StreetViewPanoramaData オブジェクトの location.latLng フィールド内で設定します。

次の例は、Google シドニー オフィスのカスタム パノラマ画像を表示します。なお、この例では、地図やデフォルトのストリートビュー画像は使用しません。

TypeScript

function initPano() {
  // Set up Street View and initially set it visible. Register the
  // custom panorama provider function. Set the StreetView to display
  // the custom panorama 'reception' which we check for below.
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("map") as HTMLElement,
    { pano: "reception", visible: true }
  );

  panorama.registerPanoProvider(getCustomPanorama);
}

// Return a pano image given the panoID.
function getCustomPanoramaTileUrl(
  pano: string,
  zoom: number,
  tileX: number,
  tileY: number
): string {
  return (
    "https://developers.google.com/maps/documentation/javascript/examples/full/images/" +
    "panoReception1024-" +
    zoom +
    "-" +
    tileX +
    "-" +
    tileY +
    ".jpg"
  );
}

// Construct the appropriate StreetViewPanoramaData given
// the passed pano IDs.
function getCustomPanorama(pano: string): google.maps.StreetViewPanoramaData {
  if (pano === "reception") {
    return {
      location: {
        pano: "reception",
        description: "Google Sydney - Reception",
      },
      links: [],
      // The text for the copyright control.
      copyright: "Imagery (c) 2010 Google",
      // The definition of the tiles for this panorama.
      tiles: {
        tileSize: new google.maps.Size(1024, 512),
        worldSize: new google.maps.Size(2048, 1024),
        // The heading in degrees at the origin of the panorama
        // tile set.
        centerHeading: 105,
        getTileUrl: getCustomPanoramaTileUrl,
      },
    };
  }
  // @ts-ignore TODO fix typings
  return null;
}

declare global {
  interface Window {
    initPano: () => void;
  }
}
window.initPano = initPano;

JavaScript

function initPano() {
  // Set up Street View and initially set it visible. Register the
  // custom panorama provider function. Set the StreetView to display
  // the custom panorama 'reception' which we check for below.
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("map"),
    { pano: "reception", visible: true },
  );

  panorama.registerPanoProvider(getCustomPanorama);
}

// Return a pano image given the panoID.
function getCustomPanoramaTileUrl(pano, zoom, tileX, tileY) {
  return (
    "https://developers.google.com/maps/documentation/javascript/examples/full/images/" +
    "panoReception1024-" +
    zoom +
    "-" +
    tileX +
    "-" +
    tileY +
    ".jpg"
  );
}

// Construct the appropriate StreetViewPanoramaData given
// the passed pano IDs.
function getCustomPanorama(pano) {
  if (pano === "reception") {
    return {
      location: {
        pano: "reception",
        description: "Google Sydney - Reception",
      },
      links: [],
      // The text for the copyright control.
      copyright: "Imagery (c) 2010 Google",
      // The definition of the tiles for this panorama.
      tiles: {
        tileSize: new google.maps.Size(1024, 512),
        worldSize: new google.maps.Size(2048, 1024),
        // The heading in degrees at the origin of the panorama
        // tile set.
        centerHeading: 105,
        getTileUrl: getCustomPanoramaTileUrl,
      },
    };
  }
  // @ts-ignore TODO fix typings
  return null;
}

window.initPano = initPano;

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;
}

HTML

<html>
  <head>
    <title>Custom Street View Panoramas</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=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
サンプルを表示

サンプルを試す

カスタム パノラマのプロバイダは、渡されたパノラマ ID、ズームレベル、パノラマタイル座標が付与された適切なタイルを返します。画像の選択はこれらの渡される値に依存するため、これらの渡される値を使って、pano_zoom_tileX_tileY.png などの名前を画像に付けると、プログラムで選択するときに便利です。

次の例では、デフォルトのストリートビューのナビゲーション矢印以外に、Google シドニー オフィスを指す別の矢印とカスタム画像へのリンクを画像に追加しています。

TypeScript

let panorama: google.maps.StreetViewPanorama;

// StreetViewPanoramaData of a panorama just outside the Google Sydney office.
let outsideGoogle: google.maps.StreetViewPanoramaData;

// StreetViewPanoramaData for a custom panorama: the Google Sydney reception.
function getReceptionPanoramaData(): google.maps.StreetViewPanoramaData {
  return {
    location: {
      pano: "reception", // The ID for this custom panorama.
      description: "Google Sydney - Reception",
      latLng: new google.maps.LatLng(-33.86684, 151.19583),
    },
    links: [
      {
        heading: 195,
        description: "Exit",
        pano: (outsideGoogle.location as google.maps.StreetViewLocation).pano,
      },
    ],
    copyright: "Imagery (c) 2010 Google",
    tiles: {
      tileSize: new google.maps.Size(1024, 512),
      worldSize: new google.maps.Size(2048, 1024),
      centerHeading: 105,
      getTileUrl: function (
        pano: string,
        zoom: number,
        tileX: number,
        tileY: number
      ): string {
        return (
          "https://developers.google.com/maps/documentation/javascript/examples/full/images/" +
          "panoReception1024-" +
          zoom +
          "-" +
          tileX +
          "-" +
          tileY +
          ".jpg"
        );
      },
    },
  };
}

function initPanorama() {
  panorama = new google.maps.StreetViewPanorama(
    document.getElementById("street-view") as HTMLElement,
    { pano: (outsideGoogle.location as google.maps.StreetViewLocation).pano }
  );
  // Register a provider for the custom panorama.
  panorama.registerPanoProvider(
    (pano: string): google.maps.StreetViewPanoramaData => {
      if (pano === "reception") {
        return getReceptionPanoramaData();
      }
      // @ts-ignore TODO fix typings
      return null;
    }
  );

  // Add a link to our custom panorama from outside the Google Sydney office.
  panorama.addListener("links_changed", () => {
    if (
      panorama.getPano() ===
      (outsideGoogle.location as google.maps.StreetViewLocation).pano
    ) {
      panorama.getLinks().push({
        description: "Google Sydney",
        heading: 25,
        pano: "reception",
      });
    }
  });
}

function initMap(): void {
  // Use the Street View service to find a pano ID on Pirrama Rd, outside the
  // Google office.
  new google.maps.StreetViewService()
    .getPanorama({ location: { lat: -33.867386, lng: 151.195767 } })
    .then(({ data }: google.maps.StreetViewResponse) => {
      outsideGoogle = data;
      initPanorama();
    });
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

let panorama;
// StreetViewPanoramaData of a panorama just outside the Google Sydney office.
let outsideGoogle;

// StreetViewPanoramaData for a custom panorama: the Google Sydney reception.
function getReceptionPanoramaData() {
  return {
    location: {
      pano: "reception", // The ID for this custom panorama.
      description: "Google Sydney - Reception",
      latLng: new google.maps.LatLng(-33.86684, 151.19583),
    },
    links: [
      {
        heading: 195,
        description: "Exit",
        pano: outsideGoogle.location.pano,
      },
    ],
    copyright: "Imagery (c) 2010 Google",
    tiles: {
      tileSize: new google.maps.Size(1024, 512),
      worldSize: new google.maps.Size(2048, 1024),
      centerHeading: 105,
      getTileUrl: function (pano, zoom, tileX, tileY) {
        return (
          "https://developers.google.com/maps/documentation/javascript/examples/full/images/" +
          "panoReception1024-" +
          zoom +
          "-" +
          tileX +
          "-" +
          tileY +
          ".jpg"
        );
      },
    },
  };
}

function initPanorama() {
  panorama = new google.maps.StreetViewPanorama(
    document.getElementById("street-view"),
    { pano: outsideGoogle.location.pano },
  );
  // Register a provider for the custom panorama.
  panorama.registerPanoProvider((pano) => {
    if (pano === "reception") {
      return getReceptionPanoramaData();
    }
    // @ts-ignore TODO fix typings
    return null;
  });
  // Add a link to our custom panorama from outside the Google Sydney office.
  panorama.addListener("links_changed", () => {
    if (panorama.getPano() === outsideGoogle.location.pano) {
      panorama.getLinks().push({
        description: "Google Sydney",
        heading: 25,
        pano: "reception",
      });
    }
  });
}

function initMap() {
  // Use the Street View service to find a pano ID on Pirrama Rd, outside the
  // Google office.
  new google.maps.StreetViewService()
    .getPanorama({ location: { lat: -33.867386, lng: 151.195767 } })
    .then(({ data }) => {
      outsideGoogle = data;
      initPanorama();
    });
}

window.initMap = initMap;

CSS

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#street-view {
  height: 100%;
}

HTML

<html>
  <head>
    <title>Custom Street View Panorama Tiles</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="street-view"></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>
サンプルを表示

サンプルを試す