Stay organized with collections Save and categorize content based on your preferences.
This example displays a Street View outside of the Google Sydney office. It adds another arrow to the image, in addition to the default Street View navigation arrows, that points into Google Sydney and links to a custom panorama.
letpanorama:google.maps.StreetViewPanorama;// StreetViewPanoramaData of a panorama just outside the Google Sydney office.letoutsideGoogle:google.maps.StreetViewPanoramaData;// StreetViewPanoramaData for a custom panorama: the Google Sydney reception.functiongetReceptionPanoramaData():google.maps.StreetViewPanoramaData{return{location:{pano:"reception",// The ID for this custom panorama.description:"Google Sydney - Reception",latLng:newgoogle.maps.LatLng(-33.86684,151.19583),},links:[{heading:195,description:"Exit",pano:(outsideGoogle.locationasgoogle.maps.StreetViewLocation).pano,},],copyright:"Imagery (c) 2010 Google",tiles:{tileSize:newgoogle.maps.Size(1024,512),worldSize:newgoogle.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");},},};}functioninitPanorama(){panorama=newgoogle.maps.StreetViewPanorama(document.getElementById("street-view")asHTMLElement,{pano:(outsideGoogle.locationasgoogle.maps.StreetViewLocation).pano});// Register a provider for the custom panorama.panorama.registerPanoProvider((pano:string):google.maps.StreetViewPanoramaData=>{if(pano==="reception"){returngetReceptionPanoramaData();}// @ts-ignore TODO fix typingsreturnnull;});// Add a link to our custom panorama from outside the Google Sydney office.panorama.addListener("links_changed",()=>{if(panorama.getPano()===(outsideGoogle.locationasgoogle.maps.StreetViewLocation).pano){panorama.getLinks().push({description:"Google Sydney",heading:25,pano:"reception",});}});}functioninitMap():void{// Use the Street View service to find a pano ID on Pirrama Rd, outside the// Google office.newgoogle.maps.StreetViewService().getPanorama({location:{lat:-33.867386,lng:151.195767}}).then(({data}:google.maps.StreetViewResponse)=>{outsideGoogle=data;initPanorama();});}declareglobal{interfaceWindow{initMap:()=>void;}}window.initMap=initMap;
letpanorama;// StreetViewPanoramaData of a panorama just outside the Google Sydney office.letoutsideGoogle;// StreetViewPanoramaData for a custom panorama: the Google Sydney reception.functiongetReceptionPanoramaData(){return{location:{pano:"reception",// The ID for this custom panorama.description:"Google Sydney - Reception",latLng:newgoogle.maps.LatLng(-33.86684,151.19583),},links:[{heading:195,description:"Exit",pano:outsideGoogle.location.pano,},],copyright:"Imagery (c) 2010 Google",tiles:{tileSize:newgoogle.maps.Size(1024,512),worldSize:newgoogle.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");},},};}functioninitPanorama(){panorama=newgoogle.maps.StreetViewPanorama(document.getElementById("street-view"),{pano:outsideGoogle.location.pano},);// Register a provider for the custom panorama.panorama.registerPanoProvider((pano)=>{if(pano==="reception"){returngetReceptionPanoramaData();}// @ts-ignore TODO fix typingsreturnnull;});// 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",});}});}functioninitMap(){// Use the Street View service to find a pano ID on Pirrama Rd, outside the// Google office.newgoogle.maps.StreetViewService().getPanorama({location:{lat:-33.867386,lng:151.195767}}).then(({data})=>{outsideGoogle=data;initPanorama();});}window.initMap=initMap;
<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>
Git and Node.js are required to run this sample locally. Follow these instructions to install Node.js and NPM. The following commands clone, install dependencies and start the sample application.
[[["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-20 UTC."],[[["\u003cp\u003eThis example showcases the use of custom Street View panoramas by adding a link to a panorama inside the Google Sydney office from a Street View outside the office.\u003c/p\u003e\n"],["\u003cp\u003eIt demonstrates how to register a custom panorama provider and use the \u003ccode\u003elinks_changed\u003c/code\u003e event to add a navigation link to the custom panorama.\u003c/p\u003e\n"],["\u003cp\u003eThe custom panorama uses its own tile images, loaded using a \u003ccode\u003egetTileUrl\u003c/code\u003e function within the \u003ccode\u003eStreetViewPanoramaData\u003c/code\u003e object.\u003c/p\u003e\n"]]],[],null,["This example displays a Street View outside of the Google Sydney office. It adds\nanother arrow to the image, in addition to the default Street View navigation\narrows, that points into Google Sydney and links to a custom panorama.\n\nRead the\n[documentation](/maps/documentation/javascript/streetview#TilingPanoramas). \n\nTypeScript \n\n```typescript\nlet panorama: google.maps.StreetViewPanorama;\n\n// StreetViewPanoramaData of a panorama just outside the Google Sydney office.\nlet outsideGoogle: google.maps.StreetViewPanoramaData;\n\n// StreetViewPanoramaData for a custom panorama: the Google Sydney reception.\nfunction getReceptionPanoramaData(): google.maps.StreetViewPanoramaData {\n return {\n location: {\n pano: \"reception\", // The ID for this custom panorama.\n description: \"Google Sydney - Reception\",\n latLng: new google.maps.LatLng(-33.86684, 151.19583),\n },\n links: [\n {\n heading: 195,\n description: \"Exit\",\n pano: (outsideGoogle.location as google.maps.StreetViewLocation).pano,\n },\n ],\n copyright: \"Imagery (c) 2010 Google\",\n tiles: {\n tileSize: new google.maps.Size(1024, 512),\n worldSize: new google.maps.Size(2048, 1024),\n centerHeading: 105,\n getTileUrl: function (\n pano: string,\n zoom: number,\n tileX: number,\n tileY: number\n ): string {\n return (\n \"https://developers.google.com/maps/documentation/javascript/examples/full/images/\" +\n \"panoReception1024-\" +\n zoom +\n \"-\" +\n tileX +\n \"-\" +\n tileY +\n \".jpg\"\n );\n },\n },\n };\n}\n\nfunction initPanorama() {\n panorama = new google.maps.StreetViewPanorama(\n document.getElementById(\"street-view\") as HTMLElement,\n { pano: (outsideGoogle.location as google.maps.StreetViewLocation).pano }\n );\n // Register a provider for the custom panorama.\n panorama.registerPanoProvider(\n (pano: string): google.maps.StreetViewPanoramaData =\u003e {\n if (pano === \"reception\") {\n return getReceptionPanoramaData();\n }\n // @ts-ignore TODO fix typings\n return null;\n }\n );\n\n // Add a link to our custom panorama from outside the Google Sydney office.\n panorama.addListener(\"links_changed\", () =\u003e {\n if (\n panorama.getPano() ===\n (outsideGoogle.location as google.maps.StreetViewLocation).pano\n ) {\n panorama.getLinks().push({\n description: \"Google Sydney\",\n heading: 25,\n pano: \"reception\",\n });\n }\n });\n}\n\nfunction initMap(): void {\n // Use the Street View service to find a pano ID on Pirrama Rd, outside the\n // Google office.\n new google.maps.StreetViewService()\n .getPanorama({ location: { lat: -33.867386, lng: 151.195767 } })\n .then(({ data }: google.maps.StreetViewResponse) =\u003e {\n outsideGoogle = data;\n initPanorama();\n });\n}\n\ndeclare global {\n interface Window {\n initMap: () =\u003e void;\n }\n}\nwindow.initMap = initMap;https://github.com/googlemaps/js-samples/blob/2683f7366fb27829401945d2a7e27d77ed2df8e5/samples/streetview-custom-tiles/index.ts#L10-L103\n```\n| **Note:** Read the [guide](/maps/documentation/javascript/using-typescript) on using TypeScript and Google Maps.\n\nJavaScript \n\n```javascript\nlet panorama;\n// StreetViewPanoramaData of a panorama just outside the Google Sydney office.\nlet outsideGoogle;\n\n// StreetViewPanoramaData for a custom panorama: the Google Sydney reception.\nfunction getReceptionPanoramaData() {\n return {\n location: {\n pano: \"reception\", // The ID for this custom panorama.\n description: \"Google Sydney - Reception\",\n latLng: new google.maps.LatLng(-33.86684, 151.19583),\n },\n links: [\n {\n heading: 195,\n description: \"Exit\",\n pano: outsideGoogle.location.pano,\n },\n ],\n copyright: \"Imagery (c) 2010 Google\",\n tiles: {\n tileSize: new google.maps.Size(1024, 512),\n worldSize: new google.maps.Size(2048, 1024),\n centerHeading: 105,\n getTileUrl: function (pano, zoom, tileX, tileY) {\n return (\n \"https://developers.google.com/maps/documentation/javascript/examples/full/images/\" +\n \"panoReception1024-\" +\n zoom +\n \"-\" +\n tileX +\n \"-\" +\n tileY +\n \".jpg\"\n );\n },\n },\n };\n}\n\nfunction initPanorama() {\n panorama = new google.maps.StreetViewPanorama(\n document.getElementById(\"street-view\"),\n { pano: outsideGoogle.location.pano },\n );\n // Register a provider for the custom panorama.\n panorama.registerPanoProvider((pano) =\u003e {\n if (pano === \"reception\") {\n return getReceptionPanoramaData();\n }\n // @ts-ignore TODO fix typings\n return null;\n });\n // Add a link to our custom panorama from outside the Google Sydney office.\n panorama.addListener(\"links_changed\", () =\u003e {\n if (panorama.getPano() === outsideGoogle.location.pano) {\n panorama.getLinks().push({\n description: \"Google Sydney\",\n heading: 25,\n pano: \"reception\",\n });\n }\n });\n}\n\nfunction initMap() {\n // Use the Street View service to find a pano ID on Pirrama Rd, outside the\n // Google office.\n new google.maps.StreetViewService()\n .getPanorama({ location: { lat: -33.867386, lng: 151.195767 } })\n .then(({ data }) =\u003e {\n outsideGoogle = data;\n initPanorama();\n });\n}\n\nwindow.initMap = initMap;https://github.com/googlemaps/js-samples/blob/2683f7366fb27829401945d2a7e27d77ed2df8e5/dist/samples/streetview-custom-tiles/docs/index.js#L8-L84\n```\n| **Note:** The JavaScript is compiled from the TypeScript snippet.\n\nCSS \n\n```css\nhtml,\nbody {\n height: 100%;\n margin: 0;\n padding: 0;\n}\n\n#street-view {\n height: 100%;\n}\nhttps://github.com/googlemaps/js-samples/blob/2683f7366fb27829401945d2a7e27d77ed2df8e5/dist/samples/streetview-custom-tiles/docs/style.css#L7-L17\n```\n\nHTML \n\n```html\n\u003chtml\u003e\n \u003chead\u003e\n \u003ctitle\u003eCustom Street View Panorama Tiles\u003c/title\u003e\n\n \u003clink rel=\"stylesheet\" type=\"text/css\" href=\"./style.css\" /\u003e\n \u003cscript type=\"module\" src=\"./index.js\"\u003e\u003c/script\u003e\n \u003c/head\u003e\n \u003cbody\u003e\n \u003cdiv id=\"street-view\"\u003e\u003c/div\u003e\n\n \u003c!-- \n The `defer` attribute causes the script to execute after the full HTML\n document has been parsed. For non-blocking uses, avoiding race conditions,\n and consistent behavior across browsers, consider loading using Promises. See\n https://developers.google.com/maps/documentation/javascript/load-maps-js-api\n for more information.\n --\u003e\n \u003cscript\n src=\"https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly\"\n defer\n \u003e\u003c/script\u003e\n \u003c/body\u003e\n\u003c/html\u003ehttps://github.com/googlemaps/js-samples/blob/2683f7366fb27829401945d2a7e27d77ed2df8e5/dist/samples/streetview-custom-tiles/docs/index.html#L8-L30\n```\n\nTry Sample \n[JSFiddle.net](https://jsfiddle.net/gh/get/library/pure/googlemaps/js-samples/tree/master/dist/samples/streetview-custom-tiles/jsfiddle) [Google Cloud Shell](https://ssh.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fgooglemaps%2Fjs-samples&cloudshell_git_branch=sample-streetview-custom-tiles&cloudshell_tutorial=cloud_shell_instructions.md&cloudshell_workspace=.)\n\nClone Sample\n\n\nGit and Node.js are required to run this sample locally. Follow these [instructions](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) to install Node.js and NPM. The following commands clone, install dependencies and start the sample application. \n\n git clone -b sample-streetview-custom-tiles https://github.com/googlemaps/js-samples.git\n cd js-samples\n npm i\n npm start\n\n\nOther samples can be tried by switching to any branch beginning with `sample-`\u003cvar translate=\"no\"\u003eSAMPLE_NAME\u003c/var\u003e. \n\n git checkout sample-\u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-nx\"\u003eSAMPLE_NAME\u003c/span\u003e\u003c/var\u003e\n npm i\n npm start"]]