Serviço Street View

Visão geral

Selecione a plataforma: Android iOS JavaScript

O Google Street View oferece vistas panorâmicas de 360 graus de vias designadas em toda a área de cobertura. A cobertura da API Street View é igual à do aplicativo Google Maps (https://maps.google.com/). A lista de cidades atualmente compatíveis com o Street View está disponível no site do Google Maps.

Veja a seguir um exemplo de imagem do Street View.


A API Maps JavaScript oferece um serviço do Street View para recuperar e manipular imagens usadas no Street View do Google Maps. Este serviço do Street View tem suporte nativo no navegador.

Uso de mapas do Street View

Embora o Street View possa ser usado em um elemento DOM independente, ele é mais útil ao indicar um local em um mapa. Por padrão, o Street View é ativado em um mapa, e um controle Paegman do Street View é exibido integrado aos controles de navegação (zoom e panorâmica). Para ocultar esse controle no MapOptions do mapa, defina streetViewControl como false. Você também pode alterar a posição padrão do controle do Street View definindo a propriedade streetViewControlOptions.position de Map como um novo ControlPosition.

O controle do Pegman no Street View permite ver panoramas do Street View diretamente no mapa. Quando o usuário clica e segura o Pegman, o mapa é atualizado para mostrar contornos azuis em torno das ruas habilitadas para o Street View, oferecendo uma experiência de usuário similar à do aplicativo Google Maps.

Quando o usuário solta o marcador do Pegman em uma rua, o mapa é atualizado para exibir um panorama do Street View do local indicado.

Panoramas do Street View

As imagens do Street View são compatíveis com o uso do objeto StreetViewPanorama, que fornece uma interface de API a um "viewer." do Street View. Cada mapa contém um panorama padrão do Street View, que você pode recuperar chamando o método getStreetView() do mapa. Ao incluir um controle do Street View no mapa definindo a opção streetViewControl como true, você conecta automaticamente o controle do Pegman a este panorama padrão do Street View.

Você também pode criar seu próprio objeto StreetViewPanorama e definir o mapa para usar isso em vez do padrão, definindo explicitamente a propriedade streetView do mapa para esse objeto construído. Você pode substituir o panorama padrão se quiser modificar o comportamento padrão, como o compartilhamento automático de sobreposições entre o mapa e o panorama. Consulte Sobreposições no Street View abaixo.

Contêineres do Street View

Você pode exibir um StreetViewPanorama em um elemento DOM separado, geralmente um elemento <div>. Basta transmitir o elemento DOM no construtor do StreetViewPanorama. Para otimizar a exibição de imagens, recomendamos um tamanho mínimo de 200 pixels por 200 pixels.

Observação:embora o recurso do Street View tenha sido projetado para ser usado com um mapa, esse uso não é obrigatório. Você pode usar um objeto independente do Street View sem um mapa.

Localizações e ponto de vista (POV) do Street View

O construtor StreetViewPanorama também permite definir o local e o ponto de vista do Street View usando o parâmetro StreetViewOptions. Você pode chamar setPosition() e setPov() no objeto após a construção para alterar o local e o POV.

O local do Street View define o posicionamento do foco da câmera para uma imagem, mas não define a orientação da câmera para essa imagem. Para essa finalidade, o objeto StreetViewPov define duas propriedades:

  • heading (0 padrão) define o ângulo de rotação em torno do centro da câmera em graus em relação ao norte verdadeiro. Os títulos são medidos no sentido horário (90 graus é o leste verdadeiro).
  • pitch (0 padrão) define a variação do ângulo ""up" ou "down" do inclinação padrão inicial da câmera, que geralmente é, mas nem sempre, plano horizontal. Por exemplo, uma imagem capturada em uma colina provavelmente terá um valor padrão de inclinação não horizontal. Os ângulos de inclinação são medidos com valores positivos voltados para cima (até +90 graus diretamente para cima e ortogonal à inclinação padrão) e valores negativos para baixo (até -90 graus diretamente para baixo e ortogonal à inclinação padrão).

O objeto StreetViewPov é mais usado para determinar o ponto de vista da câmera do Street View. Você também pode determinar o ponto de vista do fotógrafo, normalmente a direção para onde o carro ou o triciclo estava voltado, com o método StreetViewPanorama.getPhotographerPov().

O código a seguir exibe um mapa de Boston com uma visualização inicial do Fenway Park. Selecionar o Pegman e arrastá-lo para um local suportado no mapa alterará o panorama do 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 exemplo

Testar amostra

Rastreamento de movimento em dispositivos móveis

Em dispositivos compatíveis com eventos de orientação, a API permite que os usuários mudem o ponto de vista do Street View com base no movimento do dispositivo. Os usuários podem olhar em volta movimentando os dispositivos. Isso é chamado de rastreamento de movimento ou de rotação de dispositivo.

Como desenvolvedor de aplicativos, você pode alterar o comportamento padrão da seguinte forma:

  • Ativar ou desativar a funcionalidade de rastreamento de movimento. O rastreamento de movimento é ativado por padrão em qualquer dispositivo compatível. O exemplo a seguir desativa o rastreamento de movimento, mas deixa o controle dele visível. (Observe que o usuário pode ativar o rastreamento de movimento tocando no controle.)
    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTracking: false
        });
    
  • Ocultar ou mostrar o controle de rastreamento de movimento. Por padrão, o controle é exibido em dispositivos compatíveis com o rastreamento de movimento. O usuário pode tocar no controle para ativar ou desativar o rastreamento de movimento. O controle nunca será exibido se o dispositivo não for compatível com o rastreamento de movimento, independentemente do valor de motionTrackingControl.

    O exemplo a seguir desativa o controle de movimento e o controle de rastreamento de movimento. Nesse caso, o usuário não consegue ativar o rastreamento de movimento em:

    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
        });
    
  • Alterar a posição padrão do controle de rastreamento de movimento. Por padrão, o controle aparece próximo ao canto inferior direito do panorama (posição RIGHT_BOTTOM). O exemplo a seguir define a posição do controle como a parte inferior esquerda:
    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 o rastreamento de movimento em ação, veja o exemplo a seguir em um dispositivo móvel ou em qualquer dispositivo compatível com eventos de orientação do dispositivo:


Ver exemplo

Sobreposições no Street View

O objeto StreetViewPanorama padrão é compatível com a exibição nativa de sobreposições do mapa. As sobreposições geralmente aparecem no "nível da rua" ancoradas em posições LatLng. Os marcadores serão exibidos com as caudas ancoradas no plano horizontal do local dentro do panorama do Street View, por exemplo.

Atualmente, os tipos de sobreposições compatíveis com panoramas do Street View são limitados a Markers, InfoWindows e OverlayViews personalizados. As sobreposições exibidas em um mapa podem ser exibidas em um panorama do Street View, tratando o panorama como um substituto do objeto Map, chamando setMap() e transmitindo StreetViewPanorama como um argumento, em vez de um mapa. Da mesma forma, as janelas de informações podem ser abertas em um panorama do Street View chamando open(), transmitindo o StreetViewPanorama() em vez de um mapa.

Além disso, ao criar um mapa com um StreetViewPanorama padrão, todos os marcadores criados em um mapa são compartilhados automaticamente com o panorama do Street View associado a ele, desde que o panorama seja visível. Para recuperar o panorama padrão do Street View, chame getStreetView() no objeto Map. Se você definir explicitamente a propriedade streetView do mapa como StreetViewPanorama da sua própria construção, modificará o panorama padrão.

O exemplo a seguir mostra marcadores que representam vários locais ao redor de Astor Place, Nova York. Alterne a exibição para o Street View para mostrar os marcadores compartilhados no 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 exemplo

Testar amostra

Eventos do Street View

Ao navegar entre os dados do Street View ou manipular a orientação dele, você pode querer monitorar vários eventos que indicam mudanças no estado de StreetViewPanorama:

  • pano_changed é acionado sempre que um ID de panorama individual muda. Este evento não garante que os dados associados no panorama (como os links) também tenham sido alterados no momento em que esse evento é acionado. Este evento indica apenas que um ID de panorama foi alterado. O ID do panorama (que você pode usar para referenciar esse panorama) só é estável na sessão atual do navegador.
  • position_changed é disparado sempre que a posição subjacente (LatLng) do panorama é alterada. A rotação de um panorama não acionará esse evento. É possível alterar a posição subjacente de um panorama sem alterar o ID do panorama associado, já que a API associa automaticamente o ID do panorama mais próximo à posição desse panorama.
  • pov_changed é acionado sempre que a StreetViewPov do Street View muda. Este evento pode ser disparado enquanto a posição e o ID do panorama permanecem estáveis.
  • links_changed é acionado sempre que os links do Street View mudam. Este evento pode ser disparado de forma assíncrona após uma alteração no ID do panorama indicada pelo pano_changed.
  • visible_changed é acionado sempre que a visibilidade do Street View é alterada. Este evento pode ser disparado de forma assíncrona após uma alteração no ID do panorama indicada pelo pano_changed.

O código a seguir ilustra como esses eventos podem ser processados para coletar dados sobre a StreetViewPanorama subjacente:

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 exemplo

Testar amostra

Controles do Street View

Ao exibir um StreetViewPanorama, vários controles aparecem no panorama por padrão. É possível ativar ou desativar esses controles definindo os campos apropriados no StreetViewPanoramaOptions como true ou false:

  • Uma panControl fornece uma maneira de girar o panorama. Esse controle é exibido por padrão como um controle integrado padrão de bússola e movimentação. É possível alterar a posição do controle fornecendo PanControlOptions no campo panControlOptions.
  • Uma zoomControl fornece uma maneira de aplicar zoom na imagem. Esse controle é exibido por padrão perto do canto inferior direito do panorama. É possível mudar a aparência dos controles fornecendo ZoomControlOptions no campo zoomControlOptions.
  • Um addressControl oferece uma sobreposição textual que indica o endereço do local associado e oferece um link para abrir o local no Google Maps. É possível mudar a aparência dos controles fornecendo StreetViewAddressControlOptions no campo addressControlOptions.
  • Uma fullscreenControl oferece a opção de abrir o Street View no modo de tela cheia. É possível mudar a aparência dos controles fornecendo FullscreenControlOptions no campo fullscreenControlOptions.
  • Um motionTrackingControl oferece a opção de ativar ou desativar o rastreamento de movimento em dispositivos móveis. Esse controle só aparece em dispositivos compatíveis com eventos de orientação. Por padrão, o controle aparece próximo ao canto inferior direito do panorama. É possível alterar a posição dos controles fornecendo MotionTrackingControlOptions. Para mais informações, consulte a seção sobre monitoramento de movimento.
  • Uma linksControl fornece setas de guia na imagem para viagens a imagens de panorama adjacentes.
  • Um controle Close permite que o usuário feche o visualizador do Street View. Para ativar ou desativar o controle de fechamento, defina enableCloseButton como true ou false.

O exemplo a seguir altera os controles exibidos no Street View associado e remove os links da 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 exemplo

Testar amostra

Acesso direto aos dados do Street View

Você pode determinar programaticamente a disponibilidade de dados do Street View ou retornar informações sobre panoramas específicos, sem precisar manipular diretamente um mapa/panorama. Você pode fazer isso usando o objeto StreetViewService, que fornece uma interface para os dados armazenados no serviço Street View do Google.

Solicitações do serviço Street View

O acesso ao serviço do Street View é assíncrono, já que a API Google Maps precisa fazer uma chamada para um servidor externo. Por isso, é necessário transmitir um método de callback para ser executado após a conclusão da solicitação. Esse método de callback processa o resultado.

É possível iniciar solicitações para StreetViewService usando StreetViewPanoRequest ou StreetViewLocationRequest.

Uma solicitação que usa StreetViewPanoRequest retorna dados do panorama com base em um ID de referência que o identifica exclusivamente. Observe que esses códigos de referência são estáveis apenas durante a vida útil das imagens desse panorama.

Uma solicitação usando StreetViewLocationRequest pesquisa dados de panoramas em um local especificado usando os seguintes parâmetros:

  • location especifica o local (latitude e longitude) para pesquisar um panorama.
  • preference define uma preferência para o panorama a ser encontrado no raio: o mais próximo do local fornecido ou o melhor dentro do raio.
  • radius define um raio, especificado em metros, no qual pesquisar um panorama, centralizado na latitude e longitude fornecidas. Quando não é informado, o padrão é 50.
  • source especifica a origem dos panoramas a serem pesquisados. Estes são os valores válidos:
    • default usa as fontes padrão do Street View. As pesquisas não são limitadas a origens específicas.
    • outdoor limita as pesquisas a coleções ao ar livre. e pode ser que não existam panoramas externos para o local especificado.

Respostas do serviço Street View

A função getPanorama() precisa de uma função de callback para ser executada após a recuperação de um resultado do serviço do Street View. Essa função de callback retorna um conjunto de dados de panorama dentro de um objeto StreetViewPanoramaData e um código StreetViewStatus que indica o status da solicitação, nessa ordem.

Uma especificação de objeto StreetViewPanoramaData contém metadados sobre um panorama do Street View da seguinte forma:

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

Observe que esse objeto de dados não é um objeto StreetViewPanorama. Para criar um objeto do Street View com esses dados, é necessário criar um StreetViewPanorama e chamar setPano(), passando o ID conforme observado no campo location.pano retornado.

O código status pode retornar um dos seguintes valores:

  • OK indica que o serviço encontrou um panorama correspondente.
  • ZERO_RESULTS indica que o serviço não encontrou um panorama correspondente aos critérios transmitidos.
  • UNKNOWN_ERROR indica que não foi possível processar uma solicitação do Street View, embora o motivo exato seja desconhecido.

O código a seguir cria um StreetViewService que responde a cliques do usuário em um mapa criando marcadores que, quando clicados, exibem um StreetViewPanorama desse local. O código usa o conteúdo de StreetViewPanoramaData retornado do serviço.

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 exemplo

Testar amostra

Fornecer panoramas personalizados do Street View

A API Maps JavaScript é compatível com a exibição de panoramas personalizados no objeto StreetViewPanorama. Usando panoramas personalizados, é possível exibir o interior de edifícios, vistas de locais pitorescos ou qualquer coisa do seu imaginário. Você pode até mesmo vincular esses panoramas personalizados aos panoramas atuais do Google Street View.

A configuração de um conjunto de imagens de panorama personalizadas envolve as seguintes etapas:

  • Crie uma imagem panorâmica básica para cada panorama personalizado. Essa imagem base precisa ter a imagem de resolução mais alta com que você quer exibir imagens com zoom definido.
  • (Opcional, mas recomendado) Crie um conjunto de blocos panorâmicos em diferentes níveis de zoom da imagem básica.
  • Crie links entre os panoramas personalizados.
  • Opcional: inclua panoramas de "entrada" nas imagens do Street View existentes no Google e personalize os links entre o conjunto personalizado e o conjunto padrão.
  • Defina os metadados de cada imagem de panorama dentro de um objeto StreetViewPanoramaData.
  • Implemente um método que determine os dados e as imagens do panorama personalizado e designe esse método como gerenciador personalizado no objeto StreetViewPanorama.

As seções a seguir explicam o processo.

Criar panoramas personalizados

Cada panorama do Street View é uma imagem ou um conjunto de imagens que oferece uma visualização completa em 360 graus de um único local. O objeto StreetViewPanorama usa imagens que estão em conformidade com a projeção equidistante (Plate Carrée). Essa projeção contém 360 graus de visualização horizontal (uma volta completa ao redor de um ponto) e 180 graus de visualização vertical (do ponto mais alto ao mais baixo). Esses campos de visão resultam em uma imagem com proporção de 2:1. Veja a seguir um panorama completo ao redor.

As imagens de panorama geralmente são capturadas tirando várias fotos de uma posição e as agrupando usando um software de panorama. Consulte a comparação de aplicativos de agrupamento de fotos da Wikipédia para mais informações. Essas imagens precisam compartilhar um único local de "câmera" do qual cada uma das imagens do panorama é capturada. O panorama resultante de 360 graus pode definir uma projeção em uma esfera com a imagem encapsulada à superfície bidimensional da esfera.

Tratar o panorama como uma projeção em uma esfera com um sistema de coordenadas retilíneas é vantajoso ao dividir a imagem em blocos retilíneos e exibir imagens com base em coordenadas de bloco calculadas.

Criar blocos de panoramas personalizados

O Street View também oferece suporte a diferentes níveis de detalhes de imagem por meio do uso de um controle de zoom, que permite aumentar e diminuir o zoom da visualização padrão. Geralmente, o Street View oferece cinco níveis de resolução de zoom para qualquer imagem de panorama. Se você tivesse que depender de uma única imagem de panorama para exibir todos os níveis de zoom, essa imagem seria necessariamente muito grande e causaria uma lentidão significativa no seu aplicativo ou seria de baixa resolução em níveis de zoom mais altos para servir uma imagem mal pixelada. Felizmente, no entanto, podemos usar um padrão de design semelhante ao usado para exibir blocos de mapas do Google em diferentes níveis de zoom para fornecer imagens de resolução apropriadas para panoramas em cada nível de zoom.

Quando uma StreetViewPanorama é carregada pela primeira vez, ela mostra, por padrão, uma imagem composta por 25% (90 graus de arco) da amplitude horizontal do panorama no nível de zoom 1. Essa visualização corresponde aproximadamente a um campo de visão humano normal. Diminuir o zoom dessa visão padrão oferece um arco mais amplo, enquanto o zoom aumenta o campo de uma visualização para um arco menor. A StreetViewPanorama calcula automaticamente o campo de visão adequado para o nível de zoom selecionado e, em seguida, seleciona as imagens mais adequadas para essa resolução selecionando um conjunto de blocos que corresponda aproximadamente às dimensões do campo de visão horizontal. Os seguintes campos de visão mapeiam para os níveis de zoom do Street View:

Nível de zoom do Street View Campo de visão (graus)
0 180
1 (padrão) 90
2 45
3 22,5
4 11,25

O tamanho da imagem mostrada no Street View depende totalmente do tamanho da tela (largura) do contêiner do Street View. Se você fornecer um contêiner mais amplo, o serviço ainda fornecerá o mesmo campo de visão para qualquer nível de zoom. No entanto, ele pode selecionar blocos mais adequados para essa resolução.

Como cada panorama consiste em uma projeção equidistante, criar blocos de panorama é relativamente fácil. Como a projeção fornece uma imagem com proporção de 2:1, os blocos com proporções de 2:1 são mais fáceis de usar, embora os blocos quadrados possam fornecer um melhor desempenho em mapas quadrados, já que o campo de visão será quadrado.

Para blocos 2:1, uma única imagem que abrange todo o panorama representa o panorama completo (a imagem base) no nível de zoom 0, e cada nível crescente oferece quatro blocos com zoomLevel. Por exemplo, no nível de zoom 2, o panorama inteiro consiste em 16 blocos. Observação: os níveis de zoom nos blocos do Street View não correspondem diretamente aos níveis de zoom fornecidos com o controle do Street View. Em vez disso, eles selecionam um campo de visão (FoV, na sigla em inglês) em que os blocos apropriados são selecionados.

Geralmente, é recomendado nomear seus blocos de imagem para que eles possam ser selecionados programaticamente. Esse esquema de nomenclatura é discutido abaixo em Como processar solicitações de panoramas personalizados.

Processar solicitações de panoramas personalizados

Para usar um panorama personalizado, chame StreetViewPanorama.registerPanoProvider(), especificando o nome do método do seu provedor de panorama personalizado. O método do provedor do panorama precisa retornar um objeto StreetViewPanoramaData e ter a seguinte assinatura:

Function(pano):StreetViewPanoramaData

Um StreetViewPanoramaData é um objeto do seguinte formato:

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

Exiba um panorama personalizado da seguinte maneira:

  • Defina a propriedade StreetViewPanoramaOptions.pano como um valor personalizado.
  • Chame StreetViewPanorama.registerPanoProvider() para fornecer uma função personalizada do provedor de panorama.
  • Implemente sua função personalizada do provedor de panoramas para processar o valor pano especificado.
  • Crie um objeto StreetViewPanoramaData.
  • Defina a propriedade StreetViewTileData.getTileUrl como o nome de uma função de provedor de blocos personalizada que você fornecer. Por exemplo, getCustomPanoramaTileUrl.
  • Implemente sua função de provedor de blocos personalizada, conforme mostrado nos exemplos abaixo.
  • Retorne o objeto StreetViewPanoramaData.

Observação:não defina diretamente um position no StreetViewPanorama quando quiser exibir panoramas personalizados, porque essa posição instrui o serviço do Street View a solicitar as imagens padrão do Street View próximas a esse local. Em vez disso, defina essa posição no campo location.latLng personalizado do objeto StreetViewPanoramaData.

O exemplo a seguir exibe um panorama personalizado do escritório do Google Sydney. Este exemplo não usa um mapa ou imagens padrão do 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 exemplo

Testar amostra

O fornecedor de panorama personalizado retorna o bloco apropriado com base no ID do panorama transmitido, no nível de zoom e nas coordenadas do bloco do panorama. Como a seleção de imagens depende desses valores transmitidos, é útil nomear as imagens que podem ser selecionadas programaticamente considerando esses valores transmitidos, como pano_zoom_tileX_tileY.png.

O exemplo a seguir adiciona outra seta à imagem, além das setas de navegação padrão do Street View, que aponta para o Google Sydney e vincula às imagens 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 exemplo

Testar amostra