Служба Street View

Обзор

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

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

Ниже показан пример панорамы Street View.


Maps JavaScript API с помощью службы Street View может получать и обрабатывать изображения из Google Карт и Просмотра улиц. Служба Street View поддерживается встроенными возможностями браузера.

Использование карт с панорамами Street View

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

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

Когда пользователь перетаскивает человечка на улицу, на экране появляется соответствующая этому месту панорама Просмотра улиц.

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

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

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

Контейнеры Street View

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

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

Места Street View и точка обзора

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

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

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

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

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

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.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initialize&v=weekly"
      defer
    ></script>
  </body>
</html>
Посмотреть пример

Примеры кода

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

API 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. Таким же образом в панорамах Просмотра улиц можно открыть информационные окна – вызвав open() и передав StreetViewPanorama() вместо карты.

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

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

TypeScript

let panorama: google.maps.StreetViewPanorama;

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

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

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

  // 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.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>
Посмотреть пример

Примеры кода

События Street View

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

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

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

TypeScript

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

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

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

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

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

    const links = panorama.getLinks();

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

      linksTable.appendChild(row);

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

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

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

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

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

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

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

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

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

JavaScript

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

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

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

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

    const links = panorama.getLinks();

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

      linksTable.appendChild(row);

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

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

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

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

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

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

window.initPano = initPano;

CSS

/*
 * Always set the map height explicitly to define the size of the div element
 * that contains the map.
 */
#map {
  height: 100%;
}

/*
 * Optional: Makes the sample page fill the window.
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#floating-panel {
  position: absolute;
  top: 10px;
  left: 25%;
  z-index: 5;
  background-color: #fff;
  padding: 5px;
  border: 1px solid #999;
  text-align: center;
  font-family: "Roboto", "sans-serif";
  line-height: 30px;
  padding-left: 10px;
}

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

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

HTML

<html>
  <head>
    <title>Street View Events</title>
    <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.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
Посмотреть пример

Примеры кода

Элементы управления Street View

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

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

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

TypeScript

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

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

JavaScript

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

window.initPano = initPano;

CSS

/*
 * Always set the map height explicitly to define the size of the div element
 * that contains the map.
 */
#map {
  height: 100%;
}

/*
 * Optional: Makes the sample page fill the window.
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

HTML

<html>
  <head>
    <title>Street View Controls</title>
    <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.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
Посмотреть пример

Примеры кода

Прямой доступ к данным Street View

Доступность данных Street View можно определить программным способом. Также можно получить информацию об определенных панорамах, не совершая действий непосредственно с картой или панорамой. Это можно сделать с помощью объекта StreetViewService, который предоставляет интерфейс для данных, хранящихся в службе Street View.

Запросы службы Street View

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

Инициировать запрос к StreetViewService можно с помощью методов StreetViewPanoRequest или StreetViewLocationRequest.

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

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

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

Ответы службы Street View

Функции getPanorama() необходима функция обратного вызова, которая бы выполнялась при возвращении результатов из службы Street View. Она возвращает набор данных панорамы в объекте 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, возвращаемого службой.

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.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>
Посмотреть пример

Примеры кода

Собственные панорамы Street View

Maps JavaScript API поддерживает показ собственных панорам в объекте StreetViewPanorama. С помощью персонализированных панорам можно показывать любые виды: интерьеры зданий, пейзажи и т. д. Вы даже можете связать собственные панорамы с панорамами Google Просмотра улиц.

Для настройки снимков для собственной панорамы необходимо выполнить описанные ниже шаги.

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

Подробнее эта процедура описана ниже.

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

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

Панорама улицы в городе

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

Сфера с панорамой улицы на поверхности

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

Создание собственных фрагментов панорам

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

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

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

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

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

Один фрагмент 2:1 заключает в себе всю панораму с углом обзора 360° и коэффициентом масштабирования 0 (базовое изображение). Количество фрагментов равно 4уровень_масштабирования (то есть на уровне 2 панорама состоит из 16 фрагментов). Примечание. Уровни масштабирования в службе Street View не совпадают с уровнями масштабирования в интерфейсе Просмотра улиц (в последнем случае сначала выбирается зона обзора, а затем подходящий фрагмент).

Панорама улицы, разделенная на фрагменты

Обычно фрагментам присваивают имена, чтобы на них можно было ссылаться в коде. Схема именования описана в разделе ниже.

Работа с запросами собственных панорам

Для работы с собственной панорамой вызовите метод поставщика панорам 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, если вы хотите показывать собственную панораму, поскольку в этом случае служба Street View отправит запрос для получения стандартных изображений, доступных для этого места. Вместо этого задайте местоположение в объекте StreetViewPanoramaData (поле location.latLng).

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

TypeScript

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

  panorama.registerPanoProvider(getCustomPanorama);
}

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

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

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

JavaScript

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

  panorama.registerPanoProvider(getCustomPanorama);
}

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

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

window.initPano = initPano;

CSS

/*
 * Always set the map height explicitly to define the size of the div element
 * that contains the map.
 */
#map {
  height: 100%;
}

/*
 * Optional: Makes the sample page fill the window.
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

HTML

<html>
  <head>
    <title>Custom Street View Panoramas</title>
    <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.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
Посмотреть пример

Примеры кода

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

Код ниже добавляет еще одну стрелку к изображению в дополнение к стандартным стрелкам навигации Street View. Эта стрелка указывает на офис Google в Сиднее и содержит ссылку на собственные изображения:

TypeScript

let panorama: google.maps.StreetViewPanorama;

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

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

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

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

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

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

JavaScript

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

// StreetViewPanoramaData for a custom panorama: the Google Sydney reception.
function getReceptionPanoramaData() {
  return {
    location: {
      pano: "reception",
      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.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>
Посмотреть пример

Примеры кода