Tổng quan
Chế độ xem đường phố của Google cung cấp chế độ xem toàn cảnh 360 độ từ những con đường được chỉ định trong phạm vi mà chế độ này hỗ trợ. Phạm vi phủ sóng của API Chế độ xem đường phố giống với phạm vi phủ sóng của ứng dụng Google Maps (https://maps.google.com/). Danh sách các thành phố hiện được hỗ trợ cho Chế độ xem đường phố có trên trang web Google Maps.
Dưới đây là một hình ảnh mẫu trong Chế độ xem đường phố.
Maps JavaScript API cung cấp một dịch vụ Chế độ xem đường phố để lấy và thao tác với hình ảnh được dùng trong Chế độ xem đường phố của Google Maps. Dịch vụ Chế độ xem đường phố này được hỗ trợ nguyên bản trong trình duyệt.
Sử dụng bản đồ trong Chế độ xem đường phố
Mặc dù bạn có thể sử dụng Chế độ xem đường phố trong một phần tử DOM độc lập, nhưng chế độ này hữu ích nhất khi cho biết một vị trí trên bản đồ. Theo mặc định, Chế độ xem đường phố được bật trên bản đồ và nút điều khiển Người hình mắc áo của Chế độ xem đường phố sẽ xuất hiện được tích hợp trong các nút điều khiển điều hướng (thu phóng và xoay). Bạn có thể ẩn chế độ điều khiển này trong MapOptions của bản đồ bằng cách đặt streetViewControl thành false. Bạn cũng có thể thay đổi vị trí mặc định của chế độ điều khiển Chế độ xem đường phố bằng cách đặt thuộc tính streetViewControlOptions.position của Map thành một ControlPosition mới.
Chế độ điều khiển Người hình mắc áo trong Chế độ xem đường phố cho phép bạn xem ảnh toàn cảnh trong Chế độ xem đường phố ngay trên bản đồ. Khi người dùng nhấp và giữ Người hình mắc áo, bản đồ sẽ cập nhật để hiện đường viền màu xanh dương xung quanh những đường phố có hỗ trợ Chế độ xem đường phố, mang đến trải nghiệm người dùng tương tự như ứng dụng Google Maps.
Khi người dùng thả điểm đánh dấu Người hình mắc áo xuống một con đường, bản đồ sẽ cập nhật để hiển thị ảnh toàn cảnh Chế độ xem phố của vị trí được chỉ định.
Ảnh toàn cảnh trong Chế độ xem đường phố
Hình ảnh Chế độ xem đường phố được hỗ trợ thông qua việc sử dụng đối tượng StreetViewPanorama. Đối tượng này cung cấp một giao diện API cho "trình xem" Chế độ xem đường phố. Mỗi bản đồ đều chứa một ảnh toàn cảnh mặc định trong Chế độ xem đường phố mà bạn có thể truy xuất bằng cách gọi phương thức getStreetView() của bản đồ. Khi thêm một chế độ điều khiển Chế độ xem đường phố vào bản đồ bằng cách đặt lựa chọn streetViewControl thành true, bạn sẽ tự động kết nối chế độ điều khiển Người hình mắc áo với ảnh toàn cảnh mặc định này trong Chế độ xem đường phố.
Bạn cũng có thể tạo đối tượng StreetViewPanorama của riêng mình và đặt bản đồ để sử dụng đối tượng đó thay vì đối tượng mặc định, bằng cách đặt rõ ràng thuộc tính streetView của bản đồ thành đối tượng đã tạo đó. Bạn nên ghi đè chế độ xem toàn cảnh mặc định nếu muốn sửa đổi hành vi mặc định, chẳng hạn như việc tự động chia sẻ lớp phủ giữa bản đồ và chế độ xem toàn cảnh. (Xem phần Lớp phủ trong Chế độ xem phố bên dưới.)
Vùng chứa Chế độ xem đường phố
Thay vào đó, bạn có thể muốn hiển thị một StreetViewPanorama trong một phần tử DOM riêng biệt, thường là một phần tử <div>.
Chỉ cần truyền phần tử DOM trong hàm khởi tạo StreetViewPanorama. Để hình ảnh hiển thị tối ưu, bạn nên sử dụng kích thước tối thiểu là 200 x 200 pixel.
Lưu ý: Mặc dù chức năng Chế độ xem đường phố được thiết kế để sử dụng cùng với bản đồ, nhưng bạn không bắt buộc phải sử dụng theo cách này. Bạn có thể sử dụng một đối tượng Chế độ xem đường phố độc lập mà không cần bản đồ.
Vị trí và góc nhìn trong Chế độ xem đường phố
Hàm dựng StreetViewPanorama cũng cho phép bạn đặt vị trí và góc nhìn của Chế độ xem đường phố bằng cách sử dụng tham số StreetViewOptions. Bạn có thể gọi
setPosition() và setPov() trên đối tượng sau khi tạo để thay đổi vị trí và góc nhìn của đối tượng.
Vị trí trong Chế độ xem đường phố xác định vị trí tiêu điểm của camera cho một hình ảnh, nhưng không xác định hướng của camera cho hình ảnh đó. Vì mục đích đó, đối tượng StreetViewPov xác định hai thuộc tính:
heading(mặc định là0) xác định góc xoay xung quanh vị trí camera theo độ tương ứng với hướng bắc thực. Hướng được đo theo chiều kim đồng hồ (90 độ là hướng đông).pitch(mặc định là0) xác định phương sai góc "lên" hoặc "xuống" so với góc nghiêng mặc định ban đầu của camera, thường là (nhưng không phải lúc nào cũng) nằm ngang. (Ví dụ: hình ảnh chụp trên đồi có thể sẽ có góc nghiêng mặc định không nằm ngang.) Góc nghiêng được đo bằng các giá trị dương khi nhìn lên (đến +90 độ thẳng lên và vuông góc với độ nghiêng mặc định) và các giá trị âm khi nhìn xuống (đến -90 độ thẳng xuống và vuông góc với độ nghiêng mặc định).
Đối tượng StreetViewPov thường được dùng để xác định điểm nhìn của camera Chế độ xem đường phố. Bạn cũng có thể xác định quan điểm của người chụp ảnh (thường là hướng mà ô tô hoặc xe ba bánh đang hướng tới) bằng phương thức StreetViewPanorama.getPhotographerPov().
Đoạn mã sau đây hiển thị bản đồ Boston với chế độ xem ban đầu của Công viên Fenway. Khi bạn chọn Người hình mắc áo rồi kéo đến một vị trí được hỗ trợ trên bản đồ, ảnh toàn cảnh trong Chế độ xem đường phố sẽ thay đổi:
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>
<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>Dùng thử mẫu
Theo dõi chuyển động trên thiết bị di động
Trên các thiết bị hỗ trợ sự kiện hướng thiết bị, API này cho phép người dùng thay đổi góc nhìn của Chế độ xem đường phố dựa trên chuyển động của thiết bị. Người dùng có thể di chuyển thiết bị để quan sát xung quanh. Đây được gọi là tính năng theo dõi chuyển động hoặc theo dõi hướng xoay của thiết bị.
Là nhà phát triển ứng dụng, bạn có thể thay đổi hành vi mặc định như sau:
- Bật hoặc tắt chức năng theo dõi chuyển động. Theo mặc định, tính năng theo dõi chuyển động sẽ được bật trên mọi thiết bị hỗ trợ tính năng này. Mẫu sau đây vô hiệu hoá tính năng theo dõi chuyển động nhưng vẫn để chế độ điều khiển theo dõi chuyển động hiển thị.
(Lưu ý rằng người dùng có thể bật tính năng theo dõi chuyển động bằng cách nhấn vào chế độ điều khiển.)
var panorama = new google.maps.StreetViewPanorama( document.getElementById('pano'), { position: {lat: 37.869260, lng: -122.254811}, pov: {heading: 165, pitch: 0}, motionTracking: false });
-
Ẩn hoặc hiện chế độ điều khiển theo dõi chuyển động. Theo mặc định, chế độ kiểm soát này sẽ xuất hiện trên các thiết bị hỗ trợ tính năng theo dõi chuyển động. Người dùng có thể nhấn vào nút điều khiển để bật hoặc tắt tính năng theo dõi chuyển động. Xin lưu ý rằng nút điều khiển sẽ không bao giờ xuất hiện nếu thiết bị không hỗ trợ tính năng theo dõi chuyển động, bất kể giá trị của
motionTrackingControllà gì.Mẫu sau đây sẽ tắt cả tính năng theo dõi chuyển động và chế độ kiểm soát theo dõi chuyển động. Trong trường hợp này, người dùng không thể bật tính năng theo dõi chuyển động:
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 });
- Thay đổi vị trí mặc định của chế độ điều khiển theo dõi chuyển động. Theo mặc định, chế độ điều khiển sẽ xuất hiện ở gần dưới cùng bên phải của ảnh toàn cảnh (vị trí
RIGHT_BOTTOM). Mẫu sau đây đặt vị trí của chế độ điều khiển ở dưới cùng bên trái: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 } });
Để xem tính năng theo dõi chuyển động hoạt động, hãy xem mẫu sau trên thiết bị di động (hoặc bất kỳ thiết bị nào hỗ trợ sự kiện hướng thiết bị):
Lớp phủ trong Chế độ xem phố
Đối tượng StreetViewPanorama mặc định hỗ trợ chế độ hiển thị gốc của lớp phủ bản đồ.
Các lớp phủ thường xuất hiện ở "cấp đường phố" được cố định ở vị trí LatLng. (Các điểm đánh dấu sẽ xuất hiện với phần đuôi được cố định vào mặt phẳng ngang của vị trí trong ảnh toàn cảnh Chế độ xem đường phố, ví dụ:.)
Hiện tại, các loại lớp phủ được hỗ trợ trên ảnh toàn cảnh trong Chế độ xem đường phố chỉ bao gồm Marker, InfoWindow và OverlayView tuỳ chỉnh. Lớp phủ mà bạn hiển thị trên bản đồ có thể xuất hiện trên ảnh toàn cảnh Chế độ xem đường phố bằng cách coi ảnh toàn cảnh là một lựa chọn thay thế cho đối tượng Map, gọi setMap() và truyền StreetViewPanorama làm đối số thay vì bản đồ. Tương tự, bạn có thể mở các cửa sổ thông tin trong ảnh toàn cảnh Chế độ xem đường phố bằng cách gọi open(), truyền StreetViewPanorama() thay vì một bản đồ.
Ngoài ra, khi bạn tạo một bản đồ có StreetViewPanorama mặc định, mọi điểm đánh dấu được tạo trên bản đồ sẽ tự động được chia sẻ với ảnh toàn cảnh Chế độ xem đường phố được liên kết với bản đồ đó, miễn là ảnh toàn cảnh đó hiển thị. Để truy xuất ảnh toàn cảnh mặc định trong Chế độ xem đường phố, hãy gọi getStreetView() trên đối tượng Map. Xin lưu ý rằng nếu bạn đặt thuộc tính streetView của bản đồ thành StreetViewPanorama do bạn tự tạo, thì bạn sẽ ghi đè ảnh toàn cảnh mặc định.
Ví dụ sau đây cho thấy các điểm đánh dấu biểu thị nhiều vị trí xung quanh Astor Place, Thành phố New York. Chuyển chế độ hiển thị sang Chế độ xem đường phố để cho thấy các điểm đánh dấu được chia sẻ hiển thị trong StreetViewPanorama.
TypeScript
let panorama: google.maps.StreetViewPanorama; let innerMap: google.maps.Map; async function initMap() { // Request needed libraries. const { Map } = (await google.maps.importLibrary( 'maps' )) as google.maps.MapsLibrary; // Set the location of Astor Place. const astorPlace = { lat: 40.729884, lng: -73.990988 }; const mapElement = document.querySelector( 'gmp-map' ) as google.maps.MapElement; innerMap = mapElement.innerMap; document .getElementById('streetview-toggle-button')! .addEventListener('click', toggleStreetView); const cafeIcon = document.createElement('img'); cafeIcon.src = new URL('./public/cafe_icon.svg', import.meta.url).href; const dollarIcon = document.createElement('img'); dollarIcon.src = new URL('./public/bank_icon.svg', import.meta.url).href; const busIcon = document.createElement('img'); busIcon.src = new URL('./public/bus_icon.svg', import.meta.url).href; // Set up the markers on the map const cafeMarker = new google.maps.Marker({ position: { lat: 40.730031, lng: -73.991428 }, map: innerMap, title: 'Cafe', icon: cafeIcon.src, }); const bankMarker = new google.maps.Marker({ position: { lat: 40.729681, lng: -73.991138 }, map: innerMap, title: 'Bank', icon: dollarIcon.src, }); const busMarker = new google.maps.Marker({ position: { lat: 40.729559, lng: -73.990741 }, map: innerMap, 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 = innerMap.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); } } initMap();
JavaScript
let panorama; let innerMap; async function initMap() { // Request needed libraries. const { Map } = (await google.maps.importLibrary('maps')); // Set the location of Astor Place. const astorPlace = { lat: 40.729884, lng: -73.990988 }; const mapElement = document.querySelector('gmp-map'); innerMap = mapElement.innerMap; document .getElementById('streetview-toggle-button') .addEventListener('click', toggleStreetView); const cafeIcon = document.createElement('img'); cafeIcon.src = new URL('./public/cafe_icon.svg', import.meta.url).href; const dollarIcon = document.createElement('img'); dollarIcon.src = new URL('./public/bank_icon.svg', import.meta.url).href; const busIcon = document.createElement('img'); busIcon.src = new URL('./public/bus_icon.svg', import.meta.url).href; // Set up the markers on the map const cafeMarker = new google.maps.Marker({ position: { lat: 40.730031, lng: -73.991428 }, map: innerMap, title: 'Cafe', icon: cafeIcon.src, }); const bankMarker = new google.maps.Marker({ position: { lat: 40.729681, lng: -73.991138 }, map: innerMap, title: 'Bank', icon: dollarIcon.src, }); const busMarker = new google.maps.Marker({ position: { lat: 40.729559, lng: -73.990741 }, map: innerMap, 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 = innerMap.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); } } initMap(); export {};
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; } #streetview-toggle-button { height: 40px; display: flex; align-items: center; justify-content: center; padding: 0 17px; border: none; background: white; cursor: pointer; border-radius: 2px; box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3); margin: 10px 0px 10px -2px; font-family: Roboto, Arial, sans-serif; font-size: 18px; font-weight: 400; color: rgb(86, 86, 86); } #streetview-toggle-button:hover { background: #f4f4f4; color: #000; }
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>
<!-- prettier-ignore -->
<script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
({key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</script>
</head>
<body>
<gmp-map map-id="DEMO_MAP_ID" center="40.729884, -73.990988" zoom="18">
<input type="button" value="Toggle Street View" id="streetview-toggle-button" slot="control-block-start-inline-start" />
</gmp-map>
</body>
</html>Dùng thử mẫu
Sự kiện trong Chế độ xem đường phố
Khi di chuyển giữa Chế độ xem đường phố hoặc thao tác với hướng của chế độ này, bạn có thể muốn theo dõi một số sự kiện cho biết các thay đổi về trạng thái của StreetViewPanorama:
pano_changedsẽ kích hoạt bất cứ khi nào mã nhận dạng pano riêng lẻ thay đổi. Sự kiện này không đảm bảo rằng mọi dữ liệu được liên kết trong toàn cảnh (chẳng hạn như các đường liên kết) cũng đã thay đổi vào thời điểm sự kiện này được kích hoạt; sự kiện này chỉ cho biết rằng một mã nhận dạng toàn cảnh đã thay đổi. Xin lưu ý rằng mã nhận dạng toàn cảnh (bạn có thể dùng để tham chiếu đến bức toàn cảnh này) chỉ ổn định trong phiên trình duyệt hiện tại.position_changedsẽ kích hoạt bất cứ khi nào vị trí cơ bản (LatLng) của ảnh toàn cảnh thay đổi. Việc xoay ảnh toàn cảnh sẽ không kích hoạt sự kiện này. Xin lưu ý rằng bạn có thể thay đổi vị trí cơ bản của ảnh toàn cảnh mà không cần thay đổi mã nhận dạng ảnh toàn cảnh được liên kết, vì API sẽ tự động liên kết mã nhận dạng ảnh toàn cảnh gần nhất với vị trí của ảnh toàn cảnh.pov_changedsẽ kích hoạt bất cứ khi nàoStreetViewPovcủa Chế độ xem đường phố thay đổi. Xin lưu ý rằng sự kiện này có thể kích hoạt trong khi vị trí và mã nhận dạng toàn cảnh vẫn ổn định.links_changedsẽ kích hoạt bất cứ khi nào các đường liên kết của Chế độ xem đường phố thay đổi. Xin lưu ý rằng sự kiện này có thể kích hoạt không đồng bộ sau khi có thay đổi về mã nhận dạng toàn cảnh được biểu thị thông quapano_changed.visible_changedsẽ kích hoạt bất cứ khi nào chế độ hiển thị của Chế độ xem đường phố thay đổi. Xin lưu ý rằng sự kiện này có thể kích hoạt không đồng bộ sau khi có thay đổi về mã nhận dạng toàn cảnh được biểu thị thông quapano_changed.
Đoạn mã sau minh hoạ cách xử lý các sự kiện này để thu thập dữ liệu về StreetViewPanorama cơ bản:
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>
<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>Dùng thử mẫu
Các nút điều khiển Chế độ xem đường phố
Khi bạn hiển thị StreetViewPanorama, theo mặc định, nhiều chế độ kiểm soát sẽ xuất hiện trên ảnh toàn cảnh. Bạn có thể bật hoặc tắt các chế độ kiểm soát này bằng cách đặt các trường thích hợp trong StreetViewPanoramaOptions thành true hoặc false:
panControlcung cấp một cách để xoay ảnh toàn cảnh. Theo mặc định, chế độ điều khiển này sẽ xuất hiện dưới dạng một la bàn tích hợp tiêu chuẩn và chế độ điều khiển xoay. Bạn có thể thay đổi vị trí của chế độ kiểm soát bằng cách cung cấpPanControlOptionstrong trườngpanControlOptions.zoomControlcung cấp một cách để phóng to trong hình ảnh. Theo mặc định, chế độ điều khiển này sẽ xuất hiện ở gần dưới cùng bên phải của ảnh toàn cảnh. Bạn có thể thay đổi giao diện của chế độ kiểm soát bằng cách cung cấpZoomControlOptionstrong trườngzoomControlOptions.addressControlcung cấp một lớp phủ văn bản cho biết địa chỉ của vị trí được liên kết và cung cấp một đường liên kết để mở vị trí đó trong Google Maps. Bạn có thể thay đổi giao diện của chế độ kiểm soát bằng cách cung cấpStreetViewAddressControlOptionstrong trườngaddressControlOptions.- Biểu tượng
fullscreenControlcho phép bạn mở Chế độ xem đường phố ở chế độ toàn màn hình. Bạn có thể thay đổi giao diện của chế độ kiểm soát bằng cách cung cấpFullscreenControlOptionstrong trườngfullscreenControlOptions. motionTrackingControlcho phép bạn bật hoặc tắt tính năng theo dõi chuyển động trên thiết bị di động. Chế độ điều khiển này chỉ xuất hiện trên các thiết bị hỗ trợ sự kiện định hướng thiết bị. Theo mặc định, chế độ điều khiển này sẽ xuất hiện ở gần dưới cùng bên phải của ảnh toàn cảnh. Bạn có thể thay đổi vị trí của chế độ kiểm soát bằng cách cung cấpMotionTrackingControlOptions. Để biết thêm thông tin, hãy xem phần theo dõi chuyển động.linksControlcung cấp các mũi tên chỉ dẫn trên hình ảnh để di chuyển đến các hình ảnh toàn cảnh liền kề.- Nút Đóng cho phép người dùng đóng trình xem Chế độ xem đường phố. Bạn có thể bật hoặc tắt chế độ điều khiển Đóng bằng cách đặt
enableCloseButtonthànhtruehoặcfalse.
Ví dụ sau đây sẽ thay đổi các chế độ điều khiển xuất hiện trong Chế độ xem đường phố được liên kết và xoá các đường liên kết của khung hiển thị:
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>
<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>Dùng thử mẫu
Truy cập trực tiếp vào dữ liệu Chế độ xem đường phố
Bạn có thể muốn xác định theo phương thức lập trình tính sẵn có của dữ liệu Chế độ xem đường phố hoặc trả về thông tin về các ảnh toàn cảnh cụ thể mà không cần thao tác trực tiếp trên bản đồ/ảnh toàn cảnh. Bạn có thể làm như vậy bằng cách sử dụng đối tượng StreetViewService. Đối tượng này cung cấp một giao diện cho dữ liệu được lưu trữ trong dịch vụ Chế độ xem đường phố của Google.
Yêu cầu về dịch vụ Chế độ xem đường phố
Việc truy cập vào dịch vụ Chế độ xem đường phố là không đồng bộ, vì Google Maps API cần thực hiện lệnh gọi đến một máy chủ bên ngoài. Vì lý do đó, bạn cần truyền một phương thức gọi lại để thực thi khi yêu cầu hoàn tất. Phương thức gọi lại này sẽ xử lý kết quả.
Bạn có thể bắt đầu yêu cầu đến StreetViewService bằng cách sử dụng StreetViewPanoRequest hoặc StreetViewLocationRequest.
Yêu cầu sử dụng StreetViewPanoRequest sẽ trả về dữ liệu toàn cảnh khi có một mã tham chiếu xác định duy nhất ảnh toàn cảnh. Xin lưu ý rằng các mã nhận dạng tham chiếu này chỉ ổn định trong suốt thời gian tồn tại của hình ảnh trong toàn cảnh đó.
Yêu cầu sử dụng StreetViewLocationRequest sẽ tìm kiếm dữ liệu toàn cảnh tại một vị trí được chỉ định, bằng cách sử dụng các tham số sau:
locationchỉ định vị trí (vĩ độ và kinh độ) để tìm ảnh toàn cảnh.preferenceđặt lựa chọn ưu tiên cho ảnh toàn cảnh cần tìm trong bán kính: ảnh gần vị trí được cung cấp nhất hoặc ảnh đẹp nhất trong bán kính.radiusđặt bán kính (được chỉ định bằng mét) để tìm kiếm ảnh toàn cảnh, được đặt ở giữa vĩ độ và kinh độ đã cho. Giá trị mặc định là 50 khi không được cung cấp.sourcechỉ định nguồn của ảnh toàn cảnh cần tìm kiếm. Các giá trị hợp lệ là:defaultsử dụng các nguồn mặc định cho Chế độ xem đường phố; các cụm từ tìm kiếm không bị giới hạn ở các nguồn cụ thể.outdoorgiới hạn phạm vi tìm kiếm trong các bộ sưu tập ngoài trời. Xin lưu ý rằng có thể không có ảnh toàn cảnh ngoài trời cho vị trí được chỉ định.
Phản hồi của dịch vụ Chế độ xem đường phố
Hàm getPanorama() cần một hàm callback để thực thi khi truy xuất kết quả từ dịch vụ Chế độ xem đường phố. Hàm gọi lại này trả về một tập hợp dữ liệu toàn cảnh trong đối tượng StreetViewPanoramaData và mã StreetViewStatus biểu thị trạng thái của yêu cầu, theo thứ tự đó.
Quy cách đối tượng StreetViewPanoramaData chứa siêu dữ liệu về một ảnh toàn cảnh Chế độ xem đường phố có dạng sau:
{ "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 } }
Xin lưu ý rằng đối tượng dữ liệu này không phải là chính đối tượng StreetViewPanorama. Để tạo một đối tượng Chế độ xem đường phố bằng dữ liệu này, bạn cần tạo một StreetViewPanorama và gọi setPano(), truyền cho đối tượng này mã nhận dạng như đã lưu ý trong trường location.pano được trả về.
Mã status có thể trả về một trong các giá trị sau:
OKcho biết dịch vụ đã tìm thấy một ảnh toàn cảnh phù hợp.ZERO_RESULTScho biết dịch vụ không tìm thấy ảnh toàn cảnh phù hợp với tiêu chí đã truyền.UNKNOWN_ERRORcho biết rằng yêu cầu về Chế độ xem đường phố không xử lý được, mặc dù không rõ lý do chính xác.
Đoạn mã sau đây tạo một StreetViewService phản hồi các lượt nhấp của người dùng trên bản đồ bằng cách tạo các điểm đánh dấu. Khi được nhấp, các điểm đánh dấu này sẽ hiển thị một StreetViewPanorama của vị trí đó. Mã này sử dụng nội dung của StreetViewPanoramaData do dịch vụ trả về.
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>
<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>Dùng thử mẫu
Cung cấp ảnh toàn cảnh tuỳ chỉnh trong Chế độ xem đường phố
Maps JavaScript API hỗ trợ việc hiển thị ảnh toàn cảnh tuỳ chỉnh trong đối tượng StreetViewPanorama. Khi sử dụng ảnh toàn cảnh tuỳ chỉnh, bạn có thể hiển thị nội thất của các toà nhà, khung cảnh từ các địa điểm du lịch hoặc bất cứ thứ gì mà bạn có thể tưởng tượng. Bạn thậm chí có thể liên kết những ảnh toàn cảnh tuỳ chỉnh này với ảnh toàn cảnh hiện có trong Chế độ xem đường phố của Google.
Quy trình thiết lập một nhóm hình ảnh toàn cảnh tuỳ chỉnh bao gồm các bước sau:
- Tạo một hình ảnh toàn cảnh cơ bản cho mỗi ảnh toàn cảnh tuỳ chỉnh. Hình ảnh cơ sở này phải là hình ảnh có độ phân giải cao nhất mà bạn muốn phân phát hình ảnh phóng to.
- (Không bắt buộc nhưng nên làm) Tạo một nhóm ô toàn cảnh ở các mức thu phóng khác nhau từ hình ảnh cơ bản.
- Tạo đường liên kết giữa các ảnh toàn cảnh tuỳ chỉnh.
- (Không bắt buộc) Chỉ định ảnh toàn cảnh "lối vào" trong hình ảnh Chế độ xem phố hiện có của Google và tuỳ chỉnh các đường liên kết đến/từ bộ ảnh tuỳ chỉnh đến bộ ảnh tiêu chuẩn.
- Xác định siêu dữ liệu cho từng hình ảnh toàn cảnh trong đối tượng
StreetViewPanoramaData. - Triển khai một phương thức xác định dữ liệu và hình ảnh toàn cảnh tuỳ chỉnh, đồng thời chỉ định phương thức đó làm trình xử lý tuỳ chỉnh trong đối tượng
StreetViewPanorama.
Các phần sau đây giải thích quy trình này.
Tạo ảnh toàn cảnh tuỳ chỉnh
Mỗi ảnh toàn cảnh trong Chế độ xem đường phố là một hình ảnh hoặc một nhóm hình ảnh cung cấp chế độ xem 360 độ từ một vị trí duy nhất.
Đối tượng StreetViewPanorama sử dụng những hình ảnh tuân theo phép chiếu hình chữ nhật đều (Plate Carrée). Phép chiếu như vậy chứa 360 độ của khung hiển thị ngang (một khung hiển thị bao quanh hoàn toàn) và 180 độ của khung hiển thị dọc (từ trên xuống dưới). Những trường này của kết quả xem tạo ra một hình ảnh có tỷ lệ khung hình là 2:1. Dưới đây là hình ảnh toàn cảnh bao quát.

Ảnh toàn cảnh thường được tạo bằng cách chụp nhiều bức ảnh từ một vị trí và ghép chúng lại với nhau bằng phần mềm toàn cảnh. (Xem bài viết So sánh các ứng dụng ghép ảnh trên Wikipedia để biết thêm thông tin.) Những hình ảnh như vậy phải có một vị trí "camera" duy nhất, nơi chụp từng hình ảnh toàn cảnh. Ảnh toàn cảnh 360 độ thu được sau đó có thể xác định một phép chiếu trên một hình cầu với hình ảnh được bao bọc vào bề mặt hai chiều của hình cầu.

Việc coi ảnh toàn cảnh là một phép chiếu trên hình cầu với hệ toạ độ hình chữ nhật sẽ có lợi khi chia hình ảnh thành các ô hình chữ nhật và phân phát hình ảnh dựa trên toạ độ ô đã tính.
Tạo ô toàn cảnh tuỳ chỉnh
Chế độ xem đường phố cũng hỗ trợ nhiều mức độ chi tiết của hình ảnh thông qua việc sử dụng chế độ thu phóng. Chế độ này cho phép bạn phóng to và thu nhỏ từ chế độ xem mặc định. Thông thường, Chế độ xem đường phố cung cấp 5 mức độ phân giải thu phóng cho mọi hình ảnh toàn cảnh. Nếu bạn dựa vào một hình ảnh toàn cảnh duy nhất để phục vụ tất cả các mức thu phóng, thì hình ảnh đó chắc chắn sẽ khá lớn và làm chậm đáng kể ứng dụng của bạn, hoặc có độ phân giải quá kém ở các mức thu phóng cao hơn đến mức bạn sẽ phân phát một hình ảnh bị vỡ hạt. Tuy nhiên, may mắn là chúng ta có thể sử dụng một mẫu thiết kế tương tự được dùng để phân phát các ô bản đồ của Google ở nhiều mức thu phóng nhằm cung cấp hình ảnh có độ phân giải phù hợp cho ảnh toàn cảnh ở mỗi mức thu phóng.
Khi StreetViewPanorama tải lần đầu, theo mặc định, thành phần này sẽ hiển thị một hình ảnh bao gồm 25% (90 độ cung) chiều rộng ngang của ảnh toàn cảnh ở mức thu phóng 1. Chế độ xem này tương ứng với trường nhìn thông thường của con người. Thu nhỏ từ chế độ xem mặc định này về cơ bản sẽ cung cấp một vòng cung rộng hơn, trong khi phóng to sẽ thu hẹp trường của chế độ xem thành một vòng cung nhỏ hơn. StreetViewPanorama sẽ tự động tính toán trường nhìn phù hợp cho mức thu phóng đã chọn, sau đó chọn hình ảnh phù hợp nhất cho độ phân giải đó bằng cách chọn một bộ ô phù hợp với kích thước của trường nhìn ngang. Các trường sau đây của bản đồ chế độ xem tương ứng với các mức thu phóng của Chế độ xem đường phố:
| Mức thu phóng của Chế độ xem đường phố | Trường nhìn (độ) |
|---|---|
| 0 | 180 |
| 1 (mặc định) | 90 |
| 2 | 45 |
| 3 | 22,5 |
| 4 | 11,25 |
Xin lưu ý rằng kích thước của hình ảnh xuất hiện trong Chế độ xem đường phố hoàn toàn phụ thuộc vào kích thước màn hình (chiều rộng) của vùng chứa Chế độ xem đường phố. Nếu bạn cung cấp một vùng chứa rộng hơn, dịch vụ này vẫn sẽ cung cấp cùng một trường nhìn cho mọi mức thu phóng nhất định, mặc dù dịch vụ này có thể chọn các ô phù hợp hơn cho độ phân giải đó.
Vì mỗi ảnh toàn cảnh đều bao gồm một phép chiếu hình chữ nhật, nên việc tạo các ô ảnh toàn cảnh tương đối dễ dàng. Vì phép chiếu cung cấp hình ảnh có tỷ lệ khung hình 2:1, nên các ô có tỷ lệ 2:1 sẽ dễ sử dụng hơn, mặc dù các ô vuông có thể mang lại hiệu suất cao hơn trên bản đồ vuông (vì trường nhìn sẽ là hình vuông).
Đối với các ô 2:1, một hình ảnh duy nhất bao gồm toàn bộ ảnh toàn cảnh sẽ đại diện cho toàn bộ "thế giới" toàn cảnh (hình ảnh cơ sở) ở cấp độ thu phóng 0, với mỗi cấp độ thu phóng tăng lên sẽ cung cấp 4zoomLevel ô. (Ví dụ: ở mức thu phóng 2, toàn bộ ảnh toàn cảnh sẽ bao gồm 16 ô.) Lưu ý: các mức thu phóng trong tính năng chia ô của Chế độ xem đường phố không khớp trực tiếp với các mức thu phóng được cung cấp bằng chế độ điều khiển Chế độ xem đường phố; thay vào đó, các mức thu phóng của chế độ điều khiển Chế độ xem đường phố sẽ chọn một Trường nhìn (FoV), từ đó các ô phù hợp sẽ được chọn.

Thông thường, bạn sẽ muốn đặt tên cho các ô hình ảnh để có thể chọn chúng theo phương thức lập trình. Cách đặt tên như vậy sẽ được thảo luận bên dưới trong phần Xử lý các yêu cầu về ảnh toàn cảnh tuỳ chỉnh.
Xử lý các yêu cầu về ảnh toàn cảnh tuỳ chỉnh
Để sử dụng ảnh toàn cảnh tuỳ chỉnh, hãy gọi StreetViewPanorama.registerPanoProvider(), chỉ định tên của phương thức nhà cung cấp ảnh toàn cảnh tuỳ chỉnh. Phương thức của trình cung cấp ảnh toàn cảnh phải trả về một đối tượng StreetViewPanoramaData và có chữ ký sau:
Function(pano):StreetViewPanoramaData
StreetViewPanoramaData là một đối tượng có dạng sau:
{ 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 ] }
Hiển thị ảnh toàn cảnh tuỳ chỉnh như sau:
- Đặt thuộc tính
StreetViewPanoramaOptions.panothành một giá trị tuỳ chỉnh. - Gọi
StreetViewPanorama.registerPanoProvider()để cung cấp một hàm trình cung cấp ảnh toàn cảnh tuỳ chỉnh. - Triển khai hàm trình cung cấp ảnh toàn cảnh tuỳ chỉnh để xử lý giá trị
panođã chỉ định. - Tạo một đối tượng
StreetViewPanoramaData. - Đặt thuộc tính
StreetViewTileData.getTileUrlthành tên của hàm nhà cung cấp ô tuỳ chỉnh mà bạn cung cấp. Ví dụ:getCustomPanoramaTileUrl. - Triển khai hàm trình cung cấp ô tuỳ chỉnh, như minh hoạ trong các mẫu bên dưới.
- Trả về đối tượng
StreetViewPanoramaData.
Lưu ý: Đừng trực tiếp đặt position trên StreetViewPanorama khi bạn muốn hiển thị ảnh toàn cảnh tuỳ chỉnh, vì vị trí đó sẽ hướng dẫn dịch vụ Chế độ xem đường phố yêu cầu hình ảnh mặc định trong Chế độ xem đường phố ở gần vị trí đó. Thay vào đó, hãy đặt vị trí này trong trường location.latLng của đối tượng StreetViewPanoramaData tuỳ chỉnh.
Ví dụ sau đây cho thấy một ảnh toàn cảnh tuỳ chỉnh về văn phòng Google tại Sydney. Xin lưu ý rằng ví dụ này không sử dụng bản đồ hoặc hình ảnh mặc định của Chế độ xem đường phố:
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>
<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>Dùng thử mẫu
Trình cung cấp ảnh toàn cảnh tuỳ chỉnh sẽ trả về ô thích hợp dựa trên mã nhận dạng ảnh toàn cảnh, mức thu phóng và toạ độ ô ảnh toàn cảnh được truyền.
Vì việc chọn hình ảnh phụ thuộc vào các giá trị được truyền này, nên bạn nên đặt tên cho những hình ảnh có thể được chọn theo chương trình dựa trên các giá trị được truyền đó, chẳng hạn như pano_zoom_tileX_tileY.png.
Ví dụ sau đây sẽ thêm một mũi tên khác vào hình ảnh, ngoài các mũi tên điều hướng mặc định của Chế độ xem đường phố, mũi tên này sẽ chỉ vào Google Sydney và liên kết đến hình ảnh tuỳ chỉnh:
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>
<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>