Servicio de Street View

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Descripción general

Seleccionar plataforma: Android iOS JavaScript

Google Street View proporciona vistas panorámicas de 360 grados de rutas designadas en su área de cobertura. La cobertura de la API de Street View es la misma que para la aplicación de Google Maps (https://maps.google.com/). La lista de ciudades que admite Street View está disponible en el sitio web de Google Maps.

A continuación, se muestra una imagen de Street View.


La API de Maps JavaScript proporciona un servicio de Street View para obtener y manipular las imágenes que se usan en Street View de Google Maps. Este servicio de Street View es compatible de forma nativa con el navegador.

Uso de mapas de Street View

Si bien Street View se puede usar dentro de un elemento de DOM independiente, resulta muy útil para indicar una ubicación en un mapa. De manera predeterminada, Street View está habilitado en un mapa, y aparece un control del hombrecito naranja en la vista de navegación (zoom y desplazamiento lateral). Puedes ocultar este control dentro del MapOptions del mapa si estableces streetViewControl en false. También puedes cambiar la posición predeterminada del control de Street View si configuras la propiedad streetViewControlOptions.position de Map en un nuevo ControlPosition.

El control del hombrecito naranja de Street View te permite ver panoramas de Street View directamente dentro del mapa. Cuando el usuario mantiene presionado el hombrecito naranja, el mapa se actualiza para mostrar contornos azules alrededor de las calles con Street View habilitado, lo que ofrece una experiencia del usuario similar a la de la app de Google Maps.

Cuando el usuario suelta el marcador del Pegman en una calle, el mapa se actualiza para mostrar una panorámica de Street View de la ubicación indicada.

Panorámicas de Street View

Las imágenes de Street View se admiten mediante el objeto StreetViewPanorama, que proporciona una interfaz de API a un visor de Street View. Cada mapa contiene un panorama predeterminado de Street View, que puedes recuperar llamando al método getStreetView() del mapa. Cuando se agrega un control de Street View al mapa mediante la configuración de la opción streetViewControl en true, se conecta automáticamente el control del hombrecito naranja a esta panorámica predeterminada de Street View.

También puedes crear tu propio objeto StreetViewPanorama y configurar el mapa para que lo utilice en lugar del valor predeterminado. Para ello, establece explícitamente la propiedad streetView del mapa en ese objeto construido. Es posible que desees anular el panorama predeterminado si deseas modificar su comportamiento predeterminado, como el uso compartido automático de superposiciones entre el mapa y el panorama. (Consulta Superposiciones en Street View a continuación).

Contenedores de Street View

Como alternativa, puedes mostrar un StreetViewPanorama dentro de un elemento DOM independiente, que suele ser un elemento <div>. Solo pasa el elemento DOM dentro del constructor de StreetViewPanorama. Para que la visualización de las imágenes sea óptima, se recomienda un tamaño mínimo de 200 x 200 píxeles.

Nota: Si bien la funcionalidad de Street View está diseñada para usarse en conjunto con un mapa, este uso no es obligatorio. Puedes usar un objeto independiente de Street View sin un mapa.

Ubicaciones y punto de vista (POV) de Street View

El constructor StreetViewPanorama también te permite establecer la ubicación y el punto de vista de Street View mediante el parámetro StreetViewOptions. Puedes llamar a setPosition() y setPov() en el objeto después de la construcción para cambiar su ubicación y punto de vista.

La ubicación de Street View define la ubicación del enfoque de la cámara para una imagen, pero no define la orientación de la cámara para esa imagen. Para ese propósito, el objeto StreetViewPov define dos propiedades:

  • heading (valor predeterminado de 0) define el ángulo de rotación alrededor del sitio de la cámara en grados relativos al norte geográfico. Los encabezados se miden en sentido horario (el punto de 90 grados corresponde al este verdadero).
  • pitch (valor predeterminado de 0) define la variación de ángulo “hacia arriba” o “hacia abajo” a partir de la inclinación predeterminada inicial de la cámara, que a menudo (no siempre) es horizontal y plana. (Por ejemplo, una imagen tomada en una colina posiblemente exhiba una inclinación predeterminada que no es horizontal). Los ángulos de inclinación se miden con valores positivos que apuntan hacia arriba (hasta +90 grados en línea recta hacia arriba y ortogonales respecto de la inclinación predeterminada) y valores negativos que apuntan hacia abajo (hasta -90 grados en línea recta hacia abajo y ortogonales respecto de la inclinación predeterminada).

El objeto StreetViewPov se usa con mayor frecuencia para determinar el punto de vista de la cámara de Street View. También puedes determinar el punto de vista del fotógrafo (por lo general, la dirección en la que se encontraba el automóvil o la bicicleta) con el método StreetViewPanorama.getPhotographerPov().

El siguiente código muestra un mapa de Boston con una vista inicial del parque Fenway. Si seleccionas el hombrecito naranja y lo arrastras a una ubicación compatible en el mapa, se cambiará la panorámica de Street View:

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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <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 callback 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
     with https://www.npmjs.com/package/@googlemaps/js-api-loader.
    -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initialize&v=weekly"
      defer
    ></script>
  </body>
</html>
Ver ejemplo

Probar la muestra

Rastreo de movimiento en dispositivos móviles

En los dispositivos que admiten eventos de orientación del dispositivo, la API ofrece a los usuarios la capacidad de cambiar el punto de vista de Street View en función del movimiento del dispositivo. Los usuarios pueden echar un vistazo moviendo sus dispositivos. Esto se denomina seguimiento de movimiento o de dispositivo.

Como desarrollador de apps, puedes cambiar el comportamiento predeterminado de la siguiente manera:

  • Habilitar o inhabilitar la funcionalidad del rastreo de movimiento. De forma predeterminada, el rastreo de movimiento está habilitado en cualquier dispositivo que lo admita. En el siguiente ejemplo, se inhabilita el seguimiento de movimiento, pero se deja visible el control. (Ten en cuenta que el usuario puede activar el rastreo de movimiento tocando el control).
    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTracking: false
        });
    
  • Oculta o muestra el control de rastreo de movimiento. De forma predeterminada, el control se muestra en dispositivos que admiten el rastreo de movimiento. El usuario puede presionar el control para activar o desactivar el seguimiento de movimiento. Ten en cuenta que el control nunca aparecerá si el dispositivo no admite el rastreo de movimiento, independientemente del valor de motionTrackingControl.

    En el siguiente ejemplo, se inhabilitan el seguimiento y el control de movimiento. En este caso, el usuario no puede activar el seguimiento de movimiento:

    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
        });
    
  • Cambiar la posición predeterminada del control de rastreo de movimiento. De manera predeterminada, el control aparece cerca de la parte inferior derecha del panorama (posición RIGHT_BOTTOM). En el siguiente ejemplo, se establece la posición del control en la parte inferior izquierda:
    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
          }
        });
    
    .

Para ver el seguimiento de movimiento en acción, consulta el siguiente ejemplo en un dispositivo móvil (o cualquier dispositivo que admita eventos de orientación):


Ver ejemplo

Superposiciones dentro de Street View

El objeto StreetViewPanorama predeterminado admite la visualización nativa de superposiciones de mapas. Las superposiciones generalmente aparecen a nivel de la “calle” en LatLng posiciones. (por ejemplo, los marcadores aparecerán con las colas ancladas en el plano horizontal de la ubicación dentro de la panorámica de Street View).

Actualmente, los tipos de superposiciones compatibles con las panorámicas de Street View se limitan a Marker, InfoWindow y OverlayView personalizados. Las superposiciones que se muestran en un mapa se pueden mostrar en una panorámica de Street View si se trata la panorámica como sustituto del objeto Map, se llama a setMap() y se pasa StreetViewPanorama como argumento en lugar de mapa. De manera similar, es posible abrir ventanas de información dentro de una panorámica de Street View llamando a open() y pasando StreetViewPanorama() en lugar de un mapa.

Además, cuando se crea un mapa con un objeto StreetViewPanorama predeterminado, los marcadores que se crean en este se comparten automáticamente con el panorama de Street View asociado del mapa, siempre que sea visible el panorama. Para recuperar la panorámica de Street View predeterminada, llama a getStreetView() en el objeto Map. Ten en cuenta que, si estableces explícitamente la propiedad streetView del mapa en un StreetViewPanorama de tu propia construcción, se anulará el panorama predeterminado.

En el siguiente ejemplo, se muestran marcadores que denotan varias ubicaciones alrededor de Astor Place, Nueva York. Activa o desactiva la visualización en Street View para que se muestren los marcadores compartidos que aparecen dentro de 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);

  // Set up the markers on the map
  const cafeMarker = new google.maps.Marker({
    position: { lat: 40.730031, lng: -73.991428 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=cafe|FFFF00",
    title: "Cafe",
  });

  const bankMarker = new google.maps.Marker({
    position: { lat: 40.729681, lng: -73.991138 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=dollar|FFFF00",
    title: "Bank",
  });

  const busMarker = new google.maps.Marker({
    position: { lat: 40.729559, lng: -73.990741 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=bus|FFFF00",
    title: "Bus Stop",
  });

  // 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);

  // Set up the markers on the map
  const cafeMarker = new google.maps.Marker({
    position: { lat: 40.730031, lng: -73.991428 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=cafe|FFFF00",
    title: "Cafe",
  });
  const bankMarker = new google.maps.Marker({
    position: { lat: 40.729681, lng: -73.991138 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=dollar|FFFF00",
    title: "Bank",
  });
  const busMarker = new google.maps.Marker({
    position: { lat: 40.729559, lng: -73.990741 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=bus|FFFF00",
    title: "Bus Stop",
  });

  // 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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <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 callback 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
     with https://www.npmjs.com/package/@googlemaps/js-api-loader.
    -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>
Ver ejemplo

Probar la muestra

Eventos de Street View

Cuando navegas entre Street View o manipulas su orientación, puedes supervisar varios eventos que indiquen cambios en el estado de StreetViewPanorama:

  • pano_changed se activa cada vez que cambia el ID de panorámica individual. Este evento no garantiza que los datos asociados dentro de la panorámica (como los vínculos) también hayan cambiado para el momento en que se active. Este evento solo indica que cambió un ID de panorámica. Ten en cuenta que el ID de panorámica (que puedes usar para hacer referencia a este panorama) solo es estable en la sesión actual del navegador.
  • position_changed se activa cada vez que cambia la posición subyacente (LatLng) del panorama. La rotación de un panorama no activará este evento. Ten en cuenta que puedes cambiar la posición subyacente de una panorámica sin cambiar el ID de panorámica asociado, ya que la API asociará automáticamente el ID de panorámica más cercano a la posición de panorámica.
  • pov_changed se activa cada vez que cambia el StreetViewPov de Street View. Ten en cuenta que este evento puede activarse mientras la posición y el ID de panorámica no se modifican.
  • links_changed se activa cada vez que cambian los vínculos de Street View. Ten en cuenta que este evento puede activarse de forma asíncrona después de un cambio en el ID de panorámica indicado a través de pano_changed.
  • visible_changed se activa cada vez que cambia la visibilidad de Street View. Ten en cuenta que este evento puede activarse de forma asíncrona después de un cambio en el ID de panorámica indicado a través de pano_changed.

En el siguiente código, se ilustra cómo se pueden controlar estos eventos para recopilar datos sobre el StreetViewPanorama subyacente:

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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <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 callback 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
     with https://www.npmjs.com/package/@googlemaps/js-api-loader.
    -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
Ver ejemplo

Probar la muestra

Controles de Street View

Cuando se muestra un objeto StreetViewPanorama, aparece una variedad de controles en el panorama de forma predeterminada. Puedes habilitar o inhabilitar estos controles si configuras los campos adecuados dentro de StreetViewPanoramaOptions en true o false:

  • Un elemento panControl proporciona una forma de rotar la panorámica. Este control aparece de forma predeterminada como un control integrado de brújula y desplazamiento estándar. Puedes modificar la posición del control si proporcionas PanControlOptions dentro del campo panControlOptions.
  • Un objeto zoomControl proporciona una forma de acercar la imagen. Este control aparece de manera predeterminada cerca de la parte inferior derecha del panorama. Puedes modificar el aspecto del control si proporcionas ZoomControlOptions dentro del campo zoomControlOptions.
  • Un elemento addressControl proporciona una superposición textual que indica la dirección de la ubicación asociada y un vínculo para abrir la ubicación en Google Maps. Puedes modificar el aspecto del control si proporcionas StreetViewAddressControlOptions dentro del campo addressControlOptions.
  • Un elemento fullscreenControl ofrece la opción de abrir Street View en modo de pantalla completa. Puedes modificar el aspecto del control si proporcionas FullscreenControlOptions dentro del campo fullscreenControlOptions.
  • Un objeto motionTrackingControl ofrece la opción de habilitar o inhabilitar el seguimiento de movimiento en dispositivos móviles. Este control solo aparece en dispositivos que admiten eventos de orientación de dispositivos. De forma predeterminada, el control aparece cerca de la parte inferior derecha del panorama. Puedes modificar la posición del control si proporcionas MotionTrackingControlOptions. Para obtener más información, consulta la sección sobre el seguimiento de movimiento.
  • Un linksControl proporciona flechas de guía en la imagen para viajar a imágenes panorámicas adyacentes.
  • Un control “Close” permite al usuario cerrar el visor de Street View. Puedes habilitar o inhabilitar el control de cierre si configuras enableCloseButton en true o false.

En el siguiente ejemplo, se alteran los controles que se muestran dentro de Street View asociado y se quitan los vínculos de la vista:

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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <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 callback 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
     with https://www.npmjs.com/package/@googlemaps/js-api-loader.
    -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
Ver ejemplo

Probar la muestra

Cómo acceder directamente a los datos de Street View

Es posible que desees determinar de manera programática la disponibilidad de datos de Street View o mostrar información sobre panoramas específicos, sin necesidad de manipular un mapa o panorama en forma directa. Puedes hacerlo mediante el objeto StreetViewService, que proporciona una interfaz para los datos almacenados en el servicio de Street View de Google.

Solicitudes de servicio de Street View

El acceso al servicio de Street View es asíncrono, ya que la API de Google Maps debe realizar una llamada a un servidor externo. Por esa razón, debes pasar un método de callback para la ejecución al completarse la solicitud. Este método de devolución de llamada procesa el resultado.

Puedes iniciar solicitudes a StreetViewService mediante StreetViewPanoRequest o StreetViewLocationRequest.

Una solicitud que usa StreetViewPanoRequest muestra datos panorámicos con un ID de referencia que identifica el panorama de manera única. Ten en cuenta que estos ID de referencia solo son estables durante la vida útil de las imágenes de esa panorámica.

Una solicitud que usa StreetViewLocationRequest busca datos de panorámica en una ubicación especificada, con los siguientes parámetros:

  • location especifica la ubicación (latitud y longitud) para buscar una panorámica.
  • preference establece una preferencia para determinar qué panorama debe encontrarse dentro del radio: el más cercano a la ubicación proporcionada o el mejor dentro del radio.
  • radius establece un radio, especificado en metros, en el que se busca un panorama, centrado en la latitud y longitud determinadas. La configuración predeterminada es 50 cuando no se proporciona.
  • source especifica el origen de las panorámicas que se buscarán. Los valores válidos son los siguientes:
    • default usa las fuentes predeterminadas de Street View; las búsquedas no se limitan a fuentes específicas.
    • outdoor limita las búsquedas a las colecciones al aire libre. Ten en cuenta que es posible que no existan panorámicas al aire libre para la ubicación especificada.

Respuestas del servicio de Street View

La función getPanorama() necesita una función de devolución de llamada para ejecutarse cuando se recupera un resultado del servicio de Street View. Esta función de devolución de llamada muestra un conjunto de datos panorámicos dentro de un objeto StreetViewPanoramaData y un código StreetViewStatus que denota el estado de la solicitud, en ese orden.

Una especificación del objeto StreetViewPanoramaData contiene metadatos sobre una panorámica de Street View con el siguiente formato:

{
  "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
  }
}

Ten en cuenta que este objeto de datos no es un objeto StreetViewPanorama en sí mismo. Para crear un objeto de Street View con estos datos, deberás crear un StreetViewPanorama, llamar a setPano() y pasar el ID como se indica en el campo location.pano que se muestra.

El código status puede mostrar uno de los siguientes valores:

  • OK indica que el servicio encontró una panorámica coincidente.
  • ZERO_RESULTS indica que el servicio no pudo encontrar una panorámica coincidente con los criterios pasados.
  • UNKNOWN_ERROR indica que no se pudo procesar una solicitud de Street View, aunque se desconoce el motivo exacto.

El siguiente código crea un StreetViewService que responde a los clics del usuario en un mapa creando marcadores que, al hacer clic en ellos, muestran un StreetViewPanorama de esa ubicación. El código usa el contenido de StreetViewPanoramaData que muestra el servicio.

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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <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 callback 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
     with https://www.npmjs.com/package/@googlemaps/js-api-loader.
    -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>
Ver ejemplo

Probar la muestra

Cómo proporcionar panoramas de Street View personalizados

La API de Maps JavaScript admite la visualización de panoramas personalizados dentro del objeto StreetViewPanorama. Con panoramas personalizados, puedes mostrar el interior de edificios, vistas desde ubicaciones panorámicas o cualquier cosa que se te ocurra. Incluso puedes vincular estas panorámicas personalizadas con las panorámicas existentes de Street View de Google.

Para configurar un conjunto de imágenes panorámicas personalizadas, se deben seguir estos pasos:

  • Crea una imagen panorámica básica para cada panorama personalizado. Esta imagen base debe tener la resolución más alta con la que desees entregar imágenes ampliadas.
  • (Opcional, pero recomendado) Crea un conjunto de mosaicos panorámicos a diferentes niveles de zoom a partir de la imagen básica.
  • Crea vínculos entre tus panoramas personalizados.
  • (Opcional) Designa panoramas de "entrada" dentro de las imágenes existentes de Street View de Google y personaliza los vínculos hacia y desde el conjunto personalizado hasta el estándar.
  • Define metadatos para cada imagen panorámica dentro de un objeto StreetViewPanoramaData.
  • Implementa un método que determine las imágenes y los datos panorámicos personalizados y designa ese método como tu controlador personalizado dentro del objeto StreetViewPanorama.

En las secciones siguientes se explica el proceso.

Cómo crear panoramas personalizados:

Cada panorámica de Street View es una imagen o un conjunto de imágenes que proporciona una vista de 360 grados completa desde una sola ubicación. El objeto StreetViewPanorama usa imágenes que se ajustan a la proyección equirrectangular (Plate Carrée). Esta proyección contiene 360 grados de vista horizontal (vista envolvente completa) y 180 grados de vista vertical (del extremo superior al extremo inferior). Estos campos de vista dan como resultado una imagen con una relación de aspecto de 2:1. A continuación, se muestra una panorámica completa completa.

Por lo general, las imágenes panorámicas se obtienen al tomar varias fotos de una posición y unirlas con un software de panorámicas. (Para obtener más información, consulta Wikipedia sobre la comparación de aplicaciones de unión de fotos). Estas imágenes deben compartir una ubicación única de la cámara a partir de la cual se toma cada imagen panorámica. Luego, el panorama a 360 grados puede definir una proyección en una esfera con la imagen ajustada a la superficie bidimensional de la esfera.

Tratar el panorama como una proyección en una esfera con un sistema de coordenadas rectilíneas resulta beneficioso al dividir la imagen en mosaicos rectilíneos y entregar imágenes basadas en coordenadas de mosaicos computadas.

Cómo crear mosaicos de panoramas personalizados

Street View también admite diferentes niveles de detalles de la imagen mediante el uso de un control de zoom, que te permite acercar y alejar la imagen desde la vista predeterminada. En general, Street View proporciona cinco niveles de resolución de zoom para cualquier imagen panorámica específica. Si dependas de una sola imagen panorámica para entregar todos los niveles de zoom, esta imagen necesariamente será bastante grande y reducirá considerablemente la velocidad de la aplicación, o tendrá una resolución tan baja a niveles de zoom más altos que se mostrará una imagen pixelada. Afortunadamente, sin embargo, podemos usar un patrón de diseño similar que se usa para mostrar mosaicos de mapas de Google en diferentes niveles de zoom a fin de proporcionar imágenes con una resolución adecuada para panoramas en cada nivel de zoom.

Cuando se carga un StreetViewPanorama por primera vez, de manera predeterminada, muestra una imagen que comprende un 25% (90 grados de arco) de la amplitud horizontal del panorama en el nivel de zoom 1. Esta vista corresponde aproximadamente con un campo visual normal. Alejar la imagen desde esta vista predeterminada proporciona esencialmente un arco más amplio, mientras que al acercarla se reduce el campo de una vista a un arco más pequeño. StreetViewPanorama calcula automáticamente el campo visual apropiado para el nivel de zoom seleccionado y, luego, selecciona las imágenes más adecuadas para esa resolución seleccionando un conjunto de mosaicos que coincida de manera aproximada con las dimensiones del campo visual horizontal. Los siguientes campos de vistas se asignan a los niveles de zoom de Street View:

Nivel de zoom de Street View Campo visual (grados)
0 180
1 (predeterminado) 90
2 45
3 22.5
4 11,25

Ten en cuenta que el tamaño de la imagen que se muestra dentro de Street View depende por completo del tamaño de la pantalla (ancho) del contenedor de Street View. Si proporcionas un contenedor más amplio, el servicio seguirá proporcionando el mismo campo de visión para cualquier nivel de zoom determinado, aunque puede seleccionar mosaicos más apropiados para esa resolución.

Debido a que cada panorama consiste en una proyección equirrectangular, crear mosaicos de panoramas es relativamente fácil. Como la proyección proporciona una imagen con una relación de aspecto de 2:1, los mosaicos con relaciones de 2:1 son más fáciles de usar, aunque los mosaicos cuadrados pueden proporcionar un mejor rendimiento en los mapas cuadrados (ya que el campo de visión será cuadrado).

En el caso de los mosaicos con relación de aspecto de 2:1, una sola imagen que abarca todo el panorama representa todo el panorama (la imagen base) en el nivel de zoom 0, y cada nivel de zoom en aumento ofrece cuatro mosaicos de zoomLevel. (p.ej., en el nivel de zoom 2, toda la panorámica consta de 16 mosaicos). Nota: Los niveles de zoom en la vista de Street View no coinciden directamente con los niveles de zoom proporcionados mediante el control de Street View. En cambio, los niveles de zoom del control de Street View seleccionan un campo de visión (FoV) desde el que se seleccionan los mosaicos adecuados.

En general, se recomienda asignar un nombre a los mosaicos de imágenes para que puedan seleccionarse de manera programática. Este esquema de nombres se analiza a continuación en Cómo manejar solicitudes de panoramas personalizados.

Administración de solicitudes de panoramas personalizados

Para usar una panorámica personalizada, llama a StreetViewPanorama.registerPanoProvider() y especifica el nombre de tu método de proveedor de panoramas personalizados. El método del proveedor de panoramas debe mostrar un objeto StreetViewPanoramaData y tiene la siguiente firma:

Function(pano):StreetViewPanoramaData

Un StreetViewPanoramaData es un objeto que tiene la siguiente forma:

{
  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
  ]
}

Muestra una panorámica personalizada de la siguiente manera:

  • Establece la propiedad StreetViewPanoramaOptions.pano en un valor personalizado.
  • Llama a StreetViewPanorama.registerPanoProvider() para proporcionar una función de proveedor de panoramas personalizados.
  • Implementa la función de proveedor de panoramas personalizados para controlar el valor pano especificado.
  • Construye un objeto StreetViewPanoramaData.
  • Establece la propiedad StreetViewTileData.getTileUrl con el nombre de una función de proveedor de mosaicos personalizados que proporciones. Por ejemplo, getCustomPanoramaTileUrl.
  • Implementa la función de proveedor de mosaicos personalizados, como se muestra en los siguientes ejemplos.
  • Muestra el objeto StreetViewPanoramaData.

Nota: No configures directamente un elemento position en StreetViewPanorama cuando quieras mostrar panoramas personalizados, ya que una posición de este tipo le indicará al servicio de Street View que solicite las imágenes de Street View predeterminadas cercanas a esa ubicación. En su lugar, establece esta posición en el campo location.latLng personalizado del objeto StreetViewPanoramaData.

En el siguiente ejemplo, se muestra una panorámica personalizada de la oficina de Google en Sídney. Ten en cuenta que en este ejemplo no se utiliza un mapa ni imágenes predeterminadas de Street View:

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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <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 callback 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
     with https://www.npmjs.com/package/@googlemaps/js-api-loader.
    -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
Ver ejemplo

Probar la muestra

El proveedor de panoramas personalizados muestra el mosaico correspondiente con las coordenadas de mosaico de panorámicas, el ID de panorama y el nivel de zoom aprobados. Dado que la selección de imágenes depende de estos valores pasados, es útil nombrar imágenes que se puedan seleccionar de manera programática a partir de esos valores, como pano_zoom_tileX_tileY.png.

En el siguiente ejemplo, se agrega otra flecha a la imagen, además de las flechas de navegación predeterminadas de Street View, que apunta a Google Sídney y se vincula a las imágenes personalizadas:

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",
      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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <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 callback 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
     with https://www.npmjs.com/package/@googlemaps/js-api-loader.
    -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>
Ver ejemplo

Probar la muestra