บริการ Street View

ภาพรวม

เลือกแพลตฟอร์ม: Android iOS JavaScript

Google Street View แสดงภาพมุมมอง 360 องศาจากถนนที่กำหนดทั่วทั้งพื้นที่ที่ครอบคลุม ความครอบคลุมของ API ของ Street View จะเหมือนกับความครอบคลุมของแอปพลิเคชัน Google Maps (https://maps.google.com/) รายชื่อเมืองที่รองรับ Street View ในปัจจุบันอยู่ที่เว็บไซต์ Google Maps

ตัวอย่างภาพ Street View แสดงอยู่ด้านล่าง


Maps JavaScript API มีบริการ Street View สำหรับการขอรับและจัดการภาพที่ใช้ใน Street View ของ Google Maps บริการ Street View นี้มีการรองรับในตัวภายใน เบราว์เซอร์

การใช้แผนที่ Street View

แม้ว่า Street View จะใช้ภายในองค์ประกอบ DOM แบบสแตนด์อโลนได้ แต่ก็มีประโยชน์มากที่สุดในการระบุตำแหน่งบนแผนที่ โดยค่าเริ่มต้น ระบบจะเปิดใช้ Street View บนแผนที่ และการควบคุมแบบเพ็กแมนของ Street View จะปรากฏขึ้นที่รวมอยู่ในตัวควบคุมการนําทาง (ซูมและเลื่อน) คุณซ่อนการควบคุมนี้ภายใน MapOptions ของแผนที่ได้โดยการตั้งค่า streetViewControl เป็น false คุณยังเปลี่ยนตำแหน่งเริ่มต้นของตัวควบคุม Street View ได้ด้วยการตั้งค่าพร็อพเพอร์ตี้ streetViewControlOptions.position ของ Map เป็น ControlPosition ใหม่

การควบคุมเพ็กแมนของ Street View ช่วยให้คุณสามารถดูภาพพาโนรามาของ Street View ภายในแผนที่ได้โดยตรง เมื่อผู้ใช้คลิกและค้างไว้เพ็กแมน แผนที่จะอัปเดตเพื่อแสดงเส้นกรอบสีน้ำเงินรอบถนนที่สามารถใช้ Street View ได้ ซึ่งจะมอบประสบการณ์ของผู้ใช้ที่คล้ายกับแอป Google Maps

เมื่อผู้ใช้วางเครื่องหมายเพ็กแมนลงบนถนน ระบบจะอัปเดตแผนที่เพื่อแสดงภาพพาโนรามา Street View ของตำแหน่งที่ระบุ

ภาพพาโนรามาของ Street View

รูปภาพ Street View ได้รับการสนับสนุนผ่านการใช้ออบเจ็กต์ StreetViewPanorama ซึ่งมอบอินเทอร์เฟซ API ให้กับ "ผู้ดู" ของ Street View แผนที่แต่ละรายการจะมีภาพพาโนรามาเริ่มต้นของ Street View ซึ่งคุณเรียกดูได้โดยเรียกใช้เมธอด getStreetView() ของแผนที่ เมื่อเพิ่มตัวควบคุม Street View ลงในแผนที่โดยตั้งค่าตัวเลือก streetViewControl เป็น true จะเป็นการเชื่อมต่อการควบคุมเพ็กแมนกับภาพพาโนรามาเริ่มต้นของ Street View นี้โดยอัตโนมัติ

คุณยังสร้างออบเจ็กต์ StreetViewPanorama ของคุณเองและตั้งค่าแผนที่ให้ใช้ออบเจ็กต์ดังกล่าวแทนค่าเริ่มต้นได้ด้วยโดยตั้งค่าพร็อพเพอร์ตี้ streetView ของแผนที่ให้กับวัตถุที่สร้างขึ้นนั้นอย่างชัดเจน คุณอาจต้องการลบล้างภาพพาโนรามาเริ่มต้นหากต้องการปรับเปลี่ยนการทำงานเริ่มต้น เช่น การแชร์ภาพซ้อนโดยอัตโนมัติระหว่างแผนที่และพาโนรามา (ดูการวางซ้อนภายใน Street View ด้านล่าง)

คอนเทนเนอร์ Street View

คุณอาจต้องการแสดง StreetViewPanorama ภายในองค์ประกอบ DOM แยกต่างหาก ซึ่งมักจะเป็นองค์ประกอบ <div> เพียงส่งองค์ประกอบ DOM ภายในตัวสร้างของ StreetViewPanorama สำหรับการแสดงภาพที่มีประสิทธิภาพสูงสุด เราขอแนะนำขนาดขั้นต่ำที่ 200 พิกเซล x 200 พิกเซล

หมายเหตุ: แม้ว่าฟังก์ชันการทำงานของ Street View จะออกแบบมาให้ใช้ร่วมกับแผนที่ แต่ก็ไม่จำเป็นต้องใช้ฟังก์ชันการทำงานนี้ คุณใช้วัตถุ Street View แบบสแตนด์อโลนที่ไม่มีแผนที่ได้

ตำแหน่ง Street View และจุดมุมมอง (POV)

ตัวสร้าง StreetViewPanorama ยังช่วยให้คุณตั้งค่าตำแหน่งและมุมมองของ Street View โดยใช้พารามิเตอร์ StreetViewOptions ได้อีกด้วย คุณอาจเรียกใช้ setPosition() และ setPov() บนออบเจ็กต์หลังการก่อสร้างเพื่อเปลี่ยนตำแหน่งและ POV ของออบเจ็กต์ดังกล่าว

ตำแหน่ง Street View เป็นตัวกำหนดตำแหน่งของโฟกัสกล้องถ่ายรูปสำหรับรูปภาพ แต่ไม่ได้กำหนดการวางแนวของกล้องสำหรับรูปภาพนั้น เพื่อวัตถุประสงค์ดังกล่าว ออบเจ็กต์ StreetViewPov จะกำหนดพร็อพเพอร์ตี้ 2 รายการดังนี้

  • heading (ค่าเริ่มต้น 0) กำหนดมุมการหมุนรอบโลคัสของกล้องในหน่วยองศาที่สัมพัทธ์จากทิศเหนือจริง ระบบจะวัดส่วนหัวตามเข็มนาฬิกา (90 องศาคือทิศตะวันออกที่ถูกต้อง)
  • pitch (0 เริ่มต้น) กำหนดความแปรปรวนของมุม "ขึ้น" หรือ "ลง" จากระดับความสูงต่ำเริ่มต้นของกล้อง ซึ่งมักเป็นแนวนอนแบน (แต่ไม่เสมอไป) (เช่น รูปภาพที่ถ่ายบนเนินเขามีแนวโน้มที่จะแสดงระดับเสียงเริ่มต้นที่ไม่ใช่แนวนอน) มุมแหลมจะวัดด้วยค่าบวกเมื่อมองขึ้น (ถึง +90 องศาตั้งตรงและตั้งฉากกับระดับความสูงต่ำเริ่มต้น) และค่าลบที่มองลงด้านล่าง (-90 องศาตรงด้านล่างและตั้งฉากกับระดับความสูงต่ำเริ่มต้น)

วัตถุ StreetViewPov มักใช้เพื่อระบุมุมมองของกล้อง Street View นอกจากนี้คุณยังกำหนดมุมมองของช่างภาพได้ ซึ่งโดยทั่วไปคือทิศทางที่รถยนต์หรือรถสามล้อหันไปโดยใช้วิธี StreetViewPanorama.getPhotographerPov()

รหัสต่อไปนี้แสดงแผนที่ของบอสตันพร้อมมุมมองเริ่มต้นของสนามเบสบอล Fenway Park การเลือกเพ็กแมนและลากไปยังตำแหน่งที่รองรับบนแผนที่จะเป็นการเปลี่ยนพาโนรามาของ Street View

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>
ดูตัวอย่าง

ลองใช้ตัวอย่าง

การติดตามการเคลื่อนไหวในอุปกรณ์เคลื่อนที่

ในอุปกรณ์ที่รองรับเหตุการณ์การวางแนวอุปกรณ์ API จะให้ผู้ใช้สามารถเปลี่ยนมุมมองของ Street View ตามการเคลื่อนไหวของอุปกรณ์ได้ ผู้ใช้สามารถมองไปรอบๆ ด้วยการขยับอุปกรณ์ ซึ่งเรียกว่าการติดตามการเคลื่อนไหวหรือการติดตามการหมุนอุปกรณ์

ในฐานะนักพัฒนาแอป คุณสามารถเปลี่ยนลักษณะการทำงานเริ่มต้นได้ดังนี้

  • เปิดหรือปิดใช้งานฟังก์ชันการติดตามการเคลื่อนไหว โดยค่าเริ่มต้น ระบบจะเปิดใช้การติดตามการเคลื่อนไหวในอุปกรณ์ใดก็ตามที่รองรับ ตัวอย่างต่อไปนี้จะปิดใช้การติดตามการเคลื่อนไหว แต่ยังคงมองเห็นการควบคุมการติดตามการเคลื่อนไหว (โปรดทราบว่าผู้ใช้จะเปิดการติดตามการเคลื่อนไหวได้โดยแตะที่ตัวควบคุม)
    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTracking: false
        });
    
  • ซ่อนหรือแสดงตัวควบคุมการติดตามการเคลื่อนไหว โดยค่าเริ่มต้น ตัวควบคุมจะแสดงในอุปกรณ์ที่รองรับการติดตามการเคลื่อนไหว ผู้ใช้แตะที่ตัวควบคุมเพื่อเปิดหรือปิดการติดตามการเคลื่อนไหวได้ โปรดทราบว่าตัวควบคุมจะไม่ปรากฏหากอุปกรณ์ไม่รองรับการติดตามการเคลื่อนไหว ไม่ว่าค่าของ motionTrackingControl จะเป็นอะไรก็ตาม

    ตัวอย่างต่อไปนี้จะปิดใช้ทั้งการติดตามการเคลื่อนไหวและการควบคุมการติดตามการเคลื่อนไหว ในกรณีนี้ ผู้ใช้จะเปิดการติดตามการเคลื่อนไหวไม่ได้

    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTracking: false,
          motionTrackingControl: false
        });
    
  • เปลี่ยนตำแหน่งเริ่มต้นของการควบคุมการติดตามการเคลื่อนไหว โดยค่าเริ่มต้น ตัวควบคุมจะปรากฏที่บริเวณด้านขวาล่างของพาโนรามา (ตำแหน่ง RIGHT_BOTTOM) ตัวอย่างต่อไปนี้กำหนดตำแหน่งของตัวควบคุมไว้ที่ด้านล่างซ้าย:
    var panorama = new google.maps.StreetViewPanorama(
        document.getElementById('pano'), {
          position: {lat: 37.869260, lng: -122.254811},
          pov: {heading: 165, pitch: 0},
          motionTrackingControlOptions: {
            position: google.maps.ControlPosition.LEFT_BOTTOM
          }
        });
    

หากต้องการดูการทำงานของการติดตามการเคลื่อนไหว โปรดดูตัวอย่างต่อไปนี้บนอุปกรณ์เคลื่อนที่ (หรืออุปกรณ์ที่รองรับการวางแนวอุปกรณ์)


ดูตัวอย่าง

การวางซ้อนภายใน Street View

ออบเจ็กต์ StreetViewPanorama เริ่มต้นรองรับการแสดงแบบเนทีฟของการวางซ้อนแผนที่ โดยทั่วไปการวางซ้อนจะปรากฏที่ "ระดับถนน" และตรึงอยู่ที่ตำแหน่ง LatLng (ตัวอย่างเช่น เครื่องหมายจะปรากฏโดยมีหางซึ่งยึดกับระนาบแนวนอนของตำแหน่งนั้นๆ ภายในภาพพาโนรามาของ Street View เป็นต้น)

ปัจจุบันประเภทของการซ้อนทับที่รองรับในภาพพาโนรามาของ Street View จำกัดอยู่ที่ Marker, InfoWindow และ OverlayView แบบกำหนดเอง ภาพซ้อนทับที่คุณแสดงบนแผนที่อาจ แสดงในภาพพาโนรามาของ Street View โดยถือว่าภาพพาโนรามานั้นเป็นตัวแทน ของวัตถุ Map ซึ่งเรียก setMap() แล้วส่ง StreetViewPanorama เป็นอาร์กิวเมนต์แทนที่จะเป็นแผนที่ อาจเปิดหน้าต่างข้อมูลในลักษณะเดียวกันในภาพพาโนรามาของ Street View ได้โดยโทรไปที่ open() แล้วส่ง StreetViewPanorama() แทนแผนที่

นอกจากนี้ เมื่อสร้างแผนที่ที่มี StreetViewPanorama เริ่มต้น เครื่องหมายที่สร้างขึ้นบนแผนที่จะแชร์โดยอัตโนมัติกับภาพพาโนรามาของ Street View ที่เกี่ยวข้องในแผนที่หากภาพพาโนรามานั้นมองเห็นได้ หากต้องการเรียกภาพพาโนรามาเริ่มต้นของ Street View ให้เรียก getStreetView() ที่วัตถุ Map โปรดทราบว่าหากคุณตั้งค่าพร็อพเพอร์ตี้ streetView ของแผนที่เป็น StreetViewPanorama ของการก่อสร้างของคุณเอง จะลบล้างภาพพาโนรามาเริ่มต้น

ตัวอย่างต่อไปนี้แสดงเครื่องหมายที่แสดงตำแหน่งต่างๆ รอบ Astor Place ในนิวยอร์ก สลับการแสดงผลเป็น Street View เพื่อแสดงเครื่องหมายที่แชร์กันภายใน 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>
ดูตัวอย่าง

ลองใช้ตัวอย่าง

เหตุการณ์ Street View

เมื่อนำทางไปมาระหว่าง Street View หรือเปลี่ยนการวางแนว คุณอาจต้องการตรวจสอบหลายเหตุการณ์ที่ระบุ การเปลี่ยนแปลงสถานะของ StreetViewPanorama ดังนี้

  • pano_changed เริ่มทำงานเมื่อรหัสพาโนรามาแต่ละรายการมีการเปลี่ยนแปลง เหตุการณ์นี้ไม่รับประกันว่าข้อมูลใดๆ ที่เชื่อมโยงภายในพาโนรามา (เช่น ลิงก์) จะเปลี่ยนไปด้วยเมื่อมีการทริกเกอร์เหตุการณ์นี้ด้วย เหตุการณ์นี้บ่งชี้ว่ารหัสพาโนรามามีการเปลี่ยนแปลงเท่านั้น โปรดทราบว่ารหัสพาโนรามา (ซึ่งใช้อ้างอิงพาโนรามานี้ได้) จะเสถียรเฉพาะในเซสชันปัจจุบันของเบราว์เซอร์เท่านั้น
  • position_changed เริ่มทำงานเมื่อตำแหน่ง (LatLng) ที่เกี่ยวข้องของพาโนรามามีการเปลี่ยนแปลง การหมุนภาพพาโนรามาจะไม่ทริกเกอร์เหตุการณ์นี้ โปรดทราบว่าคุณสามารถเปลี่ยน ตำแหน่งที่อยู่ของพาโนรามาได้โดยไม่ต้องเปลี่ยน รหัสพาโนรามาที่เชื่อมโยง เนื่องจาก API จะเชื่อมโยง รหัสพาโนรามาที่ใกล้ที่สุดเข้ากับตำแหน่งของพาโนรามาโดยอัตโนมัติ
  • pov_changed เริ่มทำงานเมื่อ StreetViewPov ของ Street View มีการเปลี่ยนแปลง โปรดทราบว่าเหตุการณ์นี้อาจเริ่มทำงานขณะที่ตำแหน่งและรหัสพาโนยังคงไม่เปลี่ยนแปลง
  • links_changed เริ่มทำงานเมื่อลิงก์ของ Street View เปลี่ยนแปลง โปรดทราบว่าเหตุการณ์นี้อาจเริ่มทำงานแบบไม่พร้อมกันหลังจากมีการเปลี่ยนแปลงรหัสพาโนรามาที่ระบุไว้ผ่าน pano_changed
  • visible_changed เริ่มทำงานเมื่อการเปิดเผย ของ Street View เปลี่ยนไป โปรดทราบว่าเหตุการณ์นี้อาจเริ่มทำงานแบบไม่พร้อมกันหลังจากมีการเปลี่ยนแปลงรหัสพาโนรามาที่ระบุไว้ผ่าน pano_changed

โค้ดต่อไปนี้จะแสดงวิธีจัดการเหตุการณ์เหล่านี้เพื่อรวบรวมข้อมูลเกี่ยวกับ StreetViewPanorama ที่เกี่ยวข้อง

TypeScript

function initPano() {
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano") as HTMLElement,
    {
      position: { lat: 37.869, lng: -122.255 },
      pov: {
        heading: 270,
        pitch: 0,
      },
      visible: true,
    }
  );

  panorama.addListener("pano_changed", () => {
    const panoCell = document.getElementById("pano-cell") as HTMLElement;

    panoCell.innerHTML = panorama.getPano();
  });

  panorama.addListener("links_changed", () => {
    const linksTable = document.getElementById("links_table") as HTMLElement;

    while (linksTable.hasChildNodes()) {
      linksTable.removeChild(linksTable.lastChild as ChildNode);
    }

    const links = panorama.getLinks();

    for (const i in links) {
      const row = document.createElement("tr");

      linksTable.appendChild(row);

      const labelCell = document.createElement("td");

      labelCell.innerHTML = "<b>Link: " + i + "</b>";

      const valueCell = document.createElement("td");

      valueCell.innerHTML = links[i].description as string;
      linksTable.appendChild(labelCell);
      linksTable.appendChild(valueCell);
    }
  });

  panorama.addListener("position_changed", () => {
    const positionCell = document.getElementById(
      "position-cell"
    ) as HTMLElement;

    (positionCell.firstChild as HTMLElement).nodeValue =
      panorama.getPosition() + "";
  });

  panorama.addListener("pov_changed", () => {
    const headingCell = document.getElementById("heading-cell") as HTMLElement;
    const pitchCell = document.getElementById("pitch-cell") as HTMLElement;

    (headingCell.firstChild as HTMLElement).nodeValue =
      panorama.getPov().heading + "";
    (pitchCell.firstChild as HTMLElement).nodeValue =
      panorama.getPov().pitch + "";
  });
}

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

JavaScript

function initPano() {
  const panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano"),
    {
      position: { lat: 37.869, lng: -122.255 },
      pov: {
        heading: 270,
        pitch: 0,
      },
      visible: true,
    },
  );

  panorama.addListener("pano_changed", () => {
    const panoCell = document.getElementById("pano-cell");

    panoCell.innerHTML = panorama.getPano();
  });
  panorama.addListener("links_changed", () => {
    const linksTable = document.getElementById("links_table");

    while (linksTable.hasChildNodes()) {
      linksTable.removeChild(linksTable.lastChild);
    }

    const links = panorama.getLinks();

    for (const i in links) {
      const row = document.createElement("tr");

      linksTable.appendChild(row);

      const labelCell = document.createElement("td");

      labelCell.innerHTML = "<b>Link: " + i + "</b>";

      const valueCell = document.createElement("td");

      valueCell.innerHTML = links[i].description;
      linksTable.appendChild(labelCell);
      linksTable.appendChild(valueCell);
    }
  });
  panorama.addListener("position_changed", () => {
    const positionCell = document.getElementById("position-cell");

    positionCell.firstChild.nodeValue = panorama.getPosition() + "";
  });
  panorama.addListener("pov_changed", () => {
    const headingCell = document.getElementById("heading-cell");
    const pitchCell = document.getElementById("pitch-cell");

    headingCell.firstChild.nodeValue = panorama.getPov().heading + "";
    pitchCell.firstChild.nodeValue = panorama.getPov().pitch + "";
  });
}

window.initPano = initPano;

CSS

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

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

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

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

#floating-panel {
  width: 45%;
  height: 100%;
  float: right;
  text-align: left;
  overflow: auto;
  position: static;
  border: 0px solid #999;
}

HTML

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

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="pano"></div>
    <div id="floating-panel">
      <table>
        <tr>
          <td><b>Position</b></td>
          <td id="position-cell">&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>
ดูตัวอย่าง

ลองใช้ตัวอย่าง

ตัวควบคุม Street View

เมื่อแสดง StreetViewPanorama ตัวควบคุมแบบต่างๆ จะปรากฏในพาโนรามาโดยค่าเริ่มต้น คุณเปิดหรือปิดใช้การควบคุมเหล่านี้ได้โดยตั้งค่าช่องที่เหมาะสมภายใน StreetViewPanoramaOptions เป็น true หรือ false

  • panControl เป็นวิธีการหมุนพาโนรามา การควบคุมนี้จะปรากฏเป็นเข็มทิศรวมและการควบคุมการเลื่อนแบบมาตรฐานโดยค่าเริ่มต้น คุณเปลี่ยนตำแหน่งของตัวควบคุมได้โดยระบุ PanControlOptions ในช่อง panControlOptions
  • zoomControl เป็นวิธีการซูมภายในรูปภาพ ตัวควบคุมนี้จะปรากฏขึ้นโดยค่าเริ่มต้นใกล้กับด้านขวาล่างของพาโนรามา คุณแก้ไขลักษณะของตัวควบคุมได้โดยการระบุ ZoomControlOptions ในช่อง zoomControlOptions
  • addressControl จะแสดงข้อความวางซ้อนซึ่งระบุที่อยู่ของสถานที่ตั้งที่เกี่ยวข้อง และเสนอลิงก์สำหรับเปิดสถานที่นั้นใน Google Maps คุณแก้ไขลักษณะของตัวควบคุมได้โดยการระบุ StreetViewAddressControlOptions ในช่อง addressControlOptions
  • fullscreenControl มีตัวเลือกในการเปิด Street View ในโหมดเต็มหน้าจอ คุณแก้ไขลักษณะของตัวควบคุมได้โดยการระบุ FullscreenControlOptions ในช่อง fullscreenControlOptions
  • motionTrackingControl มีตัวเลือกในการเปิดหรือปิดใช้การติดตามการเคลื่อนไหวในอุปกรณ์เคลื่อนที่ การควบคุมนี้จะปรากฏในอุปกรณ์ที่รองรับเหตุการณ์การวางแนวอุปกรณ์เท่านั้น โดยค่าเริ่มต้น ตัวควบคุมจะปรากฏที่บริเวณด้านขวาล่างของพาโนรามา คุณเปลี่ยนตำแหน่งของตัวควบคุมได้โดยระบุ MotionTrackingControlOptions ดูข้อมูลเพิ่มเติมได้ที่ส่วนการติดตามการเคลื่อนไหว
  • linksControl มีลูกศรนำทางในรูปภาพเพื่อเดินทางไปยังรูปภาพพาโนรามาที่อยู่ติดกัน
  • ส่วนควบคุม "ปิด" ช่วยให้ผู้ใช้ปิดมุมมอง Street View ได้ คุณเปิดหรือปิดใช้การควบคุมปิดได้โดยการตั้งค่า enableCloseButton เป็น true หรือ false

ตัวอย่างต่อไปนี้เปลี่ยนแปลงตัวควบคุมที่แสดงภายใน Street View ที่เกี่ยวข้องและนำลิงก์ของมุมมองออก

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>
ดูตัวอย่าง

ลองใช้ตัวอย่าง

การเข้าถึงข้อมูล Street View โดยตรง

คุณอาจต้องการพิจารณาความพร้อมใช้งาน ของข้อมูล Street View โดยใช้โปรแกรม หรือแสดงข้อมูลเกี่ยวกับพาโนรามาบางอย่าง โดยไม่ต้องจัดการแผนที่/พาโนรามาโดยตรง คุณสามารถทำได้โดยใช้ออบเจ็กต์ StreetViewService ซึ่งมอบอินเทอร์เฟซสำหรับข้อมูลที่จัดเก็บไว้ในบริการ Street View ของ Google

คำขอบริการ Street View

การเข้าถึงบริการ Street View เป็นการทำงานแบบไม่พร้อมกัน เนื่องจาก Google Maps API ต้องเรียกไปยังเซิร์ฟเวอร์ภายนอก คุณจึงต้องผ่านเมธอด callback เพื่อดําเนินการเมื่อคําขอเสร็จสมบูรณ์ วิธีเรียกกลับนี้จะประมวลผลผลลัพธ์

คุณเริ่มส่งคำขอไปยัง StreetViewService โดยใช้ StreetViewPanoRequest หรือ StreetViewLocationRequest ได้

คำขอที่ใช้ StreetViewPanoRequest แสดงผลข้อมูลพาโนรามาที่ระบุรหัสอ้างอิงซึ่งระบุพาโนรามาได้อย่างไม่ซ้ำกัน โปรดทราบว่ารหัสอ้างอิงเหล่านี้จะมีความเสถียรตลอดอายุของภาพพาโนรามานั้น

คำขอที่ใช้ StreetViewLocationRequest จะค้นหาข้อมูลพาโนรามา ณ ตำแหน่งที่ระบุโดยใช้พารามิเตอร์ต่อไปนี้

  • location ระบุตำแหน่ง (ละติจูดและลองจิจูด) เพื่อค้นหาพาโนรามา
  • preference ตั้งค่ากำหนดว่าต้องการให้พบภาพพาโนรามาใน รัศมีหรือไม่ โดยเลือกอันที่ใกล้กับตำแหน่งที่ระบุมากที่สุดหรือจุดที่ดีที่สุดภายในรัศมี
  • radius กำหนดรัศมีโดยระบุเป็นเมตรซึ่งจะค้นหาพาโนรามา โดยมีศูนย์กลางอยู่ที่ละติจูดและลองจิจูดที่ระบุ ค่าเริ่มต้นจะเป็น 50 หากไม่ระบุ
  • source ระบุแหล่งที่มาของภาพพาโนรามาที่จะค้นหา ค่าที่ใช้ได้มีดังนี้
    • default ใช้แหล่งที่มาเริ่มต้นสำหรับ Street View โดยการค้นหาไม่ได้จำกัดอยู่เพียงบางแหล่งที่มา
    • outdoor จำกัดการค้นหาเป็นคอลเล็กชันกลางแจ้ง โปรดทราบว่าตำแหน่งที่ระบุอาจไม่มีภาพพาโนรามากลางแจ้ง

การตอบกลับบริการ Street View

ฟังก์ชัน getPanorama() ต้องใช้ฟังก์ชัน callback เพื่อทํางานเมื่อดึงข้อมูลผลลัพธ์จากบริการ Street View ฟังก์ชันเรียกกลับนี้จะแสดงชุดข้อมูลพาโนรามาภายในออบเจ็กต์ StreetViewPanoramaData และรหัส StreetViewStatus ที่แสดงถึงสถานะของคำขอตามลำดับดังกล่าว

ข้อมูลจำเพาะเกี่ยวกับวัตถุ StreetViewPanoramaData มีข้อมูลเมตาเกี่ยวกับพาโนรามาของ Street View ตามรูปแบบต่อไปนี้

{
  "location": {
    "latLng": LatLng,
    "description": string,
    "pano": string
  },
  "copyright": string,
  "links": [{
      "heading": number,
      "description": string,
      "pano": string,
      "roadColor": string,
      "roadOpacity": number
    }],
  "tiles": {
    "worldSize": Size,
    "tileSize": Size,
    "centerHeading": number
  }
}

โปรดทราบว่าออบเจ็กต์ข้อมูลนี้ไม่ใช่ออบเจ็กต์ StreetViewPanorama หากต้องการสร้างออบเจ็กต์ Street View โดยใช้ข้อมูลนี้ คุณจะต้องสร้าง StreetViewPanorama แล้วเรียกใช้ setPano() โดยส่งรหัสตามที่ระบุไว้ในช่อง location.pano ที่แสดงผล

โค้ด status อาจแสดงค่าใดค่าหนึ่งต่อไปนี้

  • OK บ่งบอกว่าบริการพบพาโนรามาที่ตรงกัน
  • ZERO_RESULTS บ่งบอกว่าบริการไม่พบภาพพาโนรามาที่ตรงกันกับเกณฑ์ที่ผ่าน
  • UNKNOWN_ERROR บ่งบอกว่าไม่สามารถดำเนินการตามคำขอ Street View ได้ แม้ว่าจะไม่ทราบสาเหตุที่แน่ชัด

โค้ดต่อไปนี้จะสร้าง StreetViewService ที่ตอบสนองต่อการคลิกของผู้ใช้บนแผนที่ด้วยการสร้างเครื่องหมายซึ่งเมื่อคลิกจะแสดง StreetViewPanorama ของตำแหน่งนั้น โค้ดใช้เนื้อหาของ StreetViewPanoramaData ที่แสดงผลจากบริการ

TypeScript

/*
 * Click the map to set a new location for the Street View camera.
 */

let map: google.maps.Map;

let panorama: google.maps.StreetViewPanorama;

function initMap(): void {
  const berkeley = { lat: 37.869085, lng: -122.254775 };
  const sv = new google.maps.StreetViewService();

  panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano") as HTMLElement
  );

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

  // Set the initial Street View camera to the center of the map
  sv.getPanorama({ location: berkeley, radius: 50 }).then(processSVData);

  // Look for a nearby Street View panorama when the map is clicked.
  // getPanorama will return the nearest pano when the given
  // radius is 50 meters or less.
  map.addListener("click", (event) => {
    sv.getPanorama({ location: event.latLng, radius: 50 })
      .then(processSVData)
      .catch((e) =>
        console.error("Street View data not found for this location.")
      );
  });
}

function processSVData({ data }: google.maps.StreetViewResponse) {
  const location = data.location!;

  const marker = new google.maps.Marker({
    position: location.latLng,
    map,
    title: location.description,
  });

  panorama.setPano(location.pano as string);
  panorama.setPov({
    heading: 270,
    pitch: 0,
  });
  panorama.setVisible(true);

  marker.addListener("click", () => {
    const markerPanoID = location.pano;

    // Set the Pano to use the passed panoID.
    panorama.setPano(markerPanoID as string);
    panorama.setPov({
      heading: 270,
      pitch: 0,
    });
    panorama.setVisible(true);
  });
}

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

JavaScript

/*
 * Click the map to set a new location for the Street View camera.
 */
let map;
let panorama;

function initMap() {
  const berkeley = { lat: 37.869085, lng: -122.254775 };
  const sv = new google.maps.StreetViewService();

  panorama = new google.maps.StreetViewPanorama(
    document.getElementById("pano"),
  );
  // Set up the map.
  map = new google.maps.Map(document.getElementById("map"), {
    center: berkeley,
    zoom: 16,
    streetViewControl: false,
  });
  // Set the initial Street View camera to the center of the map
  sv.getPanorama({ location: berkeley, radius: 50 }).then(processSVData);
  // Look for a nearby Street View panorama when the map is clicked.
  // getPanorama will return the nearest pano when the given
  // radius is 50 meters or less.
  map.addListener("click", (event) => {
    sv.getPanorama({ location: event.latLng, radius: 50 })
      .then(processSVData)
      .catch((e) =>
        console.error("Street View data not found for this location."),
      );
  });
}

function processSVData({ data }) {
  const location = data.location;
  const marker = new google.maps.Marker({
    position: location.latLng,
    map,
    title: location.description,
  });

  panorama.setPano(location.pano);
  panorama.setPov({
    heading: 270,
    pitch: 0,
  });
  panorama.setVisible(true);
  marker.addListener("click", () => {
    const markerPanoID = location.pano;

    // Set the Pano to use the passed panoID.
    panorama.setPano(markerPanoID);
    panorama.setPov({
      heading: 270,
      pitch: 0,
    });
    panorama.setVisible(true);
  });
}

window.initMap = initMap;

CSS

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

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

HTML

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

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

    <!-- 
      The `defer` attribute causes the 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>
ดูตัวอย่าง

ลองใช้ตัวอย่าง

การให้ภาพพาโนรามา Street View ที่กำหนดเอง

Maps JavaScript API รองรับการแสดงพาโนรามาที่กำหนดเองภายในออบเจ็กต์ StreetViewPanorama เมื่อใช้ภาพพาโนรามาที่กำหนดเอง คุณสามารถแสดงภายในอาคาร วิวจากสถานที่อันสวยงาม หรือสิ่งต่างๆ จากจินตนาการของคุณ คุณยัง ลิงก์ภาพพาโนรามาที่กำหนดเองเหล่านี้กับภาพพาโนรามา Street View ที่ Google มีอยู่ได้อีกด้วย

การตั้งค่าชุดภาพพาโนรามาที่กำหนดเองเกี่ยวข้องกับขั้นตอนต่อไปนี้

  • สร้างภาพพาโนรามาพื้นฐานสำหรับภาพพาโนรามาที่กำหนดเองแต่ละภาพ รูปภาพฐานนี้ควรเป็นรูปภาพที่มีความละเอียดสูงสุดที่คุณต้องการใช้ซูม
  • (ไม่บังคับ แต่แนะนำ) สร้างชุดของชิ้นส่วนพาโนรามาที่ระดับการซูมต่างๆ จากรูปภาพพื้นฐาน
  • สร้างลิงก์ระหว่างภาพพาโนรามาที่กำหนดเองของคุณ
  • (ไม่บังคับ) กำหนดภาพพาโนรามา "เข้า" ภายในภาพ Street View ที่มีอยู่ของ Google และปรับแต่งลิงก์ไปยัง/จากชุดที่กำหนดเองเป็นชุดมาตรฐาน
  • กำหนดข้อมูลเมตาสำหรับรูปภาพพาโนรามาแต่ละภาพภายในออบเจ็กต์ StreetViewPanoramaData
  • นำเมธอดมาใช้กำหนดข้อมูลและรูปภาพพาโนรามาที่กำหนดเอง และกำหนดให้วิธีการนั้นเป็นเครื่องจัดการที่กำหนดเองภายในออบเจ็กต์ StreetViewPanorama

ส่วนต่อไปนี้จะอธิบายกระบวนการนี้

การสร้างภาพพาโนรามาที่กำหนดเอง

ภาพพาโนรามาของ Street View แต่ละภาพคือรูปภาพหรือชุดรูปภาพที่แสดงมุมมอง 360 องศาจากสถานที่เดียว วัตถุ StreetViewPanorama ใช้รูปภาพที่สอดคล้องกับการฉายภาพทรงกลม (Plate Carrée) การฉายภาพดังกล่าวจะมีมุมมองแนวนอน 360 องศา (ภาพเต็มรอบ) และแนวตั้ง 180 องศา (จากแนวตรงไปด้านบน) ช่องของมุมมองเหล่านี้จะทำให้ได้รูปภาพที่มีสัดส่วนภาพ 2:1 ภาพพาโนรามาที่ล้อมรอบทั้งภาพจะแสดงอยู่ด้านล่าง

วิวถนนในเมืองแบบพาโนรามา

โดยทั่วไปรูปภาพพาโนรามาได้มาจากการถ่ายรูปหลายๆ รูปจากตำแหน่งเดียวแล้วต่อรูปภาพเข้าด้วยกันโดยใช้ซอฟต์แวร์พาโนรามา (ดูข้อมูลเพิ่มเติมได้ที่ การเปรียบเทียบแอปพลิเคชันสำหรับการเย็บรูปภาพของ Wikipedia) รูปภาพดังกล่าวควรใช้โลคัส "กล้อง" เดียวที่ใช้ถ่ายพาโนรามาแต่ละภาพ จากนั้น ภาพพาโนรามา 360 องศาที่ได้จะสามารถกำหนดการฉายภาพในทรงกลมที่มีภาพตัดกับพื้นผิว 2 มิติของทรงกลม

วงกลมพร้อมวิวพาโนรามาของถนนบนพื้นผิว

ถือว่าภาพพาโนรามาเป็นการฉายภาพบนทรงกลมด้วยระบบพิกัดแบบเส้นตรง จะมีข้อดีเมื่อแบ่งรูปภาพออกเป็นไทล์เส้นตรง และแสดงรูปภาพตามพิกัดชิ้นส่วน ที่คำนวณไว้

การสร้างภาพพาโนรามาที่กำหนดเอง

Street View ยังรองรับรายละเอียดของรูปภาพในระดับต่างๆ โดยใช้ตัวควบคุมการซูม ซึ่งให้คุณซูมเข้าและออกจากมุมมองเริ่มต้นได้ โดยทั่วไป Street View มีความละเอียดของการซูม 5 ระดับสำหรับภาพพาโนรามา หากคุณใช้รูปภาพพาโนรามาภาพเดียวเพื่อแสดงระดับการซูมทุกระดับ รูปภาพดังกล่าวอาจค่อนข้างใหญ่และทำให้แอปพลิเคชันทำงานช้าลงมาก หรือมีความละเอียดต่ำเช่นนั้นเมื่อซูมสูงขึ้นจนคุณจะแสดงรูปภาพที่มีภาพพิกเซลไม่ดี อย่างไรก็ตาม โชคดีที่เราใช้รูปแบบการออกแบบที่คล้ายกันซึ่งใช้เพื่อแสดง ชิ้นส่วนแผนที่ของ Google ที่ระดับการซูมต่างๆ เพื่อให้ ภาพความละเอียดที่เหมาะสมสำหรับภาพพาโนรามาในแต่ละระดับการซูม

เมื่อ StreetViewPanorama โหลดเป็นครั้งแรก โดยค่าเริ่มต้นจะแสดงภาพที่ประกอบด้วย 25% (90 องศาของแนวโค้ง) ของความกว้างในแนวนอนของพาโนรามาที่ระดับการซูม 1 มุมมองนี้สอดคล้องกับขอบเขตการมองเห็นตามปกติของมนุษย์อย่างคร่าวๆ โดยพื้นฐานแล้วการซูม "ออก" จากมุมมองเริ่มต้นนี้จะให้เส้นโค้งที่กว้างกว่า ส่วนการซูมเข้าจะจํากัดขอบเขตการแสดงผลให้มีเส้นโค้งที่เล็กลง StreetViewPanorama จะคำนวณขอบเขตการมองเห็นที่เหมาะสมสำหรับระดับการซูมที่เลือกโดยอัตโนมัติ จากนั้นเลือกภาพที่เหมาะสมที่สุดสำหรับความละเอียดดังกล่าวด้วยการเลือกชุดชิ้นส่วนที่ตรงกับขนาดขอบเขตมุมมองแนวนอนอย่างคร่าวๆ ช่องต่อไปนี้ของมุมมองแมปไปยังระดับการซูมของ Street View

ระดับการซูม Street View ฟิลด์ของมุมมอง (องศา)
0 180
1 (ค่าเริ่มต้น) 90
2 45
3 22.5
4 11.25

โปรดทราบว่าขนาดของรูปภาพที่แสดงภายใน Street View จะขึ้นอยู่กับขนาดหน้าจอ (ความกว้าง) ของคอนเทนเนอร์ Street View ทั้งหมด หากคอนเทนเนอร์กว้าง บริการจะยังคงมีขอบเขตการมองเห็นเหมือนกันสำหรับระดับการซูมทุกระดับ แต่ก็อาจเลือกชิ้นส่วนที่เหมาะกับความละเอียดดังกล่าวมากกว่าแทน

เนื่องจากภาพพาโนรามาแต่ละภาพประกอบด้วยการฉายภาพทรงกลม การสร้างภาพการ์ดพาโนรามาจึงค่อนข้างง่าย เนื่องจากเส้นโครงให้ภาพที่มีอัตราส่วน 2:1 ชิ้นส่วนภาพที่มีอัตราส่วน 2:1 จึงใช้งานได้ง่ายขึ้น แต่ภาพชิ้นส่วนสี่เหลี่ยมจัตุรัสอาจให้ประสิทธิภาพที่ดีกว่าในแผนที่สี่เหลี่ยมจัตุรัส (เนื่องจากพื้นที่การมองเห็นจะเป็นสี่เหลี่ยมจัตุรัส)

สำหรับชิ้นส่วน 2:1 ภาพ 1 ภาพที่ครอบคลุมภาพพาโนรามาทั้งภาพจะแสดงภาพพาโนรามา "โลก" (ภาพพื้นฐาน) ที่ระดับการซูม 0 โดยแต่ละระดับการซูมจะมีการ์ดzoomLevel 4 ภาพ (เช่น เมื่อซูมระดับ 2 ภาพพาโนรามาทั้งหมดประกอบด้วยการ์ด 16 แผ่น) หมายเหตุ: ระดับการซูมใน Street View ไม่ตรงกับระดับการซูมโดยตรงตามที่ระบุโดยใช้ ตัวควบคุม Street View แต่ระดับการซูมของการควบคุม Street View จะเลือกฟิลด์มุมมอง (FoV) ซึ่งเป็น เพื่อเลือกชิ้นส่วนที่เหมาะสมแทน

วิวถนนในเมืองแบบพาโนรามาที่แบ่งเป็นกระเบื้อง

โดยทั่วไปคุณจะต้องตั้งชื่อชิ้นส่วนรูปภาพเพื่อให้เลือกแบบเป็นโปรแกรมได้ คุณสามารถดูรูปแบบการตั้งชื่อดังกล่าวได้ที่ด้านล่างในการจัดการคำขอพาโนรามาที่กำหนดเอง

การจัดการคำขอภาพพาโนรามาที่กำหนดเอง

หากต้องการใช้พาโนรามาที่กำหนดเอง ให้เรียก StreetViewPanorama.registerPanoProvider() โดยระบุชื่อวิธีการของผู้ให้บริการพาโนรามาที่กำหนดเอง เมธอดของผู้ให้บริการพาโนรามาต้องส่งคืนออบเจ็กต์ StreetViewPanoramaData และมีลายเซ็นต่อไปนี้

Function(pano):StreetViewPanoramaData

StreetViewPanoramaData เป็นออบเจ็กต์ในรูปแบบต่อไปนี้

{
  copyright: string,
  location: {
    description: string,
    latLng: google.maps.LatLng,
    pano: string
  },
  tiles: {
    tileSize: google.maps.Size,
    worldSize: google.maps.Size,
    heading: number,
    getTileUrl: Function
  },
  links: [
    description: string,
    heading: number,
    pano: string,
    roadColor: string,
    roadOpacity: number
  ]
}

แสดงภาพพาโนรามาที่กำหนดเองดังนี้

  • ตั้งค่าพร็อพเพอร์ตี้ StreetViewPanoramaOptions.pano เป็นค่าที่กำหนดเอง
  • เรียก StreetViewPanorama.registerPanoProvider() เพื่อขอฟังก์ชันของผู้ให้บริการพาโนรามาที่กำหนดเอง
  • ใช้ฟังก์ชันของผู้ให้บริการพาโนรามาที่กำหนดเองเพื่อจัดการค่า pano ที่ระบุ
  • สร้างออบเจ็กต์ StreetViewPanoramaData
  • ตั้งค่าพร็อพเพอร์ตี้ StreetViewTileData.getTileUrl เป็นชื่อฟังก์ชันของผู้ให้บริการไทล์ที่กำหนดเองที่คุณระบุ เช่น getCustomPanoramaTileUrl
  • ใช้ฟังก์ชันของผู้ให้บริการไทล์ที่กำหนดเองดังที่แสดงในตัวอย่างด้านล่าง
  • ส่งคืนออบเจ็กต์ StreetViewPanoramaData

หมายเหตุ: อย่าตั้งค่า position ใน StreetViewPanorama โดยตรงเมื่อต้องการแสดงภาพพาโนรามาที่กำหนดเอง เช่น ตำแหน่งจะทำให้บริการ Street View ขอภาพ Street View เริ่มต้นที่อยู่ใกล้กับตำแหน่งนั้น ให้ตั้งค่าตำแหน่งนี้ภายในช่อง location.latLng ของออบเจ็กต์ StreetViewPanoramaData ที่กำหนดเองแทน

ตัวอย่างต่อไปนี้แสดงพาโนรามาที่กำหนดเองของสำนักงาน Google ซิดนีย์ โปรดทราบว่าตัวอย่างนี้ไม่ได้ใช้แผนที่หรือภาพ Street View เริ่มต้น

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>
ดูตัวอย่าง

ลองใช้ตัวอย่าง

ผู้ให้บริการพาโนรามาที่กำหนดเองจะแสดงภาพไทล์ที่เหมาะสมตามรหัสพาโนรามาที่ส่ง ระดับการซูม และพิกัดชิ้นส่วนภาพพาโนรามา เนื่องจากการเลือกรูปภาพขึ้นอยู่กับค่าที่ส่งเหล่านี้ จึงควรตั้งชื่อรูปภาพที่สามารถเลือกทางโปรแกรมได้ โดยใช้ค่าที่ส่ง เช่น pano_zoom_tileX_tileY.png

ตัวอย่างต่อไปนี้เพิ่มลูกศรอีก 1 รูปลงในรูปภาพนอกเหนือจากลูกศรนำทางเริ่มต้นของ Street View ที่ชี้ไปยัง Google ซิดนีย์และลิงก์ไปยังภาพที่กำหนดเอง

TypeScript

let panorama: google.maps.StreetViewPanorama;

// StreetViewPanoramaData of a panorama just outside the Google Sydney office.
let outsideGoogle: google.maps.StreetViewPanoramaData;

// StreetViewPanoramaData for a custom panorama: the Google Sydney reception.
function getReceptionPanoramaData(): google.maps.StreetViewPanoramaData {
  return {
    location: {
      pano: "reception", // The ID for this custom panorama.
      description: "Google Sydney - Reception",
      latLng: new google.maps.LatLng(-33.86684, 151.19583),
    },
    links: [
      {
        heading: 195,
        description: "Exit",
        pano: (outsideGoogle.location as google.maps.StreetViewLocation).pano,
      },
    ],
    copyright: "Imagery (c) 2010 Google",
    tiles: {
      tileSize: new google.maps.Size(1024, 512),
      worldSize: new google.maps.Size(2048, 1024),
      centerHeading: 105,
      getTileUrl: function (
        pano: string,
        zoom: number,
        tileX: number,
        tileY: number
      ): string {
        return (
          "https://developers.google.com/maps/documentation/javascript/examples/full/images/" +
          "panoReception1024-" +
          zoom +
          "-" +
          tileX +
          "-" +
          tileY +
          ".jpg"
        );
      },
    },
  };
}

function initPanorama() {
  panorama = new google.maps.StreetViewPanorama(
    document.getElementById("street-view") as HTMLElement,
    { pano: (outsideGoogle.location as google.maps.StreetViewLocation).pano }
  );
  // Register a provider for the custom panorama.
  panorama.registerPanoProvider(
    (pano: string): google.maps.StreetViewPanoramaData => {
      if (pano === "reception") {
        return getReceptionPanoramaData();
      }
      // @ts-ignore TODO fix typings
      return null;
    }
  );

  // Add a link to our custom panorama from outside the Google Sydney office.
  panorama.addListener("links_changed", () => {
    if (
      panorama.getPano() ===
      (outsideGoogle.location as google.maps.StreetViewLocation).pano
    ) {
      panorama.getLinks().push({
        description: "Google Sydney",
        heading: 25,
        pano: "reception",
      });
    }
  });
}

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

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

JavaScript

let panorama;
// StreetViewPanoramaData of a panorama just outside the Google Sydney office.
let outsideGoogle;

// StreetViewPanoramaData for a custom panorama: the Google Sydney reception.
function getReceptionPanoramaData() {
  return {
    location: {
      pano: "reception",
      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>
ดูตัวอย่าง

ลองใช้ตัวอย่าง