Servicio de Street View

Descripción general

Selecciona la 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 la de la aplicación de Google Maps (https://maps.google.com/). La lista de ciudades admitidas de Street View está disponible en el sitio web de Google Maps.

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


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

Uso de mapas de Street View

Si bien Street View puede usarse en un elemento independiente del DOM , es más útil para indicar una ubicación en un mapa. De manera predeterminada, Street View está habilitado en el mapa y muestra un control de hombrecito naranja integrado en los controles de navegación (zoom y desplazamiento lateral). Puedes ocultar este control en el MapOptions del mapa si estableces streetViewControl en false. También puedes cambiar la posición predeterminada del control de Street View; para ello, configura la propiedad streetViewControlOptions.position de Map en un nuevo ControlPosition.

El control del hombrecito naranja de Street View te permite ver panorámicas de Street View directamente en el mapa. Cuando el usuario mantiene presionado el hombrecito naranja, el mapa se actualiza y muestra líneas azules en las calles donde Street View está habilitado. Esto ofrece al usuario una experiencia similar a la que brinda la app de Google Maps.

Cuando el usuario suelta el marcador del hombrecito naranja en una calle, el mapa se actualiza y muestra una panorámica de Street View de la ubicación indicada.

Panorámicas de Street View

Se admiten imágenes de Street View mediante el objeto StreetViewPanorama, que proporciona una interfaz de API a un "visor" de Street View. Cada mapa contiene una panorámica predeterminada de Street View, que puedes recuperar llamando al método getStreetView() del mapa. Si configuras la opción streetViewControl en true para agregar un control de Street View al mapa, el control del hombrecito naranja se conectará automáticamente a esa panorámica predeterminada de Street View.

También puedes crear tu propio objeto StreetViewPanorama y configurar el mapa para que use este elemento en lugar del objeto predeterminado; para ello, debes establecer de manera explícita la propiedad streetView del mapa en ese objeto construido. Es posible que quieras anular la panorámica predeterminada si deseas modificar el comportamiento predeterminado, como el uso compartido automático de superposiciones entre el mapa y la panorámica. (Consulta la sección Superposiciones en Street View a continuación).

Contenedores de Street View

Como alternativa, es posible que desees mostrar un StreetViewPanorama dentro de un elemento del DOM independiente, que suele ser un elemento <div>. Para ello, solo debes pasar el elemento del DOM en el constructor de StreetViewPanorama. Para que la visualización de las imágenes sea óptima, recomendamos un tamaño mínimo de 200 x 200 píxeles.

Nota: Si bien la funcionalidad de Street View está diseñada para utilizarse junto con un mapa, esta implementación no es necesaria. Puedes usar un objeto de Street View independiente sin un mapa.

Ubicaciones y punto de vista (POV) de Street View

El constructor de StreetViewPanorama también te permite configurar la ubicación y el punto de vista de Street View usando 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 POV.

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

  • heading (valor predeterminado de 0) define el ángulo de rotación en grados alrededor de la ubicación de la cámara respecto del norte geográfico. Las orientaciones se miden en el sentido de las manecillas del reloj (el punto de 90 grados representa el este geográfico).
  • pitch (valor predeterminado de 0) define la variación del ángulo "hacia arriba" o "hacia abajo" a partir de la inclinación inicial predeterminada 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 sea 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 (en 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 Fenway Park. Si seleccionas el hombrecito naranja y lo arrastras hasta una ubicación compatible en el mapa, 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 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>
Ver ejemplo

Prueba la muestra

Seguimiento de movimiento en dispositivos móviles

En los dispositivos que admiten eventos de orientación del dispositivo, la API ofrece a los usuarios la posibilidad de cambiar el punto de vista de Street View según el movimiento del dispositivo. Los usuarios pueden mirar los alrededores moviendo sus dispositivos. Esto se denomina seguimiento de movimiento o seguimiento de rotación del dispositivo.

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

  • Habilita o inhabilita la funcionalidad de seguimiento de movimiento. De forma predeterminada, el seguimiento de movimiento se encuentra habilitado en cualquier dispositivo que lo admita. En el siguiente ejemplo, se inhabilita el seguimiento de movimiento, pero se deja visible el control correspondiente. (Ten en cuenta que el usuario puede presionar el control para 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
        });
    
  • Oculta o muestra el control de seguimiento de movimiento. De forma predeterminada, el control se muestra en los dispositivos que admiten esta función. El usuario puede presionar el control para activar o desactivar el seguimiento de movimiento. Ten en cuenta que el control no se mostrará si el dispositivo no admite el seguimiento de movimiento, independientemente del valor de motionTrackingControl.

    En el siguiente ejemplo, se inhabilitan el seguimiento de movimiento y el control correspondiente. 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
        });
    
  • Cambia la posición predeterminada del control de seguimiento de movimiento. De forma predeterminada, el control aparece cerca de la parte inferior derecha de la panorámica (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, mira el siguiente ejemplo en un dispositivo móvil (o en cualquier dispositivo que admita eventos de orientación):


Ver ejemplo

Superposiciones en Street View

El objeto StreetViewPanorama predeterminado admite la visualización nativa de superposiciones en el mapa. Las superposiciones generalmente aparecen a "nivel de la calle", ancladas en posiciones de LatLng. (Por ejemplo, los marcadores aparecerán con los extremos anclados en el plano horizontal de la ubicación en la panorámica de Street View).

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

Además, cuando se crea un mapa con una StreetViewPanorama predeterminada, los marcadores generados allí se comparten automáticamente con la panorámica de Street View asociada al mapa, siempre que la panorámica sea visible. Para recuperar la panorámica predeterminada de Street View, llama a getStreetView() en el objeto Map. Ten presente que, si configuras explícitamente la propiedad streetView del mapa en una StreetViewPanorama que hayas construido por tu cuenta, se anulará la panorámica predeterminada.

En el siguiente ejemplo, se muestran marcadores que indican varias ubicaciones en Astor Place, Nueva York. Activa la visualización en Street View para que se muestren los marcadores compartidos que aparecen en 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>
    <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 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>
Ver ejemplo

Prueba la muestra

Eventos de Street View

Al navegar por Street View o manipular su orientación, es posible que quieras controlar varios eventos que indiquen cambios en el estado de StreetViewPanorama:

  • pano_changed se activa cada vez que cambia el ID individual de la panorámica. Este evento no garantiza que también cambien los datos asociados dentro de la panorámica (como los vínculos) cuando se activa el evento. Solo indica el cambio de un ID de panorámica. Ten en cuenta que el ID de panorámica (que puedes usar para hacer referencia a esta panorámica) solo es estable en la sesión actual del navegador.
  • position_changed se activa cada vez que cambia la posición subyacente (LatLng) de la panorámica. La rotación de una panorámica no activará este evento. Ten en cuenta que podrías cambiar la posición subyacente de una panorámica sin modificar el ID de panorámica asociado, ya que la API asociará de manera automática el ID de la panorámica más cercano a su posición.
  • 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 permanecen estables.
  • 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 que se indica 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 que se indica a través de pano_changed.

En el siguiente código, se muestra cómo se pueden controlar estos eventos para recopilar datos sobre el objeto 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 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>
Ver ejemplo

Prueba la muestra

Controles de Street View

Cuando se muestra un objeto StreetViewPanorama, aparecen varios controles en la panorámica de forma predeterminada. Para habilitar o inhabilitar estos controles, configura los campos correspondientes de StreetViewPanoramaOptions como true o false:

  • Un objeto panControl proporciona una forma de rotar la panorámica. Este control aparece de forma predeterminada como un control estándar integrado de brújula y desplazamiento lateral. Puedes modificar la posición del control si proporcionas PanControlOptions en el campo panControlOptions.
  • Un objeto zoomControl proporciona una forma de hacer zoom en la imagen. Este control aparece de forma predeterminada cerca de la esquina inferior derecha de la panorámica. Puedes modificar el aspecto del control si proporcionas ZoomControlOptions en el campo zoomControlOptions.
  • Un objeto addressControl proporciona una superposición textual que indica la dirección de la ubicación asociada y ofrece un vínculo para abrir la ubicación en Google Maps. Puedes modificar el aspecto del control si proporcionas StreetViewAddressControlOptions en el campo addressControlOptions.
  • Un objeto fullscreenControl ofrece la opción de abrir Street View en el modo de pantalla completa. Puedes modificar el aspecto del control si proporcionas FullscreenControlOptions en el campo fullscreenControlOptions.
  • Un objeto motionTrackingControl ofrece la opción de habilitar o inhabilitar el seguimiento de movimiento en dispositivos móviles. Este control solo se muestra en los dispositivos que admiten eventos de orientación. De forma predeterminada, el control aparece cerca de la esquina inferior derecha de la panorámica. 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 objeto linksControl proporciona flechas de guía en la imagen para desplazarse a imágenes panorámicas adyacentes.
  • El control "Cerrar" permite al usuario cerrar el visor de Street View. Puedes habilitar o inhabilitar el control de cierre si configuras enableCloseButton como true o false.

En el siguiente ejemplo, se modifican los controles que se muestran en la imagen Street View asociada 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 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>
Ver ejemplo

Prueba 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 determinadas panorámicas, sin la necesidad de manipular un mapa o una panorámica de forma directa. Puedes hacerlo usando 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 ese motivo, debes pasar un método de devolución de llamada para la ejecución una vez que se complete la solicitud. Este método de devolución de llamada procesa el resultado.

Puedes iniciar solicitudes a StreetViewService usando StreetViewPanoRequest o StreetViewLocationRequest.

Una solicitud que usa StreetViewPanoRequest muestra datos de una panorámica con un ID de referencia que identifica la panorámica de manera exclusiva. Ten en cuenta que estos IDs 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 una 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é panorámica debe encontrarse dentro del radio: la más cercana a la ubicación proporcionada o la mejor dentro del radio.
  • radius establece un radio, especificado en metros, en el que se debe buscar una panorámica, según la latitud y longitud determinadas. El valor predeterminado 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 de panorámica en 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. Para crear un objeto de Street View con estos datos, deberás crear una StreetViewPanorama, llamar a setPano() y pasar el ID como se indica en el campo location.pano que se devuelve.

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

  • OK indica que el servicio encontró una panorámica que coincide.
  • ZERO_RESULTS indica que el servicio no pudo encontrar una panorámica que coincida con los criterios que se pasaron.
  • 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 de los usuarios en un mapa mediante la creación de marcadores que, una vez seleccionados, muestran una 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 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>
Ver ejemplo

Prueba la muestra

Cómo proporcionar panorámicas de Street View personalizadas

La API de Maps JavaScript admite la visualización de panorámicas personalizadas en el objeto StreetViewPanorama. Mediante panorámicas personalizados, puedes mostrar el interior de edificios, vistas de lugares pintorescos o lo que se te ocurra. Puedes incluso vincular estas panorámicas a panorámicas existentes de Street View de Google.

Para configurar una panorámica personalizada, sigue estos pasos:

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

En las secciones siguientes se explica el proceso.

Cómo crear panorámicas personalizadas

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

Vista panorámica de una calle

Para obtener imágenes panorámicas, generalmente se toman varias fotos desde una posición y se las une con software que permite generar estas vistas. (Para obtener más información, consulta la comparación de aplicaciones de unión de fotos de Wikipedia). Estas imágenes deben compartir la misma ubicación de la "cámara", desde la cual se toma cada imagen panorámica. La panorámica de 360 grados que se obtiene define una proyección en una esfera con la imagen ajustada a la superficie bidimensional de la esfera.

Esfera en cuya superficie se muestra la vista panorámica de una calle

Tratar la panorámica como una proyección en una esfera con un sistema de coordenadas rectilíneas es conveniente para dividir la imagen en mosaicos rectilíneos y proporcionar imágenes basadas en coordenadas de mosaicos computadas.

Cómo crear mosaicos de panorámicas personalizadas

Street View también admite diferentes niveles de detalle de imágenes a través de un control de zoom, lo cual te permite acercar y alejar la vista predeterminada. En general, Street View proporciona cinco niveles de resolución de zoom para cualquier imagen panorámica. Si usaras una única imagen panorámica para todos los niveles de zoom, esta debería ser bastante grande, lo que reduciría el rendimiento de tu aplicación o, a niveles de zoom superiores, tendría una resolución tan baja que se vería con una calidad deficiente y pixelada. No obstante, podemos usar un patrón de diseño similar que se usa para mostrar mosaicos de mapas de Google en diferentes niveles de zoom y proporcionar imágenes panorámicas con una resolución adecuada en cada nivel de zoom.

Cuando se carga un objeto StreetViewPanorama por primera vez, de manera predeterminada, muestra una imagen que comprende un 25% (90 grados de arco) de la amplitud horizontal de la panorámica en el nivel de zoom 1. Esta vista corresponde, aproximadamente, al campo visual normal de los humanos. El alejamiento de esta vista predeterminada proporciona básicamente un arco más amplio, mientras que el acercamiento reduce el campo visual a un arco más pequeño. StreetViewPanorama calcula automáticamente el campo visual apropiado para el nivel de zoom seleccionado y, luego, elige las imágenes más adecuadas para esa resolución mediante la selección de un conjunto de mosaicos que coincida aproximadamente con las dimensiones del campo visual horizontal. Se asignan los siguientes campos visuales 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 en Street View depende totalmente del tamaño de la pantalla (ancho) del contenedor de Street View. Si proporcionas un contenedor más amplio, el servicio proporcionará el mismo campo visual para cualquier nivel de zoom. No obstante, puede seleccionar mosaicos más adecuados para esa resolución.

Debido a que cada panorámica se compone de una proyección equirrectangular, crear mosaicos de panorámicas es relativamente fácil. Dado que la proyección proporciona una imagen con una relación de aspecto de 2:1, resulta más sencillo usar mosaicos con la misma relación de aspecto, si bien los mosaicos cuadrados pueden tener un mejor rendimiento en mapas de ángulos rectos (ya que el campo visual será cuadrado).

En el caso de los mosaicos con una relación de aspecto de 2:1, una única imagen que abarca la panorámica completa representa todo el "mundo" de la panorámica (imagen básica) en el nivel de zoom 0 y, cada vez que aumenta el nivel de zoom, se ofrecen 4 mosaicos de nivel de zoom. (Por ejemplo, en el nivel de zoom 2, toda la panorámica consta de 16 mosaicos). Nota: Los niveles de zoom de mosaicos de Street View no coinciden directamente con los niveles de zoom proporcionados usando el control de Street View. En cambio, los niveles de zoom del control de Street View seleccionan un campo visual (FoV) a partir del cual se toman los mosaicos adecuados.

Vista panorámica de una calle de la ciudad dividida en mosaicos

En general, se recomienda asignar nombres a tus mosaicos de imágenes para que puedan seleccionarse de forma programática. Este esquema de asignación de nombres se analiza a continuación en la sección Cómo administrar las solicitudes de panorámicas personalizadas.

Cómo administrar las solicitudes de panorámicas personalizadas

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

Function(pano):StreetViewPanoramaData

Un StreetViewPanoramaData es un objeto que presenta 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:

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

Nota: No configures directamente una propiedad position en StreetViewPanorama cuando quieras mostrar panorámicas personalizadas, ya que esa posición le indicará al servicio de Street View que solicite las imágenes de Street View predeterminadas de lugares cercanos a esa ubicación. En su lugar, establece esta posición en el campo location.latLng del objeto StreetViewPanoramaData personalizado.

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 usa 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 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>
Ver ejemplo

Prueba la muestra

El proveedor de panorámicas personalizadas muestra el mosaico correspondiente según el ID de panorámica que se pasó, el nivel de zoom y las coordenadas del mosaico de la panorámica. Dado que la selección de imágenes depende de los valores que se pasaron, 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 la oficina de Google en 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", // 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>
    <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 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>
Ver ejemplo

Prueba la muestra