Stay organized with collections Save and categorize content based on your preferences.
Overview Also see the Maps JavaScript API Reference: Rendering, Service)Google Street View provides panoramic 360 degree views from designated roads throughout its coverage area. Street View's API coverage is the same as that for the Google Maps application (https://maps.google.com/
). The list of currently supported cities for Street View is available at the Google Maps website.
A sample Street View image is shown below.
The Maps JavaScript API provides a Street View service for obtaining and manipulating the imagery used in Google Maps Street View. This Street View service is supported natively within the browser.
Street View Map UsageAlthough Street View can be used within a standalone DOM element, it is most useful when indicating a location on a map. By default, Street View is enabled on a map, and a Street View Pegman control appears integrated within the navigation (zoom and pan) controls. You may hide this control within the map's MapOptions
by setting streetViewControl
to false
. You may also change the default position of the Street View control by setting the Map
's streetViewControlOptions.position
property to a new ControlPosition
.
The Street View Pegman control allows you to view Street View panoramas directly within the map. When the user clicks and holds the Pegman, the map updates to show blue outlines around Street View-enabled streets, offering a user experience similar to the Google Maps app.
When the user drops the Pegman marker onto a street, the map updates to display a Street View panorama of the indicated location.
Street View Panoramas Note: Only Street View panoramas generated with theStreetViewPanorama
object are billed. The built-in Street View experience based on the Street View Pegman control, and the StreetViewService
, are not billed. For more information, see Pricing.
Street View images are supported through use of the StreetViewPanorama
object, which provides an API interface to a Street View "viewer." Each map contains a default Street View panorama, which you can retrieve by calling the map's getStreetView()
method. When you add a Street View control to the map by setting its streetViewControl
option to true
, you automatically connect the Pegman control to this default Street View panorama.
You may also create your own StreetViewPanorama
object and set the map to use that instead of the default, by setting the map's streetView
property explicitly to that constructed object. You may wish to override the default panorama if you want to modify default behavior, such as the automatic sharing of overlays between the map and the panorama. (See Overlays within Street View below.)
You may instead wish to display a StreetViewPanorama
within a separate DOM element, often a <div>
element. Simply pass the DOM element within the StreetViewPanorama
's constructor. For optimum display of images, we recommend a minimum size of 200 pixels by 200 pixels.
Note: Although Street View functionality is designed to be used in conjunction with a map, this usage is not required. You may use a standalone Street View object without a map.
Street View Locations and Point-of-View (POV)The StreetViewPanorama
constructor also allows you to set the Street View location and point of view using the StreetViewOptions
parameter. You may call setPosition()
and setPov()
on the object after construction to change its location and POV.
The Street View location defines the placement of the camera focus for an image, but it does not define the orientation of the camera for that image. For that purpose, the StreetViewPov
object defines two properties:
heading
(default 0
) defines the rotation angle around the camera locus in degrees relative from true north. Headings are measured clockwise (90 degrees is true east).pitch
(default 0
) defines the angle variance "up" or "down" from the camera's initial default pitch, which is often (but not always) flat horizontal. (For example, an image taken on a hill will likely exhibit a default pitch that is not horizontal.) Pitch angles are measured with positive values looking up (to +90 degrees straight up and orthogonal to the default pitch) and negative values looking down (to -90 degrees straight down and orthogonal to the default pitch).The StreetViewPov
object is most often used to determine the point of view of the Street View camera. You can also determine the point-of-view of the photographer — typically the direction the car or trike was facing — with the StreetViewPanorama.getPhotographerPov()
method.
The following code displays a map of Boston with an initial view of Fenway Park. Selecting the Pegman and dragging it to a supported location on the map will change the Street View panorama:
TypeScriptfunction 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;Note: Read the guide on using TypeScript and Google Maps. 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;Note: The JavaScript is compiled from the TypeScript snippet. 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>View example Try Sample Motion tracking on mobile devices
On devices that support device orientation events, the API offers users the ability to change the Street View point of view based on the movement of the device. Users can look around by moving their devices. This is called motion tracking or device rotation tracking.
As app developer, you can change the default behavior as follows:
var panorama = new google.maps.StreetViewPanorama( document.getElementById('pano'), { position: {lat: 37.869260, lng: -122.254811}, pov: {heading: 165, pitch: 0}, motionTracking: false });
Hide or show the motion tracking control. By default, the control is shown on devices that support motion tracking. The user can tap the control to turn motion tracking on or off. Note that the control will never appear if the device doesn't support motion tracking, regardless of the value of motionTrackingControl
.
The following sample disables both motion tracking and the motion tracking control. In this case, the user can't turn motion tracking on:
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
). The following sample sets the position of the control to left 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 } });
To see motion tracking in action, view the following sample on a mobile device (or any device that supports device orientation events):
The default StreetViewPanorama
object supports the native display of map overlays. Overlays generally appear at "street level" anchored at LatLng
positions. (Markers will appear with their tails anchored to the location's horizontal plane within the Street View panorama for example.)
Currently, the types of overlays which are supported on Street View panoramas are limited to Marker
s, InfoWindow
s and custom OverlayView
s. Overlays which you display on a map may be displayed on a Street View panorama by treating the panorama as a substitute for the Map
object, calling setMap()
and passing the StreetViewPanorama
as an argument instead of a map. Info windows similarly may be opened within a Street View panorama by calling open()
, passing the StreetViewPanorama()
instead of a map.
Additionally, when creating a map with a default StreetViewPanorama
, any markers created on a map are shared automatically with the map's associated Street View panorama, provided that panorama is visible. To retrieve the default Street View panorama, call getStreetView()
on the Map
object. Note that if you explicitly set the map's streetView
property to a StreetViewPanorama
of your own construction, you will override the default panorama.
The following example shows markers denoting various locations around Astor Place, New York City. Toggle the display to Street View to show the shared markers displaying within the 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;Note: Read the guide on using TypeScript and Google Maps. 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;Note: The JavaScript is compiled from the TypeScript snippet. 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>View example Try Sample Street View Events
When navigating between Street View or manipulating its orientation, you may wish to monitor several events that indicate changes to the StreetViewPanorama
's state:
pano_changed
fires whenever the individual pano ID changes. This event does not guarantee that any associated data within the panorama (such as the links) has also changed by the time this event is triggered; this event only indicates that a pano ID has changed. Note that the pano ID (which you can use to reference this panorama) is only stable within the current browser session.position_changed
fires whenever the underlying (LatLng
) position of the panorama changes. Rotating a panorama will not trigger this event. Note that you could change a panorama's underlying position without changing the associated pano ID, since the API will automatically associate the nearest pano ID to the panorama's position.pov_changed
fires whenever the Street View's StreetViewPov
changes. Note that this event may fire while the position, and pano ID, remain stable.links_changed
fires whenever the Street View's links change. Note that this event may fire asynchronously after a change in the pano ID indicated through pano_changed
.visible_changed
fires whenever the Street View's visibility changes. Note that this event may fire asynchronously after a change in the pano ID indicated through pano_changed
.The following code illustrates how these events can be handled to collect data about the underlying 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;Note: Read the guide on using TypeScript and Google Maps. 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;Note: The JavaScript is compiled from the TypeScript snippet. 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>View example Try Sample Street View Controls
When displaying a StreetViewPanorama
, a variety of controls appear on the panorama by default. You can enable or disable these controls by setting their appropriate fields within the StreetViewPanoramaOptions
to true
or false
:
panControl
provides a way to rotate the panorama. This control appears by default as a standard integrated compass and pan control. You may alter the control's position by providing PanControlOptions
within the panControlOptions
field.zoomControl
provides a way to zoom within the image. This control appears by default near the bottom right of the panorama. You can alter the control's appearance by providing ZoomControlOptions
within the zoomControlOptions
field.addressControl
provides a textual overlay indicating the address of the associated location, and offers a link to open the location in Google Maps. You can alter the control's appearance by providing StreetViewAddressControlOptions
within the addressControlOptions
field.fullscreenControl
offers the option to open Street View in fullscreen mode. You can alter the control's appearance by providing FullscreenControlOptions
within the fullscreenControlOptions
field.motionTrackingControl
offers the option to enable or disable motion tracking on mobile devices. This control appears only on devices that support device orientation events. By default, the control appears near the bottom right of the panorama. You can alter the control's position by providing MotionTrackingControlOptions
. For more information, see the section on motion tracking.linksControl
provides guide arrows on the image for traveling to adjacent panorama images.enableCloseButton
to true
or false
.The following example alters the controls displayed within the associated Street View and removes the view's links:
TypeScriptfunction 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;Note: Read the guide on using TypeScript and Google Maps. 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;Note: The JavaScript is compiled from the TypeScript snippet. 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>View example Try Sample Directly Accessing Street View Data
You may wish to programmatically determine the availability of Street View data, or return information about particular panoramas, without requiring direct manipulation of a map/panorama. You may do so using the StreetViewService
object, which provides an interface to the data stored in Google's Street View service.
Accessing the Street View service is asynchronous, since the Google Maps API needs to make a call to an external server. For that reason, you need to pass a callback method to execute upon completion of the request. This callback method processes the result.
You can initiate requests to the StreetViewService
using StreetViewPanoRequest
or StreetViewLocationRequest
.
A request using StreetViewPanoRequest
returns panorama data given a reference ID which uniquely identifies the panorama. Note that these reference IDs are only stable for the lifetime of the imagery of that panorama.
A request using StreetViewLocationRequest
searches for panorama data at a specified location, using the following parameters:
location
specifies the location (latitude and longitude) to search for a panorama.preference
sets a preference for which panorama should be found within the radius: the one nearest to the provided location, or the best one within the radius.radius
sets a radius, specified in meters, in which to search for a panorama, centered on the given latitude and longitude. Defaults to 50 when not supplied.source
specifies the source of panoramas to search. Valid values are:
default
uses the default sources for Street View; searches are not limited to specific sources.outdoor
limits searches to outdoor collections. Note that outdoor panoramas may not exist for the specified location.The function getPanorama()
needs a callback function to execute upon retrieval of a result from the Street View service. This callback function returns a set of panorama data within a StreetViewPanoramaData
object and a StreetViewStatus
code denoting the status of the request, in that order.
A StreetViewPanoramaData
object specification contains meta-data about a Street View panorama of the following form:
{ "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 } }
Note that this data object is not a StreetViewPanorama
object itself. To create a Street View object using this data, you would need to create a StreetViewPanorama
and call setPano()
, passing it the ID as noted in the returned location.pano
field.
The status
code may return one of the following values:
OK
indicates that the service found a matching panorama.ZERO_RESULTS
indicates that the service could not find a matching panorama with the passed criteria.UNKNOWN_ERROR
indicates that a Street View request could not be processed, though the exact reason is unknown.The following code creates a StreetViewService
that responds to user clicks on a map by creating markers which, when clicked, display a StreetViewPanorama
of that location. The code uses the contents of StreetViewPanoramaData
returned from the service.
/* * 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;Note: Read the guide on using TypeScript and Google Maps. 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;Note: The JavaScript is compiled from the TypeScript snippet. 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>View example Try Sample Providing Custom Street View Panoramas
The Maps JavaScript API supports the display of custom panoramas within the StreetViewPanorama
object. Using custom panoramas, you can display the interior of buildings, views from scenic locations, or anything from your imagination. You can even link these custom panoramas to Google's existing Street View panoramas.
Setting up a set of custom panorama imagery involves the following steps:
StreetViewPanoramaData
object.StreetViewPanorama
object.The following sections explain this process.
Creating Custom PanoramasEach Street View panorama is an image or set of images that provides a full 360 degree view from a single location. The StreetViewPanorama
object uses images that conform to the equirectangular (Plate Carrée) projection. Such a projection contains 360 degrees of horizontal view (a full wrap-around) and 180 degrees of vertical view (from straight up to straight down). These fields of view result in an image with an aspect ratio of 2:1. A full wrap-around panorama is shown below.
Panorama images are generally obtained by taking multiple photos from one position and stitching them together using panorama software. (See Wikipedia's Comparison of photo stitching applications for more information.) Such images should share a single "camera" locus, from which each of the panorama images are taken. The resulting 360 degree panorama can then define a projection on a sphere with the image wrapped to the two-dimensional surface of the sphere.
Treating the panorama as a projection on a sphere with a rectilinear coordinate system is advantageous when dividing up the image into rectilinear tiles, and serving images based on computed tile coordinates.
Creating Custom Panorama TilesStreet View also supports different levels of image detail through the use of a zoom control, which allows you to zoom in and out from the default view. Generally, Street View provides five levels of zoom resolution for any given panorama image. If you were to rely on a single panorama image to serve all zoom levels, such an image would either necessarily be quite large and significantly slow down your application, or be of such poor resolution at higher zoom levels that you would serve a poorly pixellated image. Luckily, however, we can use a similar design pattern used to serve Google's map tiles at different zoom levels to provide appropriate resolution imagery for panoramas at each zoom level.
When a StreetViewPanorama
first loads, by default it displays an image consisting of 25% (90 degrees of arc) of the horizontal breadth of the panorama at zoom level 1. This view corresponds roughly with a normal human field of view. Zooming "out" from this default view essentially provides a wider arc, while zooming in narrows the field of a view to a smaller arc. The StreetViewPanorama
automatically calculates the appropriate field of view for the selected zoom level, and then selects imagery most appropriate for that resolution by selecting a tile set that roughly matches the dimensions of the horizontal field of view. The following fields of view map to Street View zoom levels:
Note that the size of the image shown within Street View is entirely dependent on the screen size (width) of the Street View container. If you provide a wider container, the service will still provide the same field of view for any given zoom level, though it may select tiles more appropriate for that resolution instead.
Because each panorama consists of an equirectangular projection, creating panorama tiles is relatively easy. As the projection provides an image with an aspect ratio of 2:1, tiles with 2:1 ratios are easier to use, though square tiles may provide better performance on square maps (since the field of view will be square).
For 2:1 tiles, a single image encompassing the entire panorama represents the entire panorama "world" (the base image) at zoom level 0, with each increasing zoom level offering 4zoomLevel tiles. (E.g. at zoom level 2, the entire panorama consists of 16 tiles.) Note: zoom levels in Street View tiling do not match directly to zoom levels as provided using the Street View control; instead the Street View control zoom levels select a Field of View (FoV), from which appropriate tiles are selected.
Generally, you will want to name your image tiles so they can be selected programmatically. Such a naming scheme is discussed below in Handling Custom Panorama Requests.
Handling Custom Panorama RequestsTo use a custom panorama, call StreetViewPanorama.registerPanoProvider()
, specifying the name of your custom panorama provider method. The panorama provider method must return a StreetViewPanoramaData
object, and has the following signature:
Function(pano):StreetViewPanoramaData
A StreetViewPanoramaData
is an object of the following form:
{ 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 ] }
Display a custom panorama as follows:
StreetViewPanoramaOptions.pano
property to a custom value.StreetViewPanorama.registerPanoProvider()
to supply a custom panorama provider function.pano
value.StreetViewPanoramaData
object.StreetViewTileData.getTileUrl
property to the name of a custom tile provider function that you supply. For example, getCustomPanoramaTileUrl
.StreetViewPanoramaData
object.Note: Do not directly set a position
on the StreetViewPanorama
when you wish to display custom panoramas, as such a position will instruct the Street View service to request the default Street View imagery close to that location. Instead, set this position within the custom StreetViewPanoramaData
object's location.latLng
field.
The following example displays a custom panorama of the Google Sydney office. Note that that this example doesn't use a map or default Street View imagery:
TypeScriptfunction 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;Note: Read the guide on using TypeScript and Google Maps. 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;Note: The JavaScript is compiled from the TypeScript snippet. 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>View example Try Sample
The custom panorama provider returns the appropriate tile given the passed panorama ID, zoom level, and panorama tile coordinates. Since image selection depends on these passed values, it is useful to name images that can be selected programmatically given those passed values, such as pano_zoom_tileX_tileY.png
.
The following example adds another arrow to the image, in addition to the default Street View navigation arrows, that points into Google Sydney and links to the custom imagery:
TypeScriptlet 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;Note: Read the guide on using TypeScript and Google Maps. 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;Note: The JavaScript is compiled from the TypeScript snippet. 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>View example Try Sample
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-08-14 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-14 UTC."],[[["Google Street View API provides 360° panoramas and lets you integrate Street View into your applications."],["You can customize Street View by controlling the display, location, point-of-view, and user interactions."],["Overlays, such as markers and info windows, can be added to Street View panoramas to highlight specific points of interest."],["The API enables accessing Street View data programmatically and creating custom panoramas for unique locations."],["Custom panoramas can be seamlessly integrated with existing Google Street View imagery, enhancing the user experience."]]],[]]
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4