Сервис просмотра улиц

Оптимизируйте свои подборки Сохраняйте и классифицируйте контент в соответствии со своими настройками.

Обзор

Выберите платформу: Android iOS JavaScript

Google Street View обеспечивает панорамный вид на 360 градусов с обозначенных дорог по всей зоне покрытия. Покрытие API Street View такое же, как и у приложения Google Maps ( https://maps.google.com/ ). Список городов, в которых в настоящее время поддерживается просмотр улиц, доступен на веб- сайте Google Maps .

Образец изображения Street View показан ниже.


Maps JavaScript API предоставляет службу просмотра улиц для получения изображений, используемых в просмотре улиц Google Карт, и управления ими. Этот сервис просмотра улиц изначально поддерживается браузером.

Использование карты Просмотра улиц

Хотя просмотр улиц можно использовать в отдельном элементе DOM , он наиболее полезен при указании местоположения на карте. По умолчанию просмотр улиц включен на карте, а элемент управления человечком в просмотре улиц интегрирован в элементы управления навигацией (масштабирование и панорамирование). Вы можете скрыть этот элемент управления в streetViewControl карты, установив для MapOptions значение false . Вы также можете изменить положение элемента управления Просмотром улиц по умолчанию, задав для свойства streetViewControlOptions.position Map новое значение ControlPosition .

Элемент управления Street View Pegman позволяет просматривать панорамы Street View прямо на карте. Когда пользователь нажимает и удерживает человечка, карта обновляется, чтобы показать синие контуры вокруг улиц с включенным просмотром улиц, предлагая пользовательский интерфейс, аналогичный приложению Google Maps.

Когда пользователь помещает маркер Pegman на улицу, карта обновляется, чтобы отобразить панораму просмотра улиц указанного местоположения.

Панорамы просмотра улиц

Изображения просмотра улиц поддерживаются за счет использования объекта StreetViewPanorama , который предоставляет API-интерфейс для «просмотра» просмотра улиц. Каждая карта содержит панораму просмотра улиц по умолчанию, которую можно получить, вызвав метод карты getStreetView() . Когда вы добавляете элемент управления Street View на карту, задавая для параметра streetViewControl значение true , вы автоматически подключаете элемент управления Pegman к этой панораме Street View по умолчанию.

Вы также можете создать свой собственный объект StreetViewPanorama и настроить карту на его использование вместо объекта по умолчанию, явно установив свойство streetView карты для этого созданного объекта. Вы можете переопределить панораму по умолчанию, если хотите изменить поведение по умолчанию, например автоматическое совместное использование наложений между картой и панорамой. (См. раздел Наложения в Просмотре улиц ниже.)

Контейнеры просмотра улиц

Вместо этого вы можете отображать StreetViewPanorama в отдельном элементе DOM, часто в элементе <div> . Просто передайте элемент DOM в конструкторе StreetViewPanorama . Для оптимального отображения изображений мы рекомендуем минимальный размер 200 на 200 пикселей.

Примечание. Хотя функции просмотра улиц предназначены для использования вместе с картой, это использование не является обязательным. Вы можете использовать отдельный объект Просмотра улиц без карты.

Места просмотра улиц и точка обзора (POV)

Конструктор StreetViewPanorama также позволяет вам установить местоположение и точку обзора Street View с помощью параметра StreetViewOptions . Вы можете вызвать setPosition() и setPov() для объекта после создания, чтобы изменить его местоположение и точку зрения.

Местоположение просмотра улиц определяет размещение фокуса камеры для изображения, но не определяет ориентацию камеры для этого изображения. Для этой цели объект StreetViewPov определяет два свойства:

  • heading (по умолчанию 0 ) определяет угол поворота вокруг локуса камеры в градусах относительно истинного севера. Направления измеряются по часовой стрелке (90 градусов — истинный восток).
  • pitch (по умолчанию 0 ) определяет отклонение угла «вверх» или «вниз» от исходного шага камеры по умолчанию, который часто (но не всегда) является плоским по горизонтали. (Например, изображение, сделанное на холме, скорее всего, будет иметь шаг по умолчанию, который не является горизонтальным.) Углы наклона измеряются с положительными значениями, направленными вверх (до +90 градусов прямо вверх и ортогонально шагу по умолчанию), и отрицательными значениями, направленными вниз. (до -90 градусов прямо вниз и ортогонально шагу по умолчанию).

Объект StreetViewPov чаще всего используется для определения точки обзора камеры просмотра улиц. С помощью метода StreetViewPanorama.getPhotographerPov() можно также определить точку зрения фотографа — обычно направление движения автомобиля или мотоцикла .

Следующий код отображает карту Бостона с первоначальным видом на парк Фенуэй. Выбор человечка и перетаскивание его в поддерживаемое место на карте изменит панораму просмотра улиц:

Машинопись

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>
Посмотреть пример

Попробуйте образец

Отслеживание движения на мобильных устройствах

На устройствах, которые поддерживают события ориентации устройства, API предлагает пользователям возможность изменять точку обзора Street View в зависимости от движения устройства. Пользователи могут осмотреться, перемещая свои устройства. Это называется отслеживанием движения или отслеживанием вращения устройства.

Как разработчик приложения, вы можете изменить поведение по умолчанию следующим образом:

  • Включите или отключите функцию отслеживания движения. По умолчанию отслеживание движения включено на любом устройстве, которое его поддерживает. В следующем примере отслеживание движения отключено, но элемент управления отслеживанием остается видимым. (Обратите внимание, что пользователь может включить отслеживание движения, коснувшись элемента управления.)
    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTracking: false
        });
    
  • Скрыть или показать элемент управления отслеживанием движения. По умолчанию элемент управления отображается на устройствах, поддерживающих отслеживание движения. Пользователь может коснуться элемента управления, чтобы включить или выключить отслеживание движения. Обратите внимание, что элемент управления никогда не появится, если устройство не поддерживает отслеживание движения, независимо от значения motionTrackingControl .

    В следующем примере отключается как отслеживание движения, так и элемент управления отслеживанием движения. В этом случае пользователь не может включить отслеживание движения:

    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTracking: false,
          motionTrackingControl: false
        });
    
  • Измените положение элемента управления отслеживанием движения по умолчанию. По умолчанию элемент управления появляется в правом нижнем углу панорамы (позиция RIGHT_BOTTOM ). В следующем образце положение элемента управления задается слева внизу:
    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTrackingControlOptions: {
            position: google.maps.ControlPosition.LEFT_BOTTOM
          }
        });
    

Чтобы увидеть отслеживание движения в действии, просмотрите следующий пример на мобильном устройстве (или любом устройстве, которое поддерживает события ориентации устройства):


Посмотреть пример

Наложения в Просмотре улиц

Объект StreetViewPanorama по умолчанию поддерживает собственное отображение наложений карт. Оверлеи обычно появляются на «уровне улицы» с привязкой к позициям LatLng . (Например, маркеры будут отображаться с хвостами, привязанными к горизонтальной плоскости местоположения в панораме просмотра улиц.)

В настоящее время типы наложений, которые поддерживаются на панорамах Street View, ограничены Marker , InfoWindow и пользовательскими OverlayView . Наложения, отображаемые на карте, могут отображаться на панораме просмотра улиц путем обработки панорамы как замены объекта Map , вызова setMap() и передачи StreetViewPanorama в качестве аргумента вместо карты. Информационные окна аналогичным образом можно открыть в панораме Street View, вызвав open() и передав StreetViewPanorama() вместо карты.

Кроме того, при создании карты с StreetViewPanorama по умолчанию все маркеры, созданные на карте, автоматически используются совместно с соответствующей панорамой просмотра улиц карты, при условии, что эта панорама видна. Чтобы получить панораму Street View по умолчанию, вызовите getStreetView() для объекта Map . Обратите внимание, что если вы явно установите для свойства StreetViewPanorama streetView конструкции, вы переопределите панораму по умолчанию.

В следующем примере показаны маркеры, обозначающие различные места вокруг Астор-Плейс, Нью-Йорк. Переключите отображение на Просмотр улиц, чтобы показать общие маркеры, отображаемые в StreetViewPanorama .

Машинопись

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>
Посмотреть пример

Попробуйте образец

События Просмотра улиц

При перемещении между просмотром улиц или управлении его ориентацией вы можете отслеживать несколько событий, которые указывают на изменения в состоянии StreetViewPanorama :

  • pano_changed срабатывает всякий раз, когда изменяется индивидуальный идентификатор панорамы. Это событие не гарантирует, что любые связанные данные в панораме (например, ссылки) также изменились к моменту запуска этого события; это событие указывает только на то, что идентификатор панорамы изменился. Обратите внимание, что идентификатор панорамы (который вы можете использовать для ссылки на эту панораму) стабилен только в рамках текущего сеанса браузера.
  • position_changed срабатывает всякий раз, когда изменяется основная ( LatLng ) позиция панорамы. Вращение панорамы не вызовет это событие. Обратите внимание, что вы можете изменить основное положение панорамы, не изменяя связанный идентификатор панорамы, поскольку API автоматически свяжет ближайший идентификатор панорамы с положением панорамы.
  • pov_changed срабатывает всякий раз, когда изменяется StreetViewPov Просмотра улиц. Обратите внимание, что это событие может срабатывать, пока положение и идентификатор панорамы остаются стабильными.
  • links_changed срабатывает всякий раз, когда меняются ссылки в Просмотре улиц. Обратите внимание, что это событие может запускаться асинхронно после изменения идентификатора панорамы, указанного с помощью pano_changed .
  • visible_changed срабатывает всякий раз, когда изменяется видимость просмотра улиц. Обратите внимание, что это событие может запускаться асинхронно после изменения идентификатора панорамы, указанного с помощью pano_changed .

В следующем коде показано, как можно обрабатывать эти события для сбора данных о базовом StreetViewPanorama :

Машинопись

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>
Посмотреть пример

Попробуйте образец

Управление просмотром улиц

При отображении StreetViewPanorama по умолчанию на панораме появляются различные элементы управления. Вы можете включить или отключить эти элементы управления, установив для соответствующих полей в StreetViewPanoramaOptions значение true или false :

  • panControl предоставляет способ поворота панорамы. Этот элемент управления отображается по умолчанию как стандартный встроенный элемент управления компасом и панорамированием. Вы можете изменить положение элемента управления, указав PanControlOptions в поле panControlOptions .
  • zoomControl предоставляет способ масштабирования изображения. Этот элемент управления появляется по умолчанию в правом нижнем углу панорамы. Вы можете изменить внешний вид элемента управления, указав ZoomControlOptions в поле zoomControlOptions .
  • addressControl предоставляет текстовое наложение, указывающее адрес связанного местоположения, и предлагает ссылку, чтобы открыть местоположение в Картах Google. Вы можете изменить внешний вид элемента управления, указав StreetViewAddressControlOptions в поле addressControlOptions .
  • fullscreenControl предлагает возможность открыть просмотр улиц в полноэкранном режиме. Вы можете изменить внешний вид элемента управления, FullscreenControlOptions в поле fullscreenControlOptions .
  • motionTrackingControl предлагает возможность включить или отключить отслеживание движения на мобильных устройствах. Этот элемент управления отображается только на устройствах, которые поддерживают события ориентации устройства. По умолчанию элемент управления отображается в правом нижнем углу панорамы. Вы можете изменить положение элемента управления, MotionTrackingControlOptions . Дополнительные сведения см. в разделе об отслеживании движения .
  • linksControl предоставляет направляющие стрелки на изображении для перехода к соседним панорамным изображениям.
  • Элемент управления «Закрыть» позволяет пользователю закрыть окно просмотра улиц. Вы можете включить или отключить элемент управления Close, задав для параметра enableCloseButton значение true или false .

В следующем примере изменяются элементы управления, отображаемые в связанном просмотре улиц, и удаляются ссылки представления:

Машинопись

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>
Посмотреть пример

Попробуйте образец

Прямой доступ к данным просмотра улиц

Вы можете программно определять доступность данных Street View или возвращать информацию о конкретных панорамах, не требуя прямого манипулирования картой/панорамой. Вы можете сделать это с помощью объекта StreetViewService , который предоставляет интерфейс к данным, хранящимся в службе просмотра улиц Google.

Запросы на услуги Просмотра улиц

Доступ к службе просмотра улиц является асинхронным, поскольку API Карт Google должен выполнить вызов на внешний сервер. По этой причине вам необходимо передать метод обратного вызова для выполнения после завершения запроса. Этот метод обратного вызова обрабатывает результат.

Вы можете инициировать запросы к StreetViewService , используя StreetViewPanoRequest или StreetViewLocationRequest .

Запрос с использованием StreetViewPanoRequest возвращает данные панорамы с заданным идентификатором ссылки, который однозначно идентифицирует панораму. Обратите внимание, что эти эталонные идентификаторы стабильны только на время существования изображения этой панорамы.

Запрос с использованием StreetViewLocationRequest ищет данные панорамы в указанном месте, используя следующие параметры:

  • location указывает местоположение (широту и долготу) для поиска панорамы.
  • preference задает предпочтение, для которого панорама должна быть найдена в радиусе: ближайшая к указанному местоположению или лучшая в радиусе.
  • radius задает радиус, указанный в метрах, в котором искать панораму с центром на заданной широте и долготе. По умолчанию 50, если не указано.
  • source указывает источник панорам для поиска. Допустимые значения:
    • default используются стандартные источники для Просмотра улиц; поиск не ограничивается конкретными источниками.
    • outdoor ограничивает поиск уличными коллекциями. Обратите внимание, что наружные панорамы могут не существовать для указанного местоположения.

Ответы службы просмотра улиц

Функция getPanorama() нуждается в функции обратного вызова для выполнения после получения результата из службы просмотра улиц. Эта функция обратного вызова возвращает набор данных панорамы в объекте StreetViewPanoramaData и код StreetViewStatus , обозначающий статус запроса, в указанном порядке.

Спецификация объекта StreetViewPanoramaData содержит метаданные о панораме просмотра улиц в следующем виде:

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

Обратите внимание, что этот объект данных сам по себе не является объектом StreetViewPanorama . Чтобы создать объект Street View с использованием этих данных, вам потребуется создать StreetViewPanorama и вызвать setPano() , передав ему идентификатор, указанный в возвращаемом поле location.pano .

Код status может возвращать одно из следующих значений:

  • OK означает, что сервис нашел подходящую панораму.
  • ZERO_RESULTS означает, что службе не удалось найти подходящую панораму по переданным критериям.
  • UNKNOWN_ERROR означает, что запрос просмотра улиц не может быть обработан, хотя точная причина неизвестна.

Следующий код создает StreetViewService , который реагирует на щелчки пользователя на карте, создавая маркеры, при нажатии на которые отображается StreetViewPanorama этого местоположения. Код использует содержимое StreetViewPanoramaData , возвращаемое службой.

Машинопись

/*
 * 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>
Посмотреть пример

Попробуйте образец

Предоставление пользовательских панорам просмотра улиц

Maps JavaScript API поддерживает отображение пользовательских панорам в объекте StreetViewPanorama . Используя пользовательские панорамы, вы можете отображать внутреннюю часть зданий, виды из живописных мест или все, что только может представить ваше воображение. Вы даже можете связать эти пользовательские панорамы с существующими панорамами Google Street View.

Настройка набора пользовательских панорамных изображений включает следующие шаги:

  • Создайте базовое панорамное изображение для каждой пользовательской панорамы. Это базовое изображение должно иметь самое высокое разрешение, с которым вы хотите показывать увеличенные изображения.
  • (Необязательно, но рекомендуется) Создайте набор панорамных плиток с разными уровнями масштабирования из основного изображения.
  • Создавайте ссылки между вашими пользовательскими панорамами.
  • (Необязательно) Назначьте «входные» панорамы в существующих изображениях Просмотра улиц Google и настройте ссылки на пользовательский набор и на стандартный набор.
  • Определите метаданные для каждого панорамного изображения в объекте StreetViewPanoramaData .
  • Реализуйте метод, определяющий данные и изображения пользовательской панорамы, и назначьте этот метод в качестве пользовательского обработчика в объекте StreetViewPanorama .

В следующих разделах объясняется этот процесс.

Создание пользовательских панорам

Каждая панорама просмотра улиц представляет собой изображение или набор изображений, обеспечивающих полный обзор на 360 градусов из одного места. Объект StreetViewPanorama использует изображения, соответствующие равнопромежуточной проекции (Plate Carrée). Такая проекция содержит 360 градусов обзора по горизонтали (полный охват) и 180 градусов обзора по вертикали (от прямой вверх до прямой вниз). Эти поля зрения дают изображение с соотношением сторон 2:1. Полная круговая панорама показана ниже.

Панорамные изображения, как правило, получаются путем съемки нескольких фотографий с одного места и сшивания их вместе с помощью программного обеспечения для создания панорам. (Дополнительную информацию см. в разделе « Сравнение приложений для склеивания фотографий » в Википедии.) Такие изображения должны иметь один общий «камерный» локус, из которого берется каждое панорамное изображение. Результирующая 360-градусная панорама может затем определять проекцию на сфере с изображением, обернутым на двумерную поверхность сферы.

Обработка панорамы как проекции на сферу с прямолинейной системой координат выгодна при разделении изображения на прямолинейные плитки и предоставлении изображений на основе вычисленных координат плитки.

Создание пользовательских панорамных плиток

Просмотр улиц также поддерживает различные уровни детализации изображения с помощью элемента управления масштабированием, который позволяет увеличивать и уменьшать масштаб изображения по умолчанию. Как правило, Просмотр улиц обеспечивает пять уровней разрешения для любого панорамного изображения. Если бы вы полагались на одно панорамное изображение для обслуживания всех уровней масштабирования, такое изображение либо обязательно было бы довольно большим и значительно замедляло работу вашего приложения, либо имело бы такое низкое разрешение при более высоких уровнях масштабирования, что вы бы обслуживали изображение с плохой пикселизацией. . Однако, к счастью, мы можем использовать аналогичный шаблон проектирования, используемый для обслуживания фрагментов карт Google с разными уровнями масштабирования, чтобы обеспечить изображения с соответствующим разрешением для панорам на каждом уровне масштабирования.

При первой загрузке StreetViewPanorama по умолчанию отображается изображение, состоящее из 25% (90 градусов дуги) ширины панорамы по горизонтали при уровне масштабирования 1. Этот вид примерно соответствует нормальному полю зрения человека. «Уменьшение» этого вида по умолчанию по существу обеспечивает более широкую дугу, в то время как увеличение масштаба сужает поле зрения до меньшей дуги. StreetViewPanorama автоматически вычисляет соответствующее поле зрения для выбранного уровня масштабирования, а затем выбирает изображения, наиболее подходящие для этого разрешения, выбирая набор фрагментов, который примерно соответствует размерам горизонтального поля зрения. Следующие поля просмотра сопоставляются с уровнями масштабирования просмотра улиц:

Уровень масштабирования просмотра улиц Поле зрения (градусы)
0 180
1 (по умолчанию) 90
2 45
3 22,5
4 11.25

Обратите внимание, что размер изображения, отображаемого в Просмотре улиц, полностью зависит от размера экрана (ширины) контейнера Просмотра улиц. Если вы предоставите более широкий контейнер, служба по-прежнему будет предоставлять одинаковое поле зрения для любого заданного уровня масштабирования, хотя вместо этого она может выбрать плитки, более подходящие для этого разрешения.

Поскольку каждая панорама состоит из равнопрямоугольной проекции, создание фрагментов панорамы относительно просто. Поскольку проекция обеспечивает изображение с соотношением сторон 2:1, тайлы с соотношением сторон 2:1 проще использовать, хотя квадратные тайлы могут обеспечить лучшую производительность на квадратных картах (поскольку поле зрения будет квадратным).

Для плиток 2:1 одно изображение, охватывающее всю панораму, представляет весь «мир» панорамы (базовое изображение) при уровне масштабирования 0, при этом каждый увеличивающийся уровень масштабирования предлагает 4 плитки zoomLevel . (Например, при уровне масштабирования 2 вся панорама состоит из 16 фрагментов.) Примечание: уровни масштабирования в фрагментах просмотра улиц не соответствуют непосредственно уровням масштабирования, предоставляемым с помощью элемента управления Просмотра улиц; вместо этого уровни масштабирования управления просмотром улиц выбирают поле обзора (FoV), из которого выбираются соответствующие плитки.

Как правило, вы захотите назвать свои фрагменты изображений, чтобы их можно было выбирать программно. Такая схема именования обсуждается ниже в разделе «Обработка запросов пользовательской панорамы» .

Обработка запросов на индивидуальную панораму

Чтобы использовать пользовательскую панораму, вызовите StreetViewPanorama.registerPanoProvider() , указав имя метода поставщика пользовательской панорамы. Метод поставщика панорамы должен возвращать объект StreetViewPanoramaData и иметь следующую подпись:

Function(pano):StreetViewPanoramaData

StreetViewPanoramaData — это объект следующего вида:

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

Отобразите пользовательскую панораму следующим образом:

  • Задайте для свойства StreetViewPanoramaOptions.pano пользовательское значение.
  • Вызовите StreetViewPanorama.registerPanoProvider() , чтобы предоставить пользовательскую функцию поставщика панорамы.
  • Реализуйте функцию поставщика пользовательской панорамы для обработки указанного значения pano .
  • Создайте объект StreetViewPanoramaData .
  • Задайте для свойства StreetViewTileData.getTileUrl имя предоставленной вами пользовательской функции поставщика плиток. Например, getCustomPanoramaTileUrl .
  • Реализуйте собственную функцию поставщика плиток, как показано в примерах ниже.
  • Верните объект StreetViewPanoramaData .

Примечание. Не устанавливайте position непосредственно на StreetViewPanorama , когда хотите отображать пользовательские панорамы, так как такая позиция даст указание службе просмотра улиц запрашивать изображения просмотра улиц по умолчанию рядом с этим местом. Вместо этого задайте эту позицию в поле location.latLng пользовательского объекта StreetViewPanoramaData .

В следующем примере показана пользовательская панорама офиса Google в Сиднее. Обратите внимание, что в этом примере не используются карта или стандартные изображения Просмотра улиц:

Машинопись

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>
Посмотреть пример

Попробуйте образец

Пользовательский поставщик панорам возвращает соответствующую плитку с учетом переданного идентификатора панорамы, уровня масштабирования и координат плитки панорамы. Поскольку выбор изображения зависит от этих переданных значений, полезно именовать изображения, которые можно выбирать программно с учетом этих переданных значений, например, pano _ zoom _ tileX _ tileY .png .

В следующем примере к изображению добавляется еще одна стрелка в дополнение к стрелкам навигации по умолчанию в Просмотре улиц, которая указывает на Google Сидней и ссылается на пользовательские изображения:

Машинопись

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>
Посмотреть пример

Попробуйте образец