개요
Google 스트리트 뷰는 지정된 도로부터 지도에 표시되는 영역
전반에 걸쳐 360도 파노라마 뷰를 제공합니다. 스트리트 뷰의 API 서비스 범위는 Google 지도 애플리케이션(https://maps.google.com/
)의 서비스 범위와 동일합니다. 현재 스트리트 뷰가 지원되는 도시의 목록은 Google 지도 웹사이트에서 확인할 수 있습니다.
아래는 샘플 스트리트 뷰 이미지입니다.
Maps JavaScript API는 Google 지도 스트리트 뷰에서 사용되는 이미지를 얻고 조작하기 위한 스트리트 뷰 서비스를 제공합니다. 스트리트 뷰 서비스는 기본적으로 브라우저 내에서 지원됩니다.
스트리트 뷰 지도 사용
스트리트 뷰는 독립형 DOM 요소 내에서 사용할 수 있지만 대부분의 경우 지도의 위치를 나타낼 때 유용합니다. 기본적으로 스트리트 뷰는 지도에서 사용 설정되며 스트리트 뷰 페그맨 컨트롤이 탐색(확대/축소 및 화면 이동) 컨트롤 내에 통합되어 표시됩니다. streetViewControl
을 false
로 설정하여 이 컨트롤을 지도의 MapOptions
내에 숨길 수도 있습니다. 또한 Map
의 streetViewControlOptions.position
속성을 새 ControlPosition
으로 설정하여 스트리트 뷰 컨트롤의 기본 위치를 변경할 수 있습니다.
스트리트 뷰 페그맨 컨트롤을 사용하면 지도 내에서 직접 스트리트 뷰 파노라마를 볼 수 있습니다. 사용자가 페그맨을 길게 클릭하면 스트리트 뷰가 사용 설정된 거리 주위에 파란색 윤곽선을 표시하도록 지도가 업데이트되어 Google 지도 앱과 유사한 사용자 경험을 제공합니다.
사용자가 거리 위에 페그맨 마커를 도로에 놓으면 표시된 위치의 스트리트 뷰 파노라마를 표시하도록 지도가 업데이트됩니다.
스트리트 뷰 파노라마
스트리트 뷰 이미지는 스트리트 뷰 '뷰어'에 대한 API 인터페이스를 제공하는 StreetViewPanorama
객체를 사용하여 지원됩니다. 각 지도에는 기본 스트리트 뷰 파노라마가 포함되며 기본 스트리트 뷰 파노라마는 지도의 getStreetView()
메서드를 호출하여 가져올 수 있습니다. 지도의 streetViewControl
옵션을 true
로 설정하여 스트리트 뷰 컨트롤을 지도에 추가하면 페그맨 컨트롤이 기본 스트리트 뷰 파노라마에 자동으로 연결됩니다.
또한 StreetViewPanorama
객체를 직접 만들고 지도의 streetView
속성을 이 생성된 객체로 명시적으로 설정하여 지도에서 기본값 대신 이 객체를 사용하도록 설정할 수 있습니다. 지도와 파노라마 간 오버레이의 자동 공유와 같은 기본 동작을 수정하려는 경우 기본 파노라마를 재정의할 수도 있습니다. 아래의 스트리트 뷰 내의 오버레이를 참고하세요.
스트리트 뷰 컨테이너
대신 별도의 DOM 요소(<div>
요소일 때가 많음) 내에 StreetViewPanorama
를 표시할 수도 있습니다.
StreetViewPanorama
의 생성자 내에 DOM 요소를 전달하면 됩니다. 이미지를 최적으로 표시하려면 200x200픽셀 이상의 크기를 권장합니다.
참고: 스트리트 뷰 기능은 지도와 함께 사용하도록 설계되었지만 따로 사용해도 됩니다. 지도 없이 독립적으로 스트리트 뷰 객체를 사용할 수도 있습니다.
스트리트 뷰 위치 및 시점(POV)
또한 StreetViewPanorama
생성자를 사용하면 StreetViewOptions
매개변수를 사용하여 스트리트 뷰 위치 및 시점을 설정할 수 있습니다. 생성 후 객체에서
setPosition()
및 setPov()
를 호출하여 위치 및 POV를 변경할 수도 있습니다.
스트리트 뷰 위치는 이미지의 카메라 초점의 위치를 정의하지만 해당 이미지에 대한 카메라의 방향을 정의하지는 않습니다. 카메라의 방향은 StreetViewPov
객체가 다음 두 속성을 지정하여 정의합니다.
heading
(기본값0
)은 정북을 기준으로 카메라 초점 주위의 회전 각도를 도 단위로 정의합니다. 방향은 시계 방향으로 측정됩니다(90도는 정동입니다).pitch
(기본값0
)는 카메라의 초기 기본 피치를 기준으로 '위' 또는 '아래' 각도 편차를 정의합니다. 기본 피치는 항상 그렇지는 않지만 주로 평평한 수평입니다. 예를 들어 언덕에서 촬영한 이미지의 기본 피치는 수평이 아닐 가능성이 높습니다. 피치 각도는 위를 향할 때는 양수 값으로 측정되고(기본 피치에 수직으로 똑바로 위를 향하는 경우 +90도), 아래를 향할 때는 음수 값으로 측정됩니다(기본 피치에 수직으로 똑바로 아래를 향하는 경우 -90도).
StreetViewPov
객체는 스트리트 뷰 카메라의 시점을 결정하기 위해 가장 많이 사용됩니다. 또한 StreetViewPanorama.getPhotographerPov()
메서드를 사용하여 사진가의 시점(일반적으로 차량 또는 세발자전거에서 바라보는 방향)을 결정할 수도 있습니다.
다음 코드는 펜웨이 공원의 초기 뷰가 포함된 보스턴의 지도를 표시합니다. 페그맨을 선택하고 지도에서 지원되는 위치로 드래그하면 스트리트 뷰 파노라마가 변경됩니다.
TypeScript
function initialize() { const fenway = { lat: 42.345573, lng: -71.098326 }; const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { center: fenway, zoom: 14, } ); const panorama = new google.maps.StreetViewPanorama( document.getElementById("pano") as HTMLElement, { position: fenway, pov: { heading: 34, pitch: 10, }, } ); map.setStreetView(panorama); } declare global { interface Window { initialize: () => void; } } window.initialize = initialize;
JavaScript
function initialize() { const fenway = { lat: 42.345573, lng: -71.098326 }; const map = new google.maps.Map(document.getElementById("map"), { center: fenway, zoom: 14, }); const panorama = new google.maps.StreetViewPanorama( document.getElementById("pano"), { position: fenway, pov: { heading: 34, pitch: 10, }, }, ); map.setStreetView(panorama); } window.initialize = initialize;
CSS
html, body { height: 100%; margin: 0; padding: 0; } #map, #pano { float: left; height: 100%; width: 50%; }
HTML
<html> <head> <title>Street View split-map-panes</title> <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="map"></div> <div id="pano"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initialize&v=weekly" defer ></script> </body> </html>
샘플 사용해 보기
휴대기기에서 모션 추적
API는 기기 방향 이벤트를 지원하는 기기에서 기기 움직임에 따라 사용자가 스트리트 뷰 시점을 변경할 수 있는 기능을 제공합니다. 사용자는 기기를 움직여 주변을 둘러볼 수 있습니다. 이러한 기능을 모션 추적 또는 기기 회전 추적이라고 합니다.
앱 개발자는 다음과 같이 기본 동작을 변경할 수 있습니다.
- 모션 추적 기능을 사용 설정 또는 사용 중지합니다. 기본적으로 모션 추적을 지원하는 기기에는 이 기능이 사용 설정되어 있습니다. 다음 샘플은 모션 추적을 사용 중지하지만 모션 추적 컨트롤은 표시합니다.
사용자는 컨트롤을 탭하여 모션 추적을 켤 수 있습니다.
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
위치에 고정된 '거리 수준'에 표시됩니다. 예를 들어 마커는 스트리트 뷰 파노라마 내 위치의 수평면에 꼬리가 고정되어 표시됩니다.
현재 스트리트 뷰 파노라마에서 지원되는 오버레이 유형은 Marker
, InfoWindow
, 맞춤 OverlayView
로 제한됩니다. 지도에 표시하는 오버레이는 파노라마를 Map
객체의 대체 항목으로 간주하고 setMap()
을 호출하고 StreetViewPanorama
를 지도 대신 인수로 전달하여 스트리트 뷰 파노라마에 표시될 수도 있습니다. 마찬가지로 open()
을 호출하고 지도 대신 StreetViewPanorama()
를 전달하여 스트리트 뷰 파노라마 내에 정보 창을 열 수도 있습니다.
또한 기본 StreetViewPanorama
로 지도를 만들 때 지도에 생성된 모든 마커는 해당 파노라마가 표시된 경우 지도에 연결된 스트리트 뷰 파노라마와 자동으로 공유됩니다. 기본 스트리트 뷰 파노라마를 가져오려면 Map
객체에서 getStreetView()
를 호출하세요. 지도의 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); const cafeIcon = document.createElement("img"); cafeIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/cafe_icon.svg"; const dollarIcon = document.createElement("img"); dollarIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bank_icon.svg"; const busIcon = document.createElement("img"); busIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bus_icon.svg"; // Set up the markers on the map const cafeMarker = new google.maps.Marker({ position: { lat: 40.730031, lng: -73.991428 }, map, title: "Cafe", icon: cafeIcon.src, }); const bankMarker = new google.maps.Marker({ position: { lat: 40.729681, lng: -73.991138 }, map, title: "Bank", icon: dollarIcon.src, }); const busMarker = new google.maps.Marker({ position: { lat: 40.729559, lng: -73.990741 }, map, title: "Bus Stop", icon: busIcon.src, }); // We get the map's default panorama and set up some defaults. // Note that we don't yet set it visible. panorama = map.getStreetView()!; // TODO fix type panorama.setPosition(astorPlace); panorama.setPov( /** @type {google.maps.StreetViewPov} */ { heading: 265, pitch: 0, } ); } function toggleStreetView(): void { const toggle = panorama.getVisible(); if (toggle == false) { panorama.setVisible(true); } else { panorama.setVisible(false); } } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
let panorama; function initMap() { const astorPlace = { lat: 40.729884, lng: -73.990988 }; // Set up the map const map = new google.maps.Map(document.getElementById("map"), { center: astorPlace, zoom: 18, streetViewControl: false, }); document.getElementById("toggle").addEventListener("click", toggleStreetView); const cafeIcon = document.createElement("img"); cafeIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/cafe_icon.svg"; const dollarIcon = document.createElement("img"); dollarIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bank_icon.svg"; const busIcon = document.createElement("img"); busIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bus_icon.svg"; // Set up the markers on the map const cafeMarker = new google.maps.Marker({ position: { lat: 40.730031, lng: -73.991428 }, map, title: "Cafe", icon: cafeIcon.src, }); const bankMarker = new google.maps.Marker({ position: { lat: 40.729681, lng: -73.991138 }, map, title: "Bank", icon: dollarIcon.src, }); const busMarker = new google.maps.Marker({ position: { lat: 40.729559, lng: -73.990741 }, map, title: "Bus Stop", icon: busIcon.src, }); // We get the map's default panorama and set up some defaults. // Note that we don't yet set it visible. panorama = map.getStreetView(); // TODO fix type panorama.setPosition(astorPlace); panorama.setPov( /** @type {google.maps.StreetViewPov} */ { heading: 265, pitch: 0, }, ); } function toggleStreetView() { const toggle = panorama.getVisible(); if (toggle == false) { panorama.setVisible(true); } else { panorama.setVisible(false); } } window.initMap = initMap;
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ #map { height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } #floating-panel { position: absolute; top: 10px; left: 25%; z-index: 5; background-color: #fff; padding: 5px; border: 1px solid #999; text-align: center; font-family: "Roboto", "sans-serif"; line-height: 30px; padding-left: 10px; } #floating-panel { margin-left: -100px; }
HTML
<html> <head> <title>Overlays Within Street View</title> <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="floating-panel"> <input type="button" value="Toggle Street View" id="toggle" /> </div> <div id="map"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&libraries=marker&v=weekly" defer ></script> </body> </html>
샘플 사용해 보기
스트리트 뷰 이벤트
스트리트 뷰를 탐색하거나 방향을 바꿀 때 StreetViewPanorama
상태의 변화를 나타내는 여러 이벤트를 모니터링할 수 있습니다.
pano_changed
는 개별 pano ID가 변경될 때마다 실행됩니다. 이 이벤트가 발생했더라도 이벤트가 실행되는 시점에 파노라마 내의 연결 데이터(예: 링크)가 변경되지 않았을 수도 있습니다. 이 이벤트는 pano ID가 변경되었다는 것만 나타냅니다. 이 파노라마를 나타내는 데 사용할 수 있는 pano ID는 현재 브라우저 세션 내에서만 유지됩니다.position_changed
는 파노라마의 기본(LatLng
) 위치가 변경될 때마다 실행됩니다. 파노라마를 회전해도 이 이벤트가 실행되지 않습니다. API가 가장 가까운 pano ID를 파노라마 위치에 자동으로 연결하므로 연결된 pano ID를 변경하지 않고 파노라마의 기본 위치를 변경할 수 있습니다.pov_changed
는 스트리트 뷰의StreetViewPov
가 변경될 때마다 실행됩니다. 위치와 pano ID가 변경되지 않아도 이 이벤트가 실행될 수 있습니다.links_changed
는 스트리트 뷰의 링크가 변경될 때마다 실행됩니다. 이 이벤트는pano_changed
를 통해 pano ID 변경이 표시된 후 비동기식으로 실행됩니다.visible_changed
는 스트리트 뷰의 표시 여부가 변경될 때마다 실행됩니다. 이 이벤트는pano_changed
를 통해 pano ID 변경이 표시된 후 비동기식으로 실행됩니다.
다음 코드는 기본 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"> </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 지도에서 위치를 여는 링크를 제공합니다.addressControlOptions
필드 내에StreetViewAddressControlOptions
를 제공하여 컨트롤의 모양을 변경할 수 있습니다.fullscreenControl
을 사용하면 전체 화면 모드에서 스트리트 뷰를 열 수 있습니다.fullscreenControlOptions
필드 내에FullscreenControlOptions
를 제공하여 컨트롤의 모양을 변경할 수 있습니다.motionTrackingControl
을 사용하면 휴대기기에서 모션 추적을 사용 설정하거나 사용 중지할 수 있습니다. 이 컨트롤은 기기 방향 이벤트를 지원하는 기기에만 표시됩니다. 기본적으로 이 컨트롤은 파노라마의 오른쪽 하단에 표시됩니다.MotionTrackingControlOptions
를 제공하여 컨트롤의 위치를 변경할 수 있습니다. 자세한 내용은 모션 추적에 관한 섹션을 참고하세요.linksControl
은 이미지에 인접한 파노라마 이미지로 이동하기 위한 가이드 화살표를 표시합니다.- 닫기 컨트롤을 사용하면 사용자가 스트리트 뷰 뷰어를 닫을 수 있습니다.
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 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>
샘플 사용해 보기
스트리트 뷰 데이터에 직접 액세스
지도/파노라마를 직접 조작하지 않고 스트리트 뷰 데이터의 사용 가능 여부를 프로그래매틱 방식으로 확인하거나 특정 파노라마에 대한 정보를 반환할 수 있습니다. Google의 스트리트 뷰 서비스에 저장된 데이터에 대한 인터페이스를 제공하는 StreetViewService
객체를 사용하면 됩니다.
스트리트 뷰 서비스 요청
Google Maps API는 외부 서버를 호출해야 하므로 스트리트 뷰 서비스 액세스는 비동기식입니다. 따라서 요청 완료 시 실행할 콜백 메서드를 전달해야 합니다. 이 콜백 메서드가 결과를 처리합니다.
StreetViewPanoRequest
또는 StreetViewLocationRequest
를 사용하여 StreetViewService
에 대한 요청을 시작할 수 있습니다.
StreetViewPanoRequest
를 사용하는 요청은 파노라마를 고유하게 나타내는 참조 ID가 해당 파노라마 데이터를 반환합니다. 이 참조 ID는 해당 파노라마 이미지가 표시되는 동안에만 유지됩니다.
StreetViewLocationRequest
를 사용하는 요청은 다음 매개변수를 사용하여 지정된 위치에서 파노라마 데이터를 검색합니다.
location
은 파노라마를 검색할 위치(위도 및 경도)를 지정합니다.preference
는 반경 내에서 파노라마를 찾아야 하는 환경설정(제공된 위치에 가장 가까운 파노라마 또는 반경 내에서 가장 좋은 파노라마)을 지정합니다.radius
는 지정된 위도와 경도를 중심으로 파노라마를 검색할 반경을 미터 단위로 설정합니다. 입력하지 않을 경우 기본값은 50입니다.source
는 검색할 파노라마의 출처를 지정합니다. 유효한 값은 다음과 같습니다.default
는 스트리트 뷰에 기본 출처를 사용합니다. 검색은 특정 출처로 제한되지 않습니다.outdoor
는 야외 모음으로 검색을 제한합니다. 지정된 위치에 야외 파노라마가 없을 수도 있습니다.
스트리트 뷰 서비스 응답
getPanorama()
함수에는 스트리트 뷰 서비스에서 결과를 가져올 때 실행할 콜백 함수가 필요합니다. 콜백 함수는 StreetViewPanoramaData
객체 내의 파노라마 데이터 집합 및 요청의 상태를 나타내는 StreetViewStatus
코드를 순서대로 반환합니다.
StreetViewPanoramaData
객체 사양에는 스트리트 뷰 파노라마에 대한 다음과 같은 형태의 메타데이터가 포함됩니다.
{ "location": { "latLng": LatLng, "description": string, "pano": string }, "copyright": string, "links": [{ "heading": number, "description": string, "pano": string, "roadColor": string, "roadOpacity": number }], "tiles": { "worldSize": Size, "tileSize": Size, "centerHeading": number } }
이 데이터 객체는 StreetViewPanorama
객체 자체가 아닙니다. 이 데이터를 사용하여 스트리트 뷰 객체를 만들려면 StreetViewPanorama
를 만들고 setPano()
를 호출하여 반환된 location.pano
필드에 표시된 ID에 전달합니다.
status
코드는 다음 값 중 하나를 반환할 수 있습니다.
OK
는 서비스가 일치하는 파노라마를 찾았음을 나타냅니다.ZERO_RESULTS
는 서비스가 전달된 기준과 일치하는 파노라마를 찾지 못했음을 나타냅니다.UNKNOWN_ERROR
는 정확한 이유는 알 수 없지만 스트리트 뷰 요청을 처리하지 못했음을 나타냅니다.
다음 코드는 클릭하면 해당 위치의 StreetViewPanorama
를 표시하는 마커를 만들어서 지도의 사용자 클릭에 응답하는 StreetViewService
를 만듭니다. 이 코드에서는 서비스에서 반환된 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 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>
샘플 사용해 보기
맞춤 스트리트 뷰 파노라마 제공
Maps JavaScript API를 사용하면 StreetViewPanorama
객체 내에 맞춤 파노라마를 표시할 수 있습니다. 맞춤 파노라마를 사용하면 건물의 내부, 경치가 좋은 곳과 같이 상상 가능한 모든 것을 표시할 수 있습니다. 이 맞춤 파노라마를 Google의 기존 스트리트 뷰 파노라마에 연결할 수도 있습니다.
맞춤 파노라마 이미지의 집합을 설정하려면 다음 단계를 따르세요.
- 각 맞춤 파노라마의 기본 파노라마 이미지를 만듭니다. 이 기본 이미지는 확대된 이미지를 제공하고자 하는 최고 해상도의 이미지여야 합니다.
- (선택사항이지만 권장됨) 기본 이미지에서 다양한 확대/축소 수준으로 파노라마 타일의 집합을 만듭니다.
- 맞춤 파노라마 간의 링크를 만듭니다.
- (선택사항) Google의 기존 스트리트 뷰 이미지 내에 '기본' 파노라마를 지정하고 맞춤 집합에서 표준 집합으로 또는 그 반대로 링크를 맞춤설정합니다.
StreetViewPanoramaData
객체 내에 각 파노라마 이미지의 메타데이터를 정의합니다.- 맞춤 파노라마 데이터를 확인하는 메서드를 구현하고 그 메서드를
StreetViewPanorama
객체 내에 맞춤 핸들러로 지정합니다.
다음 섹션에 이 과정이 설명되어 있습니다.
맞춤 파노라마 만들기
각 스트리트 뷰 파노라마는 단일 이미지 또는 이미지 집합으로, 단일 위치에서 완전한 360도 뷰를 제공합니다.
StreetViewPanorama
객체는 등장방형 도법(플라트 카레)을 따르는 이미지를 사용합니다. 이 도법에는 360도 가로 뷰(완전한 래핑)와 180도 세로 뷰(위에서 아래로 수직)가 포함됩니다. 이 시야각으로 인해 가로세로 비율이 2:1인 이미지가 생성됩니다. 완전히 래핑된 파노라마가 아래에 표시되어 있습니다.
파노라마 이미지는 일반적으로 한 위치에서 여러 장의 사진을 찍은 다음 파노라마 소프트웨어를 사용해 서로 연결하여 만듭니다. (자세한 내용은 위키백과의 사진 연결 애플리케이션 비교를 참고하세요.) 이러한 이미지는 하나의 '카메라' 중심을 공유하고 여기에서 각 파노라마 이미지를 촬영해야 합니다. 그런 다음 그 결과 얻어지는 360도 파노라마 이미지로 이미지가 구체의 2차원 표면에 래핑되는 도법을 정의할 수 있습니다.
파노라마를 구에서 직선 좌표계를 사용하여 도법으로 처리하면 이미지를 직선 타일로 구분하고 계산된 타일 좌표를 기준으로 이미지를 표시할 때 편리합니다.
맞춤 파노라마 타일 만들기
스트리트 뷰는 또한 기본 뷰에서 확대/축소할 수 있는 확대/축소 컨트롤을 사용하여 다양한 수준의 이미지 세부정보를 지원합니다. 일반적으로 스트리트 뷰는 지정된 파노라마 이미지에 다섯 가지 수준의 확대/축소 해상도를 제공합니다. 단일 파노라마 이미지를 사용하여 모든 확대/축소 수준을 제공하는 경우 이미지의 크기가 상당히 커서 애플리케이션이 크게 느려지거나, 확대/축소 수준을 올릴 경우 해상도가 낮아서 심하게 모자이크화된 이미지가 표시될 가능성이 높습니다. 하지만 다행히 여러 확대/축소 수준에서 Google의 지도 타일을 표시하는 데 사용된 것과 유사한 디자인 패턴을 사용하여 각 확대/축소 수준의 파노라마를 적절한 해상도 이미지로 제공할 수 있습니다.
StreetViewPanorama
가 처음 로드되면 기본적으로 확대/축소 수준 1에서 파노라마 가로 너비의 25%(호의 90도)로 구성된 이미지가 표시됩니다. 이 뷰는 대략 일반 사람의 시야각에 해당합니다. 이 기본 뷰에서 '축소'하면 호가 더 넓어지고 확대하면 더 작은 호로 시야각이 좁아집니다. StreetViewPanorama
는 선택된 확대/축소 수준에 적절한 시야각을 자동으로 계산한 다음 대략 수평 시야각의 크기와 일치하는 타일 집합을 선택하여 해당 해상도에 가장 적절한 이미지를 선택합니다. 다음 시야각은 스트리트 뷰 확대/축소 수준에 매핑됩니다.
스트리트 뷰 확대/축소 수준 | 시야각 |
---|---|
0 | 180 |
1(기본값) | 90 |
2 | 45 |
3 | 22.5 |
4 | 11.25 |
스트리트 뷰 내에 표시되는 이미지의 크기는 전적으로 스트리트 뷰 컨테이너의 화면 크기(너비)에 따라 달라집니다. 더 넓은 컨테이너를 제공해도 서비스가 계속해서 지정된 모든 확대/축소 수준에서 동일한 시야각을 제공하지만 해당 해상도에 더욱 적절한 타일을 선택할 수도 있습니다.
각 파노라마가 등정방형 도법으로 구성되므로 파노라마 타일을 만드는 것은 비교적 쉽습니다. 도법에서 가로세로 비율이 2:1인 이미지를 제공하므로 비율이 2:1인 타일이 사용하기 더 쉽지만 시야각이 정사각형이기 때문에 정사각형 타일이 정사각형 지도에서 더 나은 성능을 제공할 수도 있습니다.
2:1 타일의 경우 전체 파노라마가 포함된 단일 이미지는 확대/축소 수준 0에서 전체 파노라마 '세계'(기본 이미지)를 나타내며, 확대/축소 수준이 증가할 때마다 4개의 zoomLevel 타일을 제공합니다. (예를 들어 확대/축소 수준 2에서 전체 파노라마는 16개의 타일로 구성됩니다.) 참고: 스트리트 뷰 타일의 확대/축소 수준은 스트리트 뷰 컨트롤을 사용하여 제공된 확대/축소 수준과 정확히 일치하지 않습니다. 대신 스트리트 뷰 컨트롤 확대/축소 수준에서 시야각을 선택하고 여기에서 적절한 타일이 선택됩니다.
일반적으로 프로그래매틱 방식으로 선택할 수 있도록 이미지 타일의 이름을 지정하는 것이 좋습니다. 이러한 이름 지정 스킴은 아래 맞춤 파노라마 요청 처리에 설명되어 있습니다.
맞춤 파노라마 요청 처리
맞춤 파노라마를 사용하려면 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
객체를 반환합니다.
참고: 맞춤 파노라마를 표시할 때 StreetViewPanorama
에서 직접 position
을 설정하지 마세요. 이러한 위치는 스트리트 뷰 서비스가 해당 위치에 가까운 기본 스트리트 뷰 이미지를 요청하도록 지시하기 때문입니다. 대신 맞춤 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 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>
샘플 사용해 보기
맞춤 파노라마 제공자는 전달된 파노라마 ID, 확대/축소 수준, 파노라마 타일 좌표를 고려하여 적절한 타일을 반환합니다.
이렇게 전달된 값에 따라 이미지가 선택되므로 이미지에 이러한 전달된 값을 프로그래매틱 방식으로 선택할 수 있는 이름(예: pano_zoom_tileX_tileY.png
)을 지정하는 것이 유용합니다.
다음 예에서는 이미지에 기본 스트리트 뷰 탐색 화살표 외에 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", // The ID for this custom panorama. description: "Google Sydney - Reception", latLng: new google.maps.LatLng(-33.86684, 151.19583), }, links: [ { heading: 195, description: "Exit", pano: outsideGoogle.location.pano, }, ], copyright: "Imagery (c) 2010 Google", tiles: { tileSize: new google.maps.Size(1024, 512), worldSize: new google.maps.Size(2048, 1024), centerHeading: 105, getTileUrl: function (pano, zoom, tileX, tileY) { return ( "https://developers.google.com/maps/documentation/javascript/examples/full/images/" + "panoReception1024-" + zoom + "-" + tileX + "-" + tileY + ".jpg" ); }, }, }; } function initPanorama() { panorama = new google.maps.StreetViewPanorama( document.getElementById("street-view"), { pano: outsideGoogle.location.pano }, ); // Register a provider for the custom panorama. panorama.registerPanoProvider((pano) => { if (pano === "reception") { return getReceptionPanoramaData(); } // @ts-ignore TODO fix typings return null; }); // Add a link to our custom panorama from outside the Google Sydney office. panorama.addListener("links_changed", () => { if (panorama.getPano() === outsideGoogle.location.pano) { panorama.getLinks().push({ description: "Google Sydney", heading: 25, pano: "reception", }); } }); } function initMap() { // Use the Street View service to find a pano ID on Pirrama Rd, outside the // Google office. new google.maps.StreetViewService() .getPanorama({ location: { lat: -33.867386, lng: 151.195767 } }) .then(({ data }) => { outsideGoogle = data; initPanorama(); }); } window.initMap = initMap;
CSS
html, body { height: 100%; margin: 0; padding: 0; } #street-view { height: 100%; }
HTML
<html> <head> <title>Custom Street View Panorama Tiles</title> <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="street-view"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly" defer ></script> </body> </html>