Dịch vụ Chế độ xem phố

Tổng quan

Chọn nền tảng: Android iOS JavaScript

Chế độ xem phố của Google cung cấp chế độ xem 360 độ trên toàn bộ khu vực phủ sóng của các con đường được chỉ định. Mức độ phù hợp của API Chế độ xem phố giống với mức độ phù hợp của ứng dụng Google Maps (https://maps.google.com/). Danh sách các thành phố hiện được hỗ trợ chế độ xem phố có tại Trang web Google Maps.

Hình ảnh Chế độ xem phố mẫu được hiển thị bên dưới.


API JavaScript của Maps cung cấp dịch vụ Chế độ xem phố để nhận và thao tác với hình ảnh được sử dụng trong Chế độ xem phố của Google Maps. Dịch vụ Chế độ xem phố này vốn được hỗ trợ trong trình duyệt.

Sử dụng bản đồ trong Chế độ xem phố

Mặc dù bạn có thể sử dụng Chế độ xem phố trong một phần tử DOM độc lập, nhưng việc này rất hữu ích khi chỉ báo một vị trí trên bản đồ. Theo mặc định, Chế độ xem phố được bật trên bản đồ và điều khiển Người hình mắc áo của Chế độ xem phố xuất hiện được tích hợp trong các điều khiển điều hướng (thu phóng và kéo). Bạn có thể ẩn tùy chọn kiểm soát 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 phố bằng cách đặt thuộc tính streetViewControlOptions.position của Map thành ControlPosition mới.

Chế độ điều khiển Người hình mắc áo của Chế độ xem phố cho phép bạn xem ảnh toàn cảnh của Chế độ xem phố ngay trong 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 thị đường viền màu xanh xung quanh các đường phố được bật Chế độ xem phố, cung cấp 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 vào một đường phố, bản đồ sẽ cập nhật để hiển thị ảnh toàn cảnh của Chế độ xem phố về vị trí được chỉ định.

Ảnh toàn cảnh trong Chế độ xem phố

Chúng tôi hỗ trợ hình ảnh Chế độ xem phố thông qua việc sử dụng đối tượng StreetViewPanorama để cung cấp giao diện API cho "người xem" Chế độ xem phố. Mỗi bản đồ chứa một ảnh toàn cảnh trong Chế độ xem phố mặc định mà bạn có thể truy xuất bằng cách gọi phương thức getStreetView() của bản đồ. Khi bạn thêm một thành phần điều khiển Chế độ xem phố vào bản đồ bằng cách đặt tuỳ chọn streetViewControltrue, bạn sẽ tự động kết nối thành phần điều khiển Người hình mắc áo với ảnh toàn cảnh mặc định trên Chế độ xem phố.

Bạn cũng có thể tạo đối tượng StreetViewPanorama riêng và thiết lập bản đồ để sử dụng thay vì mặc định, bằng cách đặt thuộc tính streetView của bản đồ thành đối tượng được tạo. Bạn nên ghi đè ảnh 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ư tính năng tự động chia sẻ lớp phủ giữa bản đồ và ảnh toàn cảnh. (Xem Lớp phủ trong Chế độ xem phố bên dưới.)

Vùng chứa có Chế độ xem phố

Thay vào đó, bạn có thể muốn hiển thị StreetViewPanorama trong một phần tử DOM riêng biệt, thường là phần tử <div>. Bạn chỉ cần truyền phần tử DOM trong hàm khởi tạo của 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 pixel x 200 pixel.

Lưu ý: Mặc dù chức năng Chế độ xem 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 tính năng này. Bạn có thể sử dụng một đối tượng Chế độ xem phố độc lập mà không cần bản đồ.

Vị trí trong Chế độ xem phố và Điểm xem (POV)

Hàm dựng StreetViewPanorama cũng cho phép bạn đặt vị trí và điểm xem Chế độ xem phố bằng thông số StreetViewOptions. Sau khi xây dựng, bạn có thể gọi setPosition()setPov() trên đối tượng để thay đổi vị trí và POV của đối tượng.

Vị trí Chế độ xem phố xác định vị trí của tiêu điểm máy ảnh cho một hình ảnh, nhưng không xác định hướng của máy ảnh cho hình ảnh đó. Vì mục đích đó, đối tượng StreetViewPov sẽ xác định hai thuộc tính:

  • heading (0 mặc định) xác định góc xoay xung quanh vị trí máy ảnh theo độ tương đối so với hướng bắc thực. Tiêu đề được đo theo chiều kim đồng hồ (90 độ là hướng đông).
  • pitch (0 mặc định) xác định phương sai góc "lên" hoặc "xuống" từ cao độ mặc định ban đầu của máy ảnh, thường là (nhưng không phải lúc nào cũng) nằm ngang. (Ví dụ: hình ảnh được chụp trên đồi sẽ hiển thị cao độ mặc định không nằm ngang.) Góc độ cao được đo bằng các giá trị dương tính khi tra cứu (lên đến +90 độ thẳng lên và trực tiếp với cao độ mặc định) và các giá trị âm nhìn xuống (xuống dưới -90 độ và thẳng hàng với cao độ mặc định).

Đối tượng StreetViewPov thường được dùng để xác định góc nhìn của máy ảnh trong Chế độ xem phố. Bạn cũng có thể xác định góc nhìn của nhiếp ảnh gia, thường là hướng của xe ô tô hoặc xe đạp ba bánh 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. Chọn và kéo Người hình mắc áo đến một vị trí được hỗ trợ trên bản đồ sẽ thay đổi ảnh toàn cảnh của Chế độ xem phố:

TypeScript

function initialize() {
  const fenway = { lat: 42.345573, lng: -71.098326 };
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      center: fenway,
      zoom: 14,
    }
  );
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano") as HTMLElement,
    {
      position: fenway,
      pov: {
        heading: 34,
        pitch: 10,
      },
    }
  );

  map.setStreetView(panorama);
}

declare global {
  interface Window {
    initialize: () => void;
  }
}
window.initialize = initialize;

JavaScript

function initialize() {
  const fenway = { lat: 42.345573, lng: -71.098326 };
  const map = new google.maps.Map(document.getElementById("map"), {
    center: fenway,
    zoom: 14,
  });
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano"),
    {
      position: fenway,
      pov: {
        heading: 34,
        pitch: 10,
      },
    },
  );

  map.setStreetView(panorama);
}

window.initialize = initialize;

CSS

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#map,
#pano {
  float: left;
  height: 100%;
  width: 50%;
}

HTML

<html>
  <head>
    <title>Street View split-map-panes</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map"></div>
    <div id="pano"></div>

    <!-- 
      The `defer` attribute causes the callback 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>
Xem ví dụ

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 cho phép người dùng thay đổi chế độ xem Phố Chế độ xem dựa trên chuyển động của thiết bị. Người dùng có thể xem xung quanh bằng cách di chuyển thiết bị của họ. Đây được gọi là theo dõi chuyển động hoặc xoay vòng 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 được bật trên mọi thiết bị hỗ trợ tính năng này. Mẫu sau đây sẽ tắt tính năng theo dõi chuyển động, nhưng bạn vẫn có thể nhìn thấy chế độ điều khiển theo dõi chuyển động. (Lưu ý rằng người dùng có thể bật theo dõi chuyển động bằng cách nhấn vào đ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 thị điều khiển theo dõi chuyển động. Theo mặc định, tùy chọn điều khiển này hiển thị 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 tuỳ chọn đ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 tuỳ chọn điều khiển này 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 motionTrackingControl là gì.

    Mẫu sau đây sẽ tắt cả tính năng theo dõi chuyển động và điều khiển 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 điều khiển theo dõi chuyển động. Theo mặc định, tùy chọn điều khiển này xuất hiện gần phía dưới cùng bên phải của ảnh toàn cảnh (vị trí RIGHT_BOTTOM). Mẫu sau đây sẽ đặt vị trí của tùy chọn điều khiển này ở 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 trong thực tế, hãy xem mẫu sau đây 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ị):


Xem ví dụ

Lớp phủ trong Chế độ xem phố

Đối tượng StreetViewPanorama mặc định hỗ trợ việc hiển thị gốc các lớp phủ bản đồ. Lớp phủ thường xuất hiện ở "cấp đường phố" được neo tại các vị trí LatLng. (Ví dụ: các điểm đánh dấu sẽ xuất hiện neo vào đuôi máy bay ngang của vị trí trong toàn cảnh Chế độ xem phố chẳng hạn.)

Hiện tại, các loại lớp phủ được hỗ trợ trên ảnh toàn cảnh của Chế độ xem phố được giới hạn ở Marker, InfoWindowOverlayView tuỳ chỉnh. Lớp phủ mà bạn hiển thị trên bản đồ có thể được hiển thị trên ảnh toàn cảnh của Chế độ xem phố bằng cách xem ảnh toàn cảnh này như một đối tượng 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ự như vậy, bạn có thể mở các cửa sổ thông tin tương tự trong ảnh toàn cảnh của Chế độ xem phố bằng cách gọi open(), truyền StreetViewPanorama() thay vì bản đồ.

Ngoài ra, khi bạn tạo bản đồ bằng một 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 của Chế độ xem phố liên kết của bản đồ, miễn là bạn có thể nhìn thấy ảnh toàn cảnh đó. Để truy xuất ảnh toàn cảnh mặc định của Chế độ xem phố, hãy gọi getStreetView() trên đối tượng Map. Xin lưu ý rằng nếu đặt rõ thuộc tính streetView của bản đồ thành StreetViewPanorama của công trình, 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 cho biết nhiều địa điểm xung quanh Astor Place, thành phố New York. Chuyển chế độ hiển thị sang Chế độ xem phố để hiển thị các điểm đánh dấu được chia sẻ hiển thị trong StreetViewPanorama.

TypeScript

let panorama: google.maps.StreetViewPanorama;

function initMap(): void {
  const astorPlace = { lat: 40.729884, lng: -73.990988 };

  // Set up the map
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      center: astorPlace,
      zoom: 18,
      streetViewControl: false,
    }
  );

  document
    .getElementById("toggle")!
    .addEventListener("click", toggleStreetView);

  // Set up the markers on the map
  const cafeMarker = new google.maps.Marker({
    position: { lat: 40.730031, lng: -73.991428 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=cafe|FFFF00",
    title: "Cafe",
  });

  const bankMarker = new google.maps.Marker({
    position: { lat: 40.729681, lng: -73.991138 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=dollar|FFFF00",
    title: "Bank",
  });

  const busMarker = new google.maps.Marker({
    position: { lat: 40.729559, lng: -73.990741 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=bus|FFFF00",
    title: "Bus Stop",
  });

  // We get the map's default panorama and set up some defaults.
  // Note that we don't yet set it visible.
  panorama = map.getStreetView()!; // TODO fix type
  panorama.setPosition(astorPlace);
  panorama.setPov(
    /** @type {google.maps.StreetViewPov} */ {
      heading: 265,
      pitch: 0,
    }
  );
}

function toggleStreetView(): void {
  const toggle = panorama.getVisible();

  if (toggle == false) {
    panorama.setVisible(true);
  } else {
    panorama.setVisible(false);
  }
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

let panorama;

function initMap() {
  const astorPlace = { lat: 40.729884, lng: -73.990988 };
  // Set up the map
  const map = new google.maps.Map(document.getElementById("map"), {
    center: astorPlace,
    zoom: 18,
    streetViewControl: false,
  });

  document.getElementById("toggle").addEventListener("click", toggleStreetView);

  // Set up the markers on the map
  const cafeMarker = new google.maps.Marker({
    position: { lat: 40.730031, lng: -73.991428 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=cafe|FFFF00",
    title: "Cafe",
  });
  const bankMarker = new google.maps.Marker({
    position: { lat: 40.729681, lng: -73.991138 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=dollar|FFFF00",
    title: "Bank",
  });
  const busMarker = new google.maps.Marker({
    position: { lat: 40.729559, lng: -73.990741 },
    map,
    icon: "https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=bus|FFFF00",
    title: "Bus Stop",
  });

  // We get the map's default panorama and set up some defaults.
  // Note that we don't yet set it visible.
  panorama = map.getStreetView(); // TODO fix type
  panorama.setPosition(astorPlace);
  panorama.setPov(
    /** @type {google.maps.StreetViewPov} */ {
      heading: 265,
      pitch: 0,
    },
  );
}

function toggleStreetView() {
  const toggle = panorama.getVisible();

  if (toggle == false) {
    panorama.setVisible(true);
  } else {
    panorama.setVisible(false);
  }
}

window.initMap = initMap;

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
  height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#floating-panel {
  position: absolute;
  top: 10px;
  left: 25%;
  z-index: 5;
  background-color: #fff;
  padding: 5px;
  border: 1px solid #999;
  text-align: center;
  font-family: "Roboto", "sans-serif";
  line-height: 30px;
  padding-left: 10px;
}

#floating-panel {
  margin-left: -100px;
}

HTML

<html>
  <head>
    <title>Overlays Within Street View</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="floating-panel">
      <input type="button" value="Toggle Street View" id="toggle" />
    </div>
    <div id="map"></div>

    <!-- 
      The `defer` attribute causes the callback 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>
Xem ví dụ

Dùng thử mẫu

Sự kiện Chế độ xem phố

Khi di chuyển giữa Chế độ xem phố hoặc thao tác với hướng của chế độ xem này, bạn có thể muốn theo dõi một số sự kiện cho biết trạng thái của StreetViewPanorama đã thay đổi:

  • pano_changed kích hoạt bất cứ khi nào toàn bộ mã toàn cảnh thay đổi. Sự kiện này không đảm bảo rằng mọi dữ liệu liên quan trong ảnh toàn cảnh (chẳng hạn như các đường liên kết) cũng đã thay đổi theo thời điểm kích hoạt sự kiện này; sự kiện này chỉ cho biết một ảnh toàn cảnh đã thay đổi. Lưu ý rằng mã ảnh toàn cảnh (bạn có thể sử dụng để tham chiếu ảnh toàn cảnh này) chỉ ổn định trong phiên trình duyệt hiện tại.
  • position_changed 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. 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 ID toàn cảnh được liên kết, vì API này sẽ tự động liên kết ID ảnh toàn cảnh gần nhất với vị trí của ảnh toàn cảnh.
  • pov_changed kích hoạt bất cứ khi nào StreetViewPov của Chế độ xem 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 toàn cảnh vẫn ổn định.
  • links_changed kích hoạt bất cứ khi nào đường liên kết của Chế độ xem 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 thay đổi giá trị nhận dạng ảnh toàn cảnh được chỉ định thông qua pano_changed.
  • visible_changed kích hoạt bất cứ khi nào chế độ hiển thị của Chế độ xem 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 thay đổi giá trị nhận dạng ảnh toàn cảnh được chỉ định thông qua pano_changed.

Mã sau đây 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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="pano"></div>
    <div id="floating-panel">
      <table>
        <tr>
          <td><b>Position</b></td>
          <td id="position-cell">&nbsp;</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">&nbsp;</td>
        </tr>
        <table id="links_table"></table>
      </table>
    </div>

    <!-- 
      The `defer` attribute causes the callback 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>
Xem ví dụ

Dùng thử mẫu

Điều khiển Chế độ xem phố

Khi hiển thị StreetViewPanorama, nhiều tuỳ chọn điều khiển xuất hiện trên ảnh toàn cảnh theo mặc định. Bạn có thể bật hoặc tắt các chế độ điều khiển này bằng cách đặt các trường thích hợp trong StreetViewPanoramaOptions thành true hoặc false:

  • panControl cung cấp một cách để xoay ảnh toàn cảnh. Chế độ điều khiển này xuất hiện theo mặc định dưới dạng một chế độ điều khiển xoay và la bàn tích hợp chuẩn. Bạn có thể thay đổi vị trí của tùy chọn điều khiển bằng cách cung cấp PanControlOptions trong trường panControlOptions.
  • zoomControl cung cấp một cách để phóng to hình ảnh. Chế độ điều khiển này xuất hiện theo mặc định ở gần phía 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 thành phần điều khiển bằng cách cung cấp ZoomControlOptions trong trường zoomControlOptions.
  • addressControl cung cấp 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 thành phần điều khiển bằng cách cung cấp StreetViewAddressControlOptions trong trường addressControlOptions.
  • fullscreenControl cung cấp tuỳ chọn mở Chế độ xem phố ở chế độ toàn màn hình. Bạn có thể thay đổi giao diện của thành phần điều khiển bằng cách cung cấp FullscreenControlOptions trong trường fullscreenControlOptions.
  • motionTrackingControl cung cấp tuỳ chọ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 những thiết bị hỗ trợ sự kiện hướng thiết bị. Theo mặc định, chế độ điều khiển này xuất hiện gần phía 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 tùy chọn điều khiển bằng cách cung cấp MotionTrackingControlOptions. Để biết thêm thông tin, hãy xem phần theo dõi chuyển động.
  • linksControl cung cấp các mũi tên chỉ dẫn trên hình ảnh để di chuyển đến các ảnh toàn cảnh liền kề.
  • Kiểm soát đóng cho phép người dùng đóng trình xem Chế độ xem phố. Bạn có thể bật hoặc tắt tính năng Kiểm soát đóng bằng cách đặt enableCloseButton thành true hoặc false.

Sau đây là ví dụ thay đổi các tùy chọn điều khiển hiển thị trong Chế độ xem phố liên kết và xóa các đường liên kết của chế độ xem:

TypeScript

function initPano() {
  // Note: constructed panorama objects have visible: true
  // set by default.
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("map") as HTMLElement,
    {
      position: { lat: 42.345573, lng: -71.098326 },
      addressControlOptions: {
        position: google.maps.ControlPosition.BOTTOM_CENTER,
      },
      linksControl: false,
      panControl: false,
      enableCloseButton: false,
    }
  );
}

declare global {
  interface Window {
    initPano: () => void;
  }
}
window.initPano = initPano;

JavaScript

function initPano() {
  // Note: constructed panorama objects have visible: true
  // set by default.
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("map"),
    {
      position: { lat: 42.345573, lng: -71.098326 },
      addressControlOptions: {
        position: google.maps.ControlPosition.BOTTOM_CENTER,
      },
      linksControl: false,
      panControl: false,
      enableCloseButton: false,
    },
  );
}

window.initPano = initPano;

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
  height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

HTML

<html>
  <head>
    <title>Street View Controls</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map"></div>

    <!-- 
      The `defer` attribute causes the callback 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>
Xem ví dụ

Dùng thử mẫu

Truy cập trực tiếp vào dữ liệu Chế độ xem phố

Bạn nên lập trình để xác định khả năng truy cập của dữ liệu Chế độ xem phố hoặc trả về thông tin về ả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 phố của Google.

Yêu cầu dịch vụ Chế độ xem phố

Việc truy cập dịch vụ Chế độ xem phố là không đồng bộ vì API Google Maps cần thực hiện lệnh gọi đến máy chủ bên ngoài. Vì lý do đó, bạn cần chuyển phương thức callback để gọi lại khi hoàn tất yêu cầu. Phương thức gọi lại này sẽ xử lý kết quả.

Bạn có thể bắt đầu các yêu cầu đến StreetViewService bằng StreetViewPanoRequest hoặc StreetViewLocationRequest.

Một yêu cầu sử dụng StreetViewPanoRequest sẽ trả về dữ liệu ảnh toàn cảnh qua một mã tham chiếu giúp nhận dạng duy nhất ảnh toàn cảnh đó. Xin lưu ý rằng các mã tham chiếu này chỉ ổn định trong suốt thời gian tồn tại của hình ảnh toàn cảnh đó.

Yêu cầu sử dụng StreetViewLocationRequest tìm kiếm dữ liệu toàn cảnh tại một vị trí cụ thể, bằng cách sử dụng các tham số sau:

  • location chỉ định vị trí (vĩ độ và kinh độ) để tìm kiếm ảnh toàn cảnh.
  • preference đặt tùy chọn để tìm thấy ảnh toàn cảnh trong bán kính: ảnh gần nhất với vị trí đã cung cấp hoặc ảnh tốt nhất trong bán kính.
  • radius đặt bán kính, xác định theo mét, để tìm kiếm một ảnh toàn cảnh, tập trung vào vĩ độ và kinh độ đã cho. Mặc định là 50 khi không được cung cấp.
  • source chỉ định nguồn ảnh toàn cảnh để tìm kiếm. Các giá trị hợp lệ là:
    • default sử dụng các nguồn mặc định cho Chế độ xem phố; tìm kiếm không bị giới hạn ở các nguồn cụ thể.
    • outdoor giới hạn phạm vi tìm kiếm ở các bộ sưu tập ngoài trời. Lưu ý rằng ảnh toàn cảnh ngoài trời có thể không tồn tại cho vị trí được chỉ định.

Phản hồi của dịch vụ Chế độ xem phố

Hàm getPanorama() cần có một hàm gọi lại để thực thi khi truy xuất kết quả từ dịch vụ Chế độ xem phố. Hàm callback này trả về một tập hợp dữ liệu ảnh toàn cảnh trong đối tượng StreetViewPanoramaData và một mã StreetViewStatus biểu thị trạng thái của yêu cầu theo thứ tự đó.

Thông số đối tượng StreetViewPanoramaData chứa siêu dữ liệu về ảnh toàn cảnh của Chế độ xem phố có dạng như 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
  }
}

Lưu ý rằng đối tượng dữ liệu này không phải là đối tượng StreetViewPanorama. Để tạo một đối tượng Chế độ xem phố bằng dữ liệu này, bạn cần tạo một StreetViewPanorama và gọi setPano(), truyền vào đó mã nhận dạng như đã lưu ý trong trường location.pano được trả về.

status có thể trả về một trong các giá trị sau:

  • OK cho biết dịch vụ đã tìm thấy ảnh toàn cảnh phù hợp.
  • ZERO_RESULTS cho biết dịch vụ không tìm thấy ảnh toàn cảnh phù hợp với tiêu chí đã vượt qua.
  • UNKNOWN_ERROR cho biết rằng hệ thống không thể xử lý yêu cầu Chế độ xem phố, mặc dù chưa xác định được lý do chính xác.

Mã sau đây tạo ra một StreetViewService dùng để phản hồi hoạt động nhấp của người dùng trên bản đồ bằng cách tạo ra các điểm đánh dấu khi được nhấp vào, hiển thị 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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map" style="width: 45%; height: 100%; float: left"></div>
    <div id="pano" style="width: 45%; height: 100%; float: left"></div>

    <!-- 
      The `defer` attribute causes the callback 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>
Xem ví dụ

Dùng thử mẫu

Cung cấp ảnh toàn cảnh ở Chế độ xem phố tùy chỉnh

API JavaScript của Maps hỗ trợ hiển thị ảnh toàn cảnh tùy chỉnh trong đối tượng StreetViewPanorama. Sử dụng ảnh toàn cảnh tùy chỉnh, bạn có thể hiển thị nội thất của các tòa nhà, quang cảnh từ các vị trí tuyệt đẹp hoặc bất cứ điều gì từ trí tưởng tượng của bạn. Thậm chí, bạn có thể liên kết những ảnh toàn cảnh tùy chỉnh này với ảnh toàn cảnh trong Chế độ xem phố hiện có của Google.

Thiết lập một bộ ảnh toàn cảnh tùy chỉnh bao gồm các bước sau:

  • Tạo ảnh toàn cảnh cơ sở cho từng ảnh toàn cảnh tùy 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 tập hợp các ô toàn cảnh ở nhiều mức thu phóng khác nhau so với hình ảnh cơ bản.
  • Tạo liên kết giữa ảnh toàn cảnh tùy chỉnh của bạn.
  • (Không bắt buộc) Chỉ định ảnh toàn cảnh "mục nhập" trong hình ảnh Chế độ xem phố hiện tại của Google và tùy chỉnh đường liên kết đến/từ bộ tùy chỉnh đến bộ tiêu chuẩn.
  • Xác định siêu dữ liệu cho mỗi ảnh toàn cảnh trong một đố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 của bạn trong đối tượng StreetViewPanorama.

Các phần sau giải thích quy trình này.

Tạo ảnh toàn cảnh tùy chỉnh

Mỗi ảnh toàn cảnh của Chế độ xem phố là một hình ảnh hoặc một tập hợp các hình ảnh cung cấp chế độ xem toàn cảnh 360 độ từ một vị trí. Đối tượng StreetViewPanorama sử dụng hình ảnh phù hợp với phép chiếu hình chữ nhật (Plate Carrée). Chế độ chiếu như vậy chứa góc nhìn ngang 360 độ (xoay toàn bộ) và góc dọc 180 độ (từ thẳng lên đến thẳng). Các trường xem này dẫn đến một hình ảnh có tỷ lệ khung hình là 2:1. Bên dưới là ảnh toàn cảnh bao quanh đầy đủ.

Toàn cảnh phố phường

Hình ảnh toàn cảnh thường có được bằng cách chụp nhiều ảnh từ một vị trí và ghép chúng lại với nhau bằng phần mềm ảnh toàn cảnh. (Hãy xem phần 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ó chung một quỹ tích "máy ảnh", là nơi chụp từng ảnh toàn cảnh. Sau đó, ảnh toàn cảnh 360 độ có thể xác định một phép chiếu trên một hình cầu có hình ảnh được bọc vào bề mặt hai chiều của hình cầu.

Quả cầu với tầm nhìn toàn cảnh của một con phố trên bề mặt của nó

Ưu điểm của ảnh toàn cảnh như một phép chiếu trên hình cầu có hệ thống tọa độ trực tuyến là một lợi thế khi chia hình ảnh thành các ô trực tuyến và phân phát hình ảnh dựa trên toạ độ ô được tính toán.

Tạo Thẻ thông tin Toàn cảnh Tùy chỉnh

Chế độ xem phố cũng hỗ trợ nhiều mức độ chi tiết hình ảnh thông qua một chế độ điều khiển thu phóng, cho phép bạn phóng to và thu nhỏ chế độ xem mặc định. Nhìn chung, Chế độ xem phố cung cấp năm độ phân giải thu phóng cho bất kỳ ảnh toàn cảnh nào. Nếu bạn chỉ phải dựa vào một ảnh toàn cảnh duy nhất để phân phát tất cả các mức thu phóng, thì hình ảnh như vậy sẽ phải khá lớn và làm chậm đáng kể ứng dụng của bạn hoặc có độ phân giải kém ở các mức thu phóng cao đến mức bạn sẽ phân phát hình ảnh kém pixel. Tuy nhiên, rất may là chúng tôi có thể sử dụng mẫu thiết kế tương tự 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 thích hợp cho ảnh toàn cảnh ở mỗi mức thu phóng.

Khi tải lần đầu tiên, StreetViewPanorama sẽ hiển thị một hình ảnh bao gồm 25% (90 độ cung) của chiều ngang của ảnh toàn cảnh ở mức thu phóng 1. Thành phần hiển thị này tương ứng với trường nhìn của con người bình thường. Về cơ bản, thao tác thu nhỏ "ngoài" trong chế độ xem mặc định sẽ cung cấp một vòng cung rộng hơn, đồng thời thu nhỏ trường trong chế độ xem thành một vòng cung nhỏ hơn. StreetViewPanorama tự động tính toán trường nhìn thích hợp cho mức thu phóng đã chọn, sau đó chọn hình ảnh thích hợp nhất cho độ phân giải đó bằng cách chọn một tập hợp ô gần tương ứng với kích thước của trường nhìn ngang. Các trường sau đây của bản đồ ánh xạ tới mức thu phóng của Chế độ xem phố:

Mức thu phóng của Chế độ xem phố Trường xem (độ)
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 hiển thị trong Chế độ xem phố phụ thuộc hoàn toàn vào kích thước màn hình (chiều rộng) của vùng chứa Chế độ xem phố. Nếu bạn cung cấp một vùng chứa rộng hơn, thì dịch vụ sẽ vẫn 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ù có thể chọn ô phù hợp hơn cho độ phân giải đó.

Vì mỗi ảnh toàn cảnh bao gồm một phép chiếu hình chữ nhật, nên việc tạo ô ả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 ô vuông có tỷ lệ 2:1 sẽ dễ sử dụng hơn, mặc dù ô vuông có thể mang lại hiệu suất tốt hơn trên bản đồ hình vuông (vì trường xem 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 đại diện cho toàn bộ "thế giới" (hình ảnh cơ sở) ở mức thu phóng 0, với mỗi cấp độ thu phóng tăng dần cung cấp 4 ôzoomLevel. (Ví dụ: ở mức thu phóng 2, toàn bộ ảnh toàn cảnh bao gồm 16 ô.) Lưu ý: mức thu phóng trong ô của Chế độ xem phố không phù hợp trực tiếp với mức thu phóng như được cung cấp bằng chế độ điều khiển Chế độ xem phố. Thay vào đó, mức thu phóng của chế độ xem phố sẽ chọn Trường nhìn (FoV), nơi sẽ chọn ô phù hợp.

Toàn cảnh phố được lát gạch

Nhìn chung, bạn nên đặt tên cho các hình ảnh để có thể chọn các hình ảnh theo cách lập trình. Sơ đồ đặt tên như vậy sẽ được thảo luận dưới đây trong phần Xử lý yêu cầu ảnh toàn cảnh tuỳ chỉnh.

Xử lý yêu cầu ảnh toàn cảnh tùy 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 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à đối tượng của biểu mẫu 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 tùy chỉnh như sau:

  • Đặt thuộc tính StreetViewPanoramaOptions.pano thành một giá trị tùy chỉnh.
  • Gọi StreetViewPanorama.registerPanoProvider() để cung cấp hàm tuỳ chỉnh của nhà cung cấp ảnh toàn cảnh.
  • Triển khai hàm nhà cung cấp ảnh toàn cảnh tuỳ chỉnh để xử lý giá trị pano được chỉ định.
  • Tạo một đối tượng StreetViewPanoramaData.
  • Đặt thuộc tính StreetViewTileData.getTileUrl thành tên của hàm trình cung cấp ô tuỳ chỉnh mà bạn cung cấp. Ví dụ: getCustomPanoramaTileUrl.
  • Triển khai hàm tuỳ chỉnh của trình cung cấp ô, như hiển thị trong các mẫu dưới đây.
  • Trả về đối tượng StreetViewPanoramaData.

Lưu ý: Không trực tiếp đặt position trên StreetViewPanorama khi bạn muốn hiển thị ảnh toàn cảnh tùy chỉnh, vì vị trí như vậy sẽ hướng dẫn dịch vụ Chế độ xem phố yêu cầu hình ảnh Chế độ xem phố mặc định gần với vị trí đó. Thay vào đó, hãy đặt vị trí này trong trường location.latLng tuỳ chỉnh của đối tượng StreetViewPanoramaData.

Ví dụ sau đây cho thấy ảnh toàn cảnh tuỳ chỉnh của văn phòng Google ở 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 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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map"></div>

    <!-- 
      The `defer` attribute causes the callback 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>
Xem ví dụ

Dùng thử mẫu

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 toàn cảnh đã được truyền, cấp độ thu phóng và ô tọa độ. Vì lựa chọn hình ảnh phụ thuộc vào các giá trị đã truyền này, bạn nên đặt tên cho các hình ảnh có thể chọn bằng cách lập trình dựa trên các giá trị được chuyể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 mặc định của Chế độ xem phố) trỏ đến 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",
      description: "Google Sydney - Reception",
      latLng: new google.maps.LatLng(-33.86684, 151.19583),
    },
    links: [
      {
        heading: 195,
        description: "Exit",
        pano: outsideGoogle.location.pano,
      },
    ],
    copyright: "Imagery (c) 2010 Google",
    tiles: {
      tileSize: new google.maps.Size(1024, 512),
      worldSize: new google.maps.Size(2048, 1024),
      centerHeading: 105,
      getTileUrl: function (pano, zoom, tileX, tileY) {
        return (
          "https://developers.google.com/maps/documentation/javascript/examples/full/images/" +
          "panoReception1024-" +
          zoom +
          "-" +
          tileX +
          "-" +
          tileY +
          ".jpg"
        );
      },
    },
  };
}

function initPanorama() {
  panorama = new google.maps.StreetViewPanorama(
    document.getElementById("street-view"),
    { pano: outsideGoogle.location.pano },
  );
  // Register a provider for the custom panorama.
  panorama.registerPanoProvider((pano) => {
    if (pano === "reception") {
      return getReceptionPanoramaData();
    }
    // @ts-ignore TODO fix typings
    return null;
  });
  // Add a link to our custom panorama from outside the Google Sydney office.
  panorama.addListener("links_changed", () => {
    if (panorama.getPano() === outsideGoogle.location.pano) {
      panorama.getLinks().push({
        description: "Google Sydney",
        heading: 25,
        pano: "reception",
      });
    }
  });
}

function initMap() {
  // Use the Street View service to find a pano ID on Pirrama Rd, outside the
  // Google office.
  new google.maps.StreetViewService()
    .getPanorama({ location: { lat: -33.867386, lng: 151.195767 } })
    .then(({ data }) => {
      outsideGoogle = data;
      initPanorama();
    });
}

window.initMap = initMap;

CSS

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#street-view {
  height: 100%;
}

HTML

<html>
  <head>
    <title>Custom Street View Panorama Tiles</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="street-view"></div>

    <!-- 
      The `defer` attribute causes the callback 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>
Xem ví dụ

Dùng thử mẫu