Обзор
Google Street View обеспечивает панорамный вид на 360 градусов с обозначенных дорог по всей зоне покрытия. Охват API Street View такой же, как и у приложения Google Maps ( https://maps.google.com/
). Список городов, которые в настоящее время поддерживаются для просмотра улиц, доступен на сайте Google Maps .
Пример изображения Street View показан ниже.
Maps JavaScript API предоставляет службу Street View для получения и управления изображениями, используемыми в Google Maps Street View. Эта служба просмотра улиц изначально поддерживается браузером.
Использование карты просмотра улиц
Хотя просмотр улиц можно использовать в отдельном элементе DOM , он наиболее полезен при указании местоположения на карте. По умолчанию просмотр улиц включен на карте, а элемент управления «Человеческий человечек» просмотра улиц интегрирован в элементы управления навигацией (масштабированием и панорамированием). Вы можете скрыть этот элемент управления в MapOptions
карты, установив для streetViewControl
значение false
. Вы также можете изменить положение элемента управления Street View по умолчанию, установив для свойства streetViewControlOptions.position
Map
новое значение ControlPosition
.
Элемент управления Street View Pegman позволяет просматривать панорамы Street View прямо на карте. Когда пользователь нажимает и удерживает человечка, карта обновляется, показывая синие контуры вокруг улиц с включенным просмотром улиц, предлагая пользовательский интерфейс, аналогичный приложению Google Maps.
Когда пользователь помещает маркер человечка на улицу, карта обновляется и отображает панораму Street View указанного места.
Панорамы просмотра улиц
Изображения Street View поддерживаются посредством использования объекта StreetViewPanorama
, который предоставляет интерфейс API для «просмотра» Street View. Каждая карта содержит панораму Street View по умолчанию, которую можно получить, вызвав метод карты getStreetView()
. Когда вы добавляете на карту элемент управления Street View, устанавливая для его параметра streetViewControl
значение true
, вы автоматически подключаете элемент управления Pegman к этой панораме Street View по умолчанию.
Вы также можете создать свой собственный объект StreetViewPanorama
и настроить карту на его использование вместо объекта по умолчанию, явно установив свойство streetView
карты для этого созданного объекта. Вы можете переопределить панораму по умолчанию, если хотите изменить поведение по умолчанию, например автоматическое совместное использование наложений между картой и панорамой. (См. раздел «Наложения в просмотре улиц» ниже.)
Контейнеры просмотра улиц
Вместо этого вы можете захотеть отобразить StreetViewPanorama
в отдельном элементе DOM, часто в элементе <div>
. Просто передайте элемент DOM в конструкторе StreetViewPanorama
. Для оптимального отображения изображений мы рекомендуем минимальный размер 200 на 200 пикселей.
Примечание. Хотя функция просмотра улиц предназначена для использования вместе с картой, это использование не является обязательным. Вы можете использовать отдельный объект Street View без карты.
Места просмотра улиц и точки обзора (POV)
Конструктор StreetViewPanorama
также позволяет вам установить местоположение и точку обзора Street View с помощью параметра StreetViewOptions
. Вы можете вызвать setPosition()
и setPov()
для объекта после создания, чтобы изменить его местоположение и точку зрения.
Местоположение просмотра улиц определяет расположение фокуса камеры для изображения, но не определяет ориентацию камеры для этого изображения. Для этой цели объект StreetViewPov
определяет два свойства:
-
heading
(по умолчанию0
) определяет угол поворота вокруг локуса камеры в градусах относительно истинного севера. Направление измеряется по часовой стрелке (90 градусов соответствует востоку). -
pitch
(по умолчанию0
) определяет отклонение угла «вверх» или «вниз» от исходного шага камеры по умолчанию, который часто (но не всегда) является плоским по горизонтали. (Например, изображение, сделанное на холме, скорее всего, будет иметь наклон по умолчанию, который не является горизонтальным.) Углы наклона измеряются с положительными значениями при взгляде вверх (до +90 градусов прямо вверх и ортогонально наклону по умолчанию) и отрицательными значениями при взгляде вниз. (до -90 градусов прямо вниз и ортогонально шагу по умолчанию).
Объект StreetViewPov
чаще всего используется для определения точки обзора камеры Street View. Вы также можете определить точку зрения фотографа (обычно в направлении, в котором смотрел автомобиль или мотоцикл ) с помощью метода 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> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="map"></div> <div id="pano"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initialize&v=weekly" defer ></script> </body> </html>
Попробуйте образец
Отслеживание движения на мобильных устройствах
На устройствах, поддерживающих события ориентации устройства, 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
. Наложения, отображаемые на карте, могут отображаться на панораме Street View, рассматривая панораму как замену объекта Map
, вызывая setMap()
и передавая StreetViewPanorama
в качестве аргумента вместо карты. Информационные окна аналогичным образом можно открыть в панораме Street View, вызвав open()
, передав StreetViewPanorama()
вместо карты.
Кроме того, при создании карты с StreetViewPanorama
по умолчанию все маркеры, созданные на карте, автоматически используются совместно со связанной с картой панорамой Street View, при условии, что панорама видна. Чтобы получить панораму Street View по умолчанию, вызовите getStreetView()
для объекта Map
. Обратите внимание: если вы явно зададите для свойства streetView
карты значение StreetViewPanorama
собственной конструкции, вы переопределите панораму по умолчанию.
В следующем примере показаны маркеры, обозначающие различные места вокруг Астор-Плейс, Нью-Йорк. Переключите отображение на просмотр улиц, чтобы отобразить общие маркеры, отображаемые в 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); const cafeIcon = document.createElement("img"); cafeIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/cafe_icon.svg"; const dollarIcon = document.createElement("img"); dollarIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bank_icon.svg"; const busIcon = document.createElement("img"); busIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bus_icon.svg"; // Set up the markers on the map const cafeMarker = new google.maps.Marker({ position: { lat: 40.730031, lng: -73.991428 }, map, title: "Cafe", icon: cafeIcon.src, }); const bankMarker = new google.maps.Marker({ position: { lat: 40.729681, lng: -73.991138 }, map, title: "Bank", icon: dollarIcon.src, }); const busMarker = new google.maps.Marker({ position: { lat: 40.729559, lng: -73.990741 }, map, title: "Bus Stop", icon: busIcon.src, }); // We get the map's default panorama and set up some defaults. // Note that we don't yet set it visible. panorama = map.getStreetView()!; // TODO fix type panorama.setPosition(astorPlace); panorama.setPov( /** @type {google.maps.StreetViewPov} */ { heading: 265, pitch: 0, } ); } function toggleStreetView(): void { const toggle = panorama.getVisible(); if (toggle == false) { panorama.setVisible(true); } else { panorama.setVisible(false); } } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
let panorama; function initMap() { const astorPlace = { lat: 40.729884, lng: -73.990988 }; // Set up the map const map = new google.maps.Map(document.getElementById("map"), { center: astorPlace, zoom: 18, streetViewControl: false, }); document.getElementById("toggle").addEventListener("click", toggleStreetView); const cafeIcon = document.createElement("img"); cafeIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/cafe_icon.svg"; const dollarIcon = document.createElement("img"); dollarIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bank_icon.svg"; const busIcon = document.createElement("img"); busIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bus_icon.svg"; // Set up the markers on the map const cafeMarker = new google.maps.Marker({ position: { lat: 40.730031, lng: -73.991428 }, map, title: "Cafe", icon: cafeIcon.src, }); const bankMarker = new google.maps.Marker({ position: { lat: 40.729681, lng: -73.991138 }, map, title: "Bank", icon: dollarIcon.src, }); const busMarker = new google.maps.Marker({ position: { lat: 40.729559, lng: -73.990741 }, map, title: "Bus Stop", icon: busIcon.src, }); // We get the map's default panorama and set up some defaults. // Note that we don't yet set it visible. panorama = map.getStreetView(); // TODO fix type panorama.setPosition(astorPlace); panorama.setPov( /** @type {google.maps.StreetViewPov} */ { heading: 265, pitch: 0, }, ); } function toggleStreetView() { const toggle = panorama.getVisible(); if (toggle == false) { panorama.setVisible(true); } else { panorama.setVisible(false); } } window.initMap = initMap;
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ #map { height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } #floating-panel { position: absolute; top: 10px; left: 25%; z-index: 5; background-color: #fff; padding: 5px; border: 1px solid #999; text-align: center; font-family: "Roboto", "sans-serif"; line-height: 30px; padding-left: 10px; } #floating-panel { margin-left: -100px; }
HTML
<html> <head> <title>Overlays Within Street View</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="floating-panel"> <input type="button" value="Toggle Street View" id="toggle" /> </div> <div id="map"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&libraries=marker&v=weekly" defer ></script> </body> </html>
Попробуйте образец
События просмотра улиц
При переходе между просмотром улиц или управлении его ориентацией вам может потребоваться отслеживать несколько событий, указывающих на изменения состояния StreetViewPanorama
:
-
pano_changed
срабатывает всякий раз, когда меняется индивидуальный идентификатор панорамы. Это событие не гарантирует, что любые связанные данные в панораме (например, ссылки) также изменятся к моменту срабатывания этого события; это событие указывает только на то, что идентификатор панорамы изменился. Обратите внимание, что идентификатор панорамы (который вы можете использовать для ссылки на эту панораму) стабилен только в пределах текущего сеанса браузера. -
position_changed
срабатывает всякий раз, когда изменяется базовое положение (LatLng
) панорамы. Вращение панорамы не вызовет это событие. Обратите внимание, что вы можете изменить базовое положение панорамы, не меняя связанный идентификатор панорамы, поскольку API автоматически свяжет ближайший идентификатор панорамы с положением панорамы. -
pov_changed
срабатывает всякий раз, когда изменяетсяStreetViewPov
Street View. Обратите внимание, что это событие может сработать, пока положение и идентификатор панорамы остаются стабильными. -
links_changed
срабатывает всякий раз, когда изменяются ссылки Street View. Обратите внимание, что это событие может сработать асинхронно после изменения идентификатора панорамы, указанного черезpano_changed
. -
visible_changed
срабатывает всякий раз, когда изменяется видимость Street View. Обратите внимание, что это событие может сработать асинхронно после изменения идентификатора панорамы, указанного через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> <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"> </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"> </td> </tr> <table id="links_table"></table> </table> </div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly" defer ></script> </body> </html>
Попробуйте образец
Элементы управления просмотром улиц
При отображении 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> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="map"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly" defer ></script> </body> </html>
Попробуйте образец
Прямой доступ к данным просмотра улиц
Возможно, вы захотите программно определить доступность данных Street View или вернуть информацию об определенных панорамах, не требуя прямого манипулирования картой/панорамой. Вы можете сделать это с помощью объекта StreetViewService
, который предоставляет интерфейс для данных, хранящихся в службе просмотра улиц Google.
Запросы на услуги просмотра улиц
Доступ к службе Street View является асинхронным, поскольку API Карт Google должен выполнить вызов внешнего сервера. По этой причине вам необходимо передать метод обратного вызова , который будет выполняться после завершения запроса. Этот метод обратного вызова обрабатывает результат.
Вы можете инициировать запросы к StreetViewService
с помощью StreetViewPanoRequest
или StreetViewLocationRequest
.
Запрос с использованием StreetViewPanoRequest
возвращает данные панорамы с идентификатором ссылки, который однозначно идентифицирует панораму. Обратите внимание, что эти эталонные идентификаторы стабильны только на протяжении всего срока службы изображений этой панорамы.
Запрос с использованием StreetViewLocationRequest
выполняет поиск данных панорамы в указанном месте, используя следующие параметры:
-
location
указывает местоположение (широту и долготу) для поиска панорамы. -
preference
устанавливает предпочтение, какую панораму следует найти в радиусе: ближайшую к указанному местоположению или лучшую в радиусе. -
radius
задает радиус, указанный в метрах, в котором можно искать панораму с центром по заданной широте и долготе. По умолчанию 50, если не указано. -
source
указывает источник панорам для поиска. Допустимые значения:-
default
использует источники по умолчанию для просмотра улиц; поиск не ограничивается конкретными источниками. -
outdoor
ограничивает поиск коллекциями на открытом воздухе. Обратите внимание, что панорамы на открытом воздухе для указанного места могут отсутствовать.
-
Ответы службы просмотра улиц
Для функции getPanorama()
требуется функция обратного вызова для выполнения при получении результата от службы просмотра улиц. Эта функция обратного вызова возвращает набор данных панорамы в объекте StreetViewPanoramaData
и код StreetViewStatus
, обозначающий статус запроса, в указанном порядке.
Спецификация объекта StreetViewPanoramaData
содержит метаданные о панораме Street View следующей формы:
{ "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> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="map" style="width: 45%; height: 100%; float: left"></div> <div id="pano" style="width: 45%; height: 100%; float: left"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly" defer ></script> </body> </html>
Попробуйте образец
Предоставление пользовательских панорам Street View
API JavaScript Карт поддерживает отображение пользовательских панорам внутри объекта StreetViewPanorama
. Используя пользовательские панорамы, вы можете отобразить интерьеры зданий, виды из живописных мест или все, что угодно вашему воображению. Вы даже можете связать эти пользовательские панорамы с существующими панорамами Google Street View.
Настройка набора пользовательских панорамных изображений включает в себя следующие шаги:
- Создайте базовое панорамное изображение для каждой пользовательской панорамы. Это базовое изображение должно иметь максимальное разрешение, с которым вы хотите показывать увеличенные изображения.
- (Необязательно, но рекомендуется) Создайте набор панорамных фрагментов с разными уровнями масштабирования из основного изображения.
- Создавайте связи между вашими пользовательскими панорамами.
- (Необязательно) Назначьте «входные» панорамы в существующих изображениях Просмотра улиц Google и настройте ссылки на пользовательский набор или из стандартного набора.
- Определите метаданные для каждого панорамного изображения в объекте
StreetViewPanoramaData
. - Реализуйте метод, который определяет данные и изображения пользовательской панорамы, и назначьте этот метод в качестве пользовательского обработчика в объекте
StreetViewPanorama
.
В следующих разделах объясняется этот процесс.
Создание пользовательских панорам
Каждая панорама Street View представляет собой изображение или набор изображений, обеспечивающих полный обзор на 360 градусов из одного места. Объект StreetViewPanorama
использует изображения, соответствующие равноугольной проекции (Plate Carrée). Такая проекция содержит 360 градусов горизонтального обзора (полный охват) и 180 градусов вертикального обзора (от прямого вверх до прямого вниз). Эти поля зрения дают изображение с соотношением сторон 2:1. Полная панорама показана ниже.
Панорамные изображения обычно получаются путем съемки нескольких фотографий с одной позиции и их сшивки с помощью программного обеспечения для панорамирования. (Для получения дополнительной информации см. раздел «Сравнение приложений для сшивания фотографий» в Википедии.) Такие изображения должны иметь единый локус «камеры», из которого берется каждое из панорамных изображений. Полученная 360-градусная панорама затем может определить проекцию на сферу, при этом изображение будет перенесено на двумерную поверхность сферы.
Рассматривать панораму как проекцию на сферу с прямолинейной системой координат выгодно при разделении изображения на прямолинейные фрагменты и подаче изображений на основе вычисленных координат фрагментов.
Создание пользовательских фрагментов панорамы
Просмотр улиц также поддерживает различные уровни детализации изображения за счет использования элемента управления масштабированием, который позволяет увеличивать и уменьшать масштаб изображения по умолчанию. Обычно Street View обеспечивает пять уровней разрешения масштабирования для любого панорамного изображения. Если бы вы полагались на одно панорамное изображение для обслуживания всех уровней масштабирования, такое изображение либо обязательно было бы довольно большим и значительно замедляло работу вашего приложения, либо имело бы такое низкое разрешение при более высоких уровнях масштабирования, что вы бы использовали изображение с плохой пикселизацией. . Однако, к счастью, мы можем использовать аналогичный шаблон проектирования, который используется для обслуживания фрагментов карты 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
, если вы хотите отображать пользовательские панорамы, так как такая позиция будет указывать службе Street View запросить изображения Street View по умолчанию рядом с этим местоположением. Вместо этого установите эту позицию в поле location.latLng
пользовательского объекта StreetViewPanoramaData
.
В следующем примере показана пользовательская панорама офиса Google в Сиднее. Обратите внимание, что в этом примере не используется карта или изображения Street View по умолчанию:
Машинопись
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> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="map"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly" defer ></script> </body> </html>
Попробуйте образец
Поставщик пользовательской панорамы возвращает соответствующую плитку с учетом переданного идентификатора панорамы, уровня масштабирования и координат плитки панорамы. Поскольку выбор изображения зависит от этих переданных значений, полезно называть изображения, которые можно выбирать программно с учетом этих переданных значений, например pano _ zoom _ tileX _ tileY .png
.
В следующем примере к изображению добавляется еще одна стрелка в дополнение к стрелкам навигации Street View по умолчанию, которая указывает на Google Sydney и ссылается на пользовательские изображения:
Машинопись
let panorama: google.maps.StreetViewPanorama; // StreetViewPanoramaData of a panorama just outside the Google Sydney office. let outsideGoogle: google.maps.StreetViewPanoramaData; // StreetViewPanoramaData for a custom panorama: the Google Sydney reception. function getReceptionPanoramaData(): google.maps.StreetViewPanoramaData { return { location: { pano: "reception", // The ID for this custom panorama. description: "Google Sydney - Reception", latLng: new google.maps.LatLng(-33.86684, 151.19583), }, links: [ { heading: 195, description: "Exit", pano: (outsideGoogle.location as google.maps.StreetViewLocation).pano, }, ], copyright: "Imagery (c) 2010 Google", tiles: { tileSize: new google.maps.Size(1024, 512), worldSize: new google.maps.Size(2048, 1024), centerHeading: 105, getTileUrl: function ( pano: string, zoom: number, tileX: number, tileY: number ): string { return ( "https://developers.google.com/maps/documentation/javascript/examples/full/images/" + "panoReception1024-" + zoom + "-" + tileX + "-" + tileY + ".jpg" ); }, }, }; } function initPanorama() { panorama = new google.maps.StreetViewPanorama( document.getElementById("street-view") as HTMLElement, { pano: (outsideGoogle.location as google.maps.StreetViewLocation).pano } ); // Register a provider for the custom panorama. panorama.registerPanoProvider( (pano: string): google.maps.StreetViewPanoramaData => { if (pano === "reception") { return getReceptionPanoramaData(); } // @ts-ignore TODO fix typings return null; } ); // Add a link to our custom panorama from outside the Google Sydney office. panorama.addListener("links_changed", () => { if ( panorama.getPano() === (outsideGoogle.location as google.maps.StreetViewLocation).pano ) { panorama.getLinks().push({ description: "Google Sydney", heading: 25, pano: "reception", }); } }); } function initMap(): void { // Use the Street View service to find a pano ID on Pirrama Rd, outside the // Google office. new google.maps.StreetViewService() .getPanorama({ location: { lat: -33.867386, lng: 151.195767 } }) .then(({ data }: google.maps.StreetViewResponse) => { outsideGoogle = data; initPanorama(); }); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
let panorama; // StreetViewPanoramaData of a panorama just outside the Google Sydney office. let outsideGoogle; // StreetViewPanoramaData for a custom panorama: the Google Sydney reception. function getReceptionPanoramaData() { return { location: { pano: "reception", // The ID for this custom panorama. description: "Google Sydney - Reception", latLng: new google.maps.LatLng(-33.86684, 151.19583), }, links: [ { heading: 195, description: "Exit", pano: outsideGoogle.location.pano, }, ], copyright: "Imagery (c) 2010 Google", tiles: { tileSize: new google.maps.Size(1024, 512), worldSize: new google.maps.Size(2048, 1024), centerHeading: 105, getTileUrl: function (pano, zoom, tileX, tileY) { return ( "https://developers.google.com/maps/documentation/javascript/examples/full/images/" + "panoReception1024-" + zoom + "-" + tileX + "-" + tileY + ".jpg" ); }, }, }; } function initPanorama() { panorama = new google.maps.StreetViewPanorama( document.getElementById("street-view"), { pano: outsideGoogle.location.pano }, ); // Register a provider for the custom panorama. panorama.registerPanoProvider((pano) => { if (pano === "reception") { return getReceptionPanoramaData(); } // @ts-ignore TODO fix typings return null; }); // Add a link to our custom panorama from outside the Google Sydney office. panorama.addListener("links_changed", () => { if (panorama.getPano() === outsideGoogle.location.pano) { panorama.getLinks().push({ description: "Google Sydney", heading: 25, pano: "reception", }); } }); } function initMap() { // Use the Street View service to find a pano ID on Pirrama Rd, outside the // Google office. new google.maps.StreetViewService() .getPanorama({ location: { lat: -33.867386, lng: 151.195767 } }) .then(({ data }) => { outsideGoogle = data; initPanorama(); }); } window.initMap = initMap;
CSS
html, body { height: 100%; margin: 0; padding: 0; } #street-view { height: 100%; }
HTML
<html> <head> <title>Custom Street View Panorama Tiles</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="street-view"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly" defer ></script> </body> </html>