שירות Street View

סקירה

בחירת פלטפורמה: Android iOS JavaScript

Google Street View מספק תצוגות פנורמיות של 360 מעלות מכבישים ייעודיים ברחבי אזור הכיסוי. כיסוי ה-API של Street View זהה לזה של אפליקציית מפות Google (https://maps.google.com/). רשימת הערים שנתמכות כרגע ב-Street View זמינה באתר מפות Google.

למטה מוצגת דוגמה של תמונת Street View.


JavaScript API של מפות Google מספק שירות Street View שמאפשר לקבל ולבצע מניפולציות על התמונות שמשמשות ב-Street View במפות Google. שירות Street View הזה נתמך מתוך הדפדפן.

שימוש במפה ב-Street View

אפשר להשתמש ב-Street View בתוך רכיב DOM עצמאי, אבל הוא הכי שימושי כשמציינים מיקום במפה. כברירת מחדל, Street View מופעל במפה, ופקד של האטב-איש של Street View משולב בפקדי הניווט (מרחק התצוגה והזזה). אפשר להסתיר את הפקד הזה בMapOptions של המפה על ידי הגדרת הערך false של streetViewControl. אפשר גם לשנות את מיקום ברירת המחדל של הפקד ב-Street View על ידי הגדרת המאפיין streetViewControlOptions.position של Map לערך ControlPosition חדש.

הפקד של האטב-איש של Street View מאפשר להציג תמונות פנורמיות של Street View ישירות בתוך המפה. כשהמשתמש לוחץ ומחזיק באטב-איש, המפה מתעדכנת ומוצגים בה קווי מתאר כחולים סביב רחובות שתומכים ב-Street View. כך חוויית המשתמש דומה לזו של אפליקציית מפות Google.

כשמשתמש משחרר את האטב-איש ברחוב, המפה מתעדכנת ומציגה תמונת פנורמית ב-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 בתוך ה-constructor של StreetViewPanorama. לתצוגה אופטימלית של תמונות, מומלץ גודל מינימלי של 200 פיקסלים על 200 פיקסלים.

הערה: אמנם הפונקציונליות של Street View מיועדת לשימוש בשילוב עם מפה, אבל לא חייבים להשתמש בה. אפשר להשתמש באובייקט Street View נפרד בלי מפה.

מיקומים ונקודת מבט של Street View (POV)

ה-constructor של StreetViewPanorama מאפשר גם להגדיר את המיקום ואת נקודת המבט של Street View באמצעות הפרמטר StreetViewOptions. אחרי עבודות הבנייה, אפשר לקרוא לאובייקט setPosition() ו-setPov() כדי לשנות את המיקום ואת נקודת המבט שלו.

המיקום של Street View מגדיר את מיקום המיקוד של המצלמה עבור תמונה, אבל הוא לא מגדיר את כיוון המצלמה עבור אותה תמונה. לשם כך, האובייקט StreetViewPov מגדיר שני מאפיינים:

  • heading (ברירת המחדל 0) מגדיר את זווית הסיבוב סביב מיקום המצלמה במעלות ביחס לצפון האמיתי. כותרות נמדדות בכיוון השעון (90 מעלות הוא הערך האמיתי של מזרח).
  • pitch (ברירת המחדל 0) מגדירה את השונות בזווית 'למעלה' או 'למטה' מגובה ברירת המחדל הראשוני של המצלמה, שהוא בדרך כלל (אבל לא תמיד) שטוח. (לדוגמה, סביר להניח שתמונה שצולמה על גבעה תציג גובה-רוחב שאינו אופקי כברירת מחדל.) זוויות הפנייה נמדדות באמצעות ערכים חיוביים כלפי מעלה (עד +90 מעלות ישר למעלה ואורתוגונלית לגובה ברירת המחדל) ושל ערכים שליליים כלפי מטה (עד 90 מעלות ישר למטה ואורתוגונלי לגובה ברירת המחדל).

פעמים רבות משתמשים באובייקט StreetViewPov כדי לקבוע את נקודת המבט של מצלמת Street View. אפשר גם לקבוע את נקודת המבט של הצלם – בדרך כלל לכיוון המכונית או התלת-אופן – באמצעות השיטה StreetViewPanorama.getPhotographerPov().

הקוד הבא מציג מפה של בוסטון עם נוף ראשוני של פארק פנוויי. בחירת האטב-איש וגרירתו למיקום נתמך במפה ישנו את הפנורמה של 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>

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

    <!-- 
      The `defer` attribute causes the script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initialize&v=weekly"
      defer
    ></script>
  </body>
</html>
להצגת דוגמה

כדאי לנסות דוגמה

מעקב תנועה במכשירים ניידים

במכשירים שתומכים באירועי כיוון של המכשיר, ה-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 של הבנייה שלך, היא מבטלת את ברירת המחדל של הפנורמה.

בדוגמה הבאה מוצגים סמנים לציון מיקומים שונים בסביבת אסטור פלייס, ניו יורק. מעבירים את התצוגה ל-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);

  const cafeIcon = document.createElement("img");
  cafeIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/cafe_icon.svg";

  const dollarIcon = document.createElement("img");
  dollarIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bank_icon.svg";

  const busIcon = document.createElement("img");
  busIcon.src = "https://developers.google.com/maps/documentation/javascript/examples/full/images/bus_icon.svg";


  // Set up the markers on the map
  const cafeMarker = new google.maps.Marker({
    position: { lat: 40.730031, lng: -73.991428 },
    map,
    title: "Cafe",
    icon: cafeIcon.src,
  });

  const bankMarker = new google.maps.Marker({
    position: { lat: 40.729681, lng: -73.991138 },
    map,
    title: "Bank",
    icon: dollarIcon.src,
  });

  const busMarker = new google.maps.Marker({
    position: { lat: 40.729559, lng: -73.990741 },
    map,
    title: "Bus Stop",
    icon: busIcon.src,
  });

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

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

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

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

JavaScript

let panorama;

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

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

  const cafeIcon = document.createElement("img");

  cafeIcon.src =
    "https://developers.google.com/maps/documentation/javascript/examples/full/images/cafe_icon.svg";

  const dollarIcon = document.createElement("img");

  dollarIcon.src =
    "https://developers.google.com/maps/documentation/javascript/examples/full/images/bank_icon.svg";

  const busIcon = document.createElement("img");

  busIcon.src =
    "https://developers.google.com/maps/documentation/javascript/examples/full/images/bus_icon.svg";

  // Set up the markers on the map
  const cafeMarker = new google.maps.Marker({
    position: { lat: 40.730031, lng: -73.991428 },
    map,
    title: "Cafe",
    icon: cafeIcon.src,
  });
  const bankMarker = new google.maps.Marker({
    position: { lat: 40.729681, lng: -73.991138 },
    map,
    title: "Bank",
    icon: dollarIcon.src,
  });
  const busMarker = new google.maps.Marker({
    position: { lat: 40.729559, lng: -73.990741 },
    map,
    title: "Bus Stop",
    icon: busIcon.src,
  });

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

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

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

window.initMap = initMap;

CSS

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

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

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

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

HTML

<html>
  <head>
    <title>Overlays Within Street View</title>

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

    <!-- 
      The `defer` attribute causes the script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&libraries=marker&v=weekly"
      defer
    ></script>
  </body>
</html>
להצגת דוגמה

כדאי לנסות דוגמה

אירועי 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>

    <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 script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
להצגת דוגמה

כדאי לנסות דוגמה

פקדים ב-Street View

כשמציגים StreetViewPanorama, מגוון פקדים מופיעים בפנורמה כברירת מחדל. אפשר להפעיל או להשבית את אמצעי הבקרה האלה על ידי הגדרת השדות המתאימים ב-StreetViewPanoramaOptions לערך true או false:

  • panControl מאפשר לסובב את הפנורמה. אמצעי הבקרה הזה מופיע כברירת מחדל כפקד משולב רגיל של מצפן והזזה. כדי לשנות את המיקום של אמצעי הבקרה, אפשר להוסיף את PanControlOptions בשדה panControlOptions.
  • zoomControl מאפשר לשנות את מרחק התצוגה בתוך התמונה. אמצעי הבקרה הזה מופיע כברירת מחדל ליד הפינה השמאלית התחתונה של הפנורמה. כדי לשנות את המראה של אמצעי הבקרה, אפשר להוסיף את ZoomControlOptions בשדה zoomControlOptions.
  • addressControl מספק שכבת-על של טקסט שמציינת את הכתובת של המיקום המשויך ומציע קישור לפתיחת המיקום במפות Google. כדי לשנות את המראה של אמצעי הבקרה, אפשר להוסיף את 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>

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

    <!-- 
      The `defer` attribute causes the script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
להצגת דוגמה

כדאי לנסות דוגמה

גישה ישירה לנתוני Street View

ייתכן שתרצו לקבוע באופן פרוגרמטי את הזמינות של נתוני Street View, או להציג מידע על תמונות פנורמיות מסוימות, בלי שתצטרכו להפעיל מניפולציה ישירה של המפה או הפנורמה. אפשר לעשות זאת באמצעות האובייקט StreetViewService, שמספק ממשק לנתונים שמאוחסנים בשירות Street View של Google.

בקשות שירות של Street View

הגישה לשירות Street View היא אסינכרונית, כי ה-API של מפות Google צריך לבצע קריאה לשרת חיצוני. לכן תצטרכו להעביר שיטת קריאה חוזרת שתבוצע בסיום הבקשה. שיטת הקריאה החוזרת הזו מעבדת את התוצאה.

אפשר לשלוח בקשות אל 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>

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

    <!-- 
      The `defer` attribute causes the script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>
להצגת דוגמה

כדאי לנסות דוגמה

יצירת תמונות פנורמיות ב-Street View בהתאמה אישית

API של JavaScript במפות Google תומך בתצוגה של תמונות פנורמיות בהתאמה אישית בתוך האובייקט StreetViewPanorama. באמצעות תמונות פנורמיות מותאמות אישית, אפשר להציג את פנים המבנים, נופים ממקומות ציוריים או כל דבר אחר מהדמיון שלך. אפשר אפילו לקשר את התמונות הפנורמיות המותאמות אישית האלה לתמונות הפנורמה הקיימות של Google ב-Street View.

כדי להגדיר קבוצה של תמונות פנורמה מותאמות אישית, יש לבצע את השלבים הבאים:

  • יצירת תמונה פנורמית בסיסית לכל פנורמה מותאמת אישית. תמונת הבסיס צריכה להיות ברזולוציה הגבוהה ביותר שבה רוצים להציג תמונות עם זום.
  • (אופציונלי, אבל מומלץ) יוצרים קבוצה של משבצות פנורמיות ברמות זום שונות מהתמונה הבסיסית.
  • יצירת קישורים בין תמונות פנורמיות בהתאמה אישית.
  • (אופציונלי) יש לציין תמונות פנורמיות מסוג 'רשומה' בתמונות Street View הקיימות של Google, ולהתאים אישית קישורים לקבוצה המותאמת אישית או לסטנדרט הרגיל שלה.
  • הגדרת מטא-נתונים לכל תמונה פנורמית באובייקט StreetViewPanoramaData.
  • תטמיעו שיטה שקובעת את התמונות והנתונים של הפנורמה בהתאמה אישית, ומגדירה את השיטה הזו כ-handler המותאם אישית בתוך האובייקט StreetViewPanorama.

הקטעים הבאים מסבירים את התהליך הזה.

יצירת צילומים פנורמיים מותאמים אישית

כל תמונה פנורמית ב-Street View היא תמונה או קבוצת תמונות שמציעות תצוגה מלאה של 360 מעלות ממיקום אחד. האובייקט StreetViewPanorama משתמש בתמונות שתואמות להיטל מלבבני (Plate Carrée). היטל כזה מכיל תצוגה אופקית של 360 מעלות (התצוגה המקיפה מלאה) ו-180 מעלות של תצוגה אנכית (מהישר למעלה עד למטה). בשדות התצוגה האלה נוצרת תמונה ביחס גובה-רוחב של 2:1. למטה מוצגת תמונה פנורמית מלאה.

נוף פנורמי של רחוב עירוני

בדרך כלל, תמונות פנורמה מתקבלות על ידי צילום מספר תמונות ממיקום אחד וקיבל אותן יחד באמצעות תוכנת פנורמה. (למידע נוסף, ראו השוואה בין אפליקציות לצילום תמונות בוויקיפדיה). תמונות כאלה צריכות להיות במיקום אחד של "מצלמה", שממנו צולמה כל אחת מהתמונות הפנורמיות. לאחר מכן, תמונת הפנורמה ב-360 מעלות שמתקבלת יכולה להגדיר היטל על כדור הארץ שהתמונה עטופה על פני השטח הדו-ממדיים של הכדור.

תמונה פנורמית ב-360° עם נוף פנורמי של רחוב על פני השטח

התייחסות לפנורמה כהיטל על כדור עם מערכת קואורדינטות ישר

יצירת אריחי פנורמה מותאמים אישית

ב-Street View יש גם תמיכה ברמות שונות של פרטי תמונה באמצעות בקרת זום, שמאפשרת להגדיל או להקטין את התצוגה מתצוגת ברירת המחדל. באופן כללי, ב-Street View יש חמש רמות של רזולוציית זום לכל תמונה פנורמית ב-360°. אם מסתמכים על תמונה פנורמית אחת כדי להציג את כל רמות הזום, התמונה הזו תהיה בהכרח גדולה למדי ותגרום להאטת האפליקציה באופן משמעותי, או שהרזולוציה שלה תהיה כל כך נמוכה ברמות זום גבוהות יותר, עד שהתמונה תהיה מפוקסלת בצורה גרועה. עם זאת, למרבה המזל, אנחנו יכולים להשתמש בתבנית עיצוב דומה שמשמשת להצגת משבצות המפה של 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, תמונה אחת שמקיפה את כל הפנורמה מייצגת את כל "העולם" הפנורמית (תמונת הבסיס) ברמת זום 0, וכל רמת זום הולכת וגדלה מציעה 4 משבצות zoomLevel. (למשל, ברמת זום 2, כל הפנורמה מורכבת מ-16 משבצות.) הערה: רמות הזום ב-Street View לא תואמות ישירות לרמות מרחק התצוגה שסופקו באמצעות הפקד של Street View. במקום זאת, רמות הזום של הפקד ב-Street View בוחרות שדה תצוגה (FoV), שממנו נבחרים המשבצות המתאימות.

נוף פנורמי של רחוב עירוני שמחולק לאריחים

באופן כללי, כדאי לתת שם למשבצות התמונות כדי שיהיה אפשר לבחור אותן באופן פרוגרמטי. סכמת שמות כזו מתוארת בהמשך בקטע טיפול בבקשות פנורמה מותאמות אישית.

טיפול בבקשות פנורמה מותאמת אישית

כדי להשתמש בפנורמה מותאמת אישית, צריך לקרוא לפונקציה StreetViewPanorama.registerPanoProvider() ולציין את שם ה-method של הספק של תמונת הפנורמה המותאמת אישית. ה-method של ספק הפנורמה חייבת להחזיר אובייקט 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>

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

    <!-- 
      The `defer` attribute causes the script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initPano&v=weekly"
      defer
    ></script>
  </body>
</html>
להצגת דוגמה

כדאי לנסות דוגמה

ספק הפנורמה המותאם אישית מחזיר את המשבצת המתאימה בהינתן מזהה הפנורמה, רמת הזום והקואורדינטות של משבצת הפנורמה שהתקבלו. בחירת התמונות תלויה בערכים שמועברים, ולכן כדאי לתת שמות לתמונות שאפשר לבחור באופן פרוגרמטי על סמך הערכים שמועברים, למשל pano_zoom_tileX_tileY.png.

הדוגמה הבאה מוסיפה חץ נוסף לתמונה, בנוסף לחיצי הניווט שמוגדרים כברירת מחדל ב-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", // The ID for this custom panorama.
      description: "Google Sydney - Reception",
      latLng: new google.maps.LatLng(-33.86684, 151.19583),
    },
    links: [
      {
        heading: 195,
        description: "Exit",
        pano: outsideGoogle.location.pano,
      },
    ],
    copyright: "Imagery (c) 2010 Google",
    tiles: {
      tileSize: new google.maps.Size(1024, 512),
      worldSize: new google.maps.Size(2048, 1024),
      centerHeading: 105,
      getTileUrl: function (pano, zoom, tileX, tileY) {
        return (
          "https://developers.google.com/maps/documentation/javascript/examples/full/images/" +
          "panoReception1024-" +
          zoom +
          "-" +
          tileX +
          "-" +
          tileY +
          ".jpg"
        );
      },
    },
  };
}

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

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

window.initMap = initMap;

CSS

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

#street-view {
  height: 100%;
}

HTML

<html>
  <head>
    <title>Custom Street View Panorama Tiles</title>

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

    <!-- 
      The `defer` attribute causes the script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>
להצגת דוגמה

כדאי לנסות דוגמה