שירות Street View

סקירה כללית

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

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

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


‫Maps JavaScript API מספק שירות Street View כדי לקבל את התמונות שמוצגות ב-Street View במפות Google ולבצע בהן שינויים. השירות הזה של 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.

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

תמונות פנורמיות ב-Street View

כדי להציג תמונות Street View, משתמשים באובייקט StreetViewPanorama, שמספק ממשק API ל "מציג" של Street View. כל מפה מכילה פנורמה ב-Street View כברירת מחדל, שאפשר לאחזר על ידי קריאה ל-method‏ 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 עצמאי בלי מפה.

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

ה-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

async function init(): Promise<void> {
    // Request needed libraries.
    const [{ StreetViewPanorama }] = await Promise.all([
        google.maps.importLibrary('streetView'),
        google.maps.importLibrary('maps'),
    ]);

    // Get the gmp-map element and its innerMap.
    const mapElement = document.querySelector('gmp-map')!;
    const innerMap = mapElement.innerMap;

    // Get the center of the map.
    const position = mapElement.center as google.maps.LatLng;

    // Create a new StreetViewPanorama, set its position, and attach it to the map.
    const panorama = new StreetViewPanorama(document.getElementById('pano')!, {
        position,
        pov: {
            heading: 34,
            pitch: 10,
        },
    });

    /**
     * Set the StreetViewPanorama so it displays in the pano element
     * rather than taking over the map.
     * This creates a link between the map and the panorama so that
     * the map is updated when the StreetViewPanorama position changes,
     * and the StreetViewPanorama is updated when the map changes.
     */
    innerMap.setStreetView(panorama);
}

void init();

JavaScript

async function init() {
    // Request needed libraries.
    const [{ StreetViewPanorama }] = await Promise.all([
        google.maps.importLibrary('streetView'),
        google.maps.importLibrary('maps'),
    ]);

    // Get the gmp-map element and its innerMap.
    const mapElement = document.querySelector('gmp-map');
    const innerMap = mapElement.innerMap;

    // Get the center of the map.
    const position = mapElement.center;

    // Create a new StreetViewPanorama, set its position, and attach it to the map.
    const panorama = new StreetViewPanorama(document.getElementById('pano'), {
        position,
        pov: {
            heading: 34,
            pitch: 10,
        },
    });

    /**
     * Set the StreetViewPanorama so it displays in the pano element
     * rather than taking over the map.
     * This creates a link between the map and the panorama so that
     * the map is updated when the StreetViewPanorama position changes,
     * and the StreetViewPanorama is updated when the map changes.
     */
    innerMap.setStreetView(panorama);
}

void init();

CSS

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

body {
    display: flex;
}

gmp-map,
#pano {
    flex: 1;
    height: 100%;
}

HTML

<html>
    <head>
        <title>Street View split-map-panes</title>

        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.ts"></script>
        <script>
            // prettier-ignore
            (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
                key: "GOOGLE_MAPS_API_KEY",
            });
        </script>
    </head>
    <body>
        <gmp-map
            center="42.345573,-71.098326"
            zoom="14"
            map-id="DEMO_MAP_ID"></gmp-map>
        <div id="pano"></div>
    </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

const ASSET_BASE_URL = new URL('https://maps-docs-team.web.app/samples/streetview-overlays/dist/');

let panorama: google.maps.StreetViewPanorama;
let innerMap: google.maps.Map;

async function init() {
    // Request needed libraries.
    const [{ Marker }] = await Promise.all([
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('maps'),
    ]);

    // Set the location of Astor Place.
    const astorPlace = { lat: 40.729884, lng: -73.990988 };

    const mapElement = document.querySelector('gmp-map')!;

    innerMap = mapElement.innerMap;

    document
        .getElementById('streetview-toggle-button')!
        .addEventListener('click', toggleStreetView);

    const cafeIcon = document.createElement('img');
    cafeIcon.src = new URL('./cafe_icon.svg', ASSET_BASE_URL).href;

    const dollarIcon = document.createElement('img');
    dollarIcon.src = new URL('./bank_icon.svg', ASSET_BASE_URL).href;

    const busIcon = document.createElement('img');
    busIcon.src = new URL('./bus_icon.svg', ASSET_BASE_URL).href;

    // Set up the markers on the map
    new Marker({
        position: { lat: 40.730031, lng: -73.991428 },
        map: innerMap,
        title: 'Cafe',
        icon: cafeIcon.src,
    });

    new Marker({
        position: { lat: 40.729681, lng: -73.991138 },
        map: innerMap,
        title: 'Bank',
        icon: dollarIcon.src,
    });

    new Marker({
        position: { lat: 40.729559, lng: -73.990741 },
        map: innerMap,
        title: 'Bus Stop',
        icon: busIcon.src,
    });

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

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

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

void init();

JavaScript

const ASSET_BASE_URL = new URL('https://maps-docs-team.web.app/samples/streetview-overlays/dist/');

let panorama;
let innerMap;

async function init() {
    // Request needed libraries.
    const [{ Marker }] = await Promise.all([
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('maps'),
    ]);

    // Set the location of Astor Place.
    const astorPlace = { lat: 40.729884, lng: -73.990988 };

    const mapElement = document.querySelector('gmp-map');

    innerMap = mapElement.innerMap;

    document
        .getElementById('streetview-toggle-button')
        .addEventListener('click', toggleStreetView);

    const cafeIcon = document.createElement('img');
    cafeIcon.src = new URL('./cafe_icon.svg', ASSET_BASE_URL).href;

    const dollarIcon = document.createElement('img');
    dollarIcon.src = new URL('./bank_icon.svg', ASSET_BASE_URL).href;

    const busIcon = document.createElement('img');
    busIcon.src = new URL('./bus_icon.svg', ASSET_BASE_URL).href;

    // Set up the markers on the map
    new Marker({
        position: { lat: 40.730031, lng: -73.991428 },
        map: innerMap,
        title: 'Cafe',
        icon: cafeIcon.src,
    });

    new Marker({
        position: { lat: 40.729681, lng: -73.991138 },
        map: innerMap,
        title: 'Bank',
        icon: dollarIcon.src,
    });

    new Marker({
        position: { lat: 40.729559, lng: -73.990741 },
        map: innerMap,
        title: 'Bus Stop',
        icon: busIcon.src,
    });

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

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

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

void init();
export {};

CSS

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

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

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

#streetview-toggle-button {
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 17px;
    border: none;
    background: white;
    cursor: pointer;
    border-radius: 2px;
    box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3);
    margin: 10px 0px 10px -2px;
    font-family: Roboto, Arial, sans-serif;
    font-size: 18px;
    font-weight: 400;
    color: rgb(86, 86, 86);
}

#streetview-toggle-button:hover {
    background: #f4f4f4;
    color: #000;
}

HTML

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

        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.js"></script>
        <script>
            // prettier-ignore
            (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
                key: "GOOGLE_MAPS_API_KEY"
            });
        </script>
    </head>
    <body>
        <gmp-map map-id="DEMO_MAP_ID" center="40.729884, -73.990988" zoom="18">
            <input
                type="button"
                value="Toggle Street View"
                id="streetview-toggle-button"
                slot="control-block-start-inline-start" />
        </gmp-map>
    </body>
</html>
להצגת דוגמה

דוגמה לניסיון

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

אפשר לשלוח בקשות ל-StreetViewService באמצעות StreetViewPanoRequest או StreetViewLocationRequest.

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

בקשה באמצעות StreetViewLocationRequest מחפשת נתוני פנורמה במיקום מסוים, באמצעות הפרמטרים הבאים:

  • הפרמטר location מציין את המיקום (קו רוחב וקו אורך) שבו רוצים לחפש תמונה פנורמית.
  • preference מגדיר העדפה לגבי התמונה הפנורמית שצריך למצוא בתוך הרדיוס: התמונה הקרובה ביותר למיקום שצוין, או התמונה הטובה ביותר בתוך הרדיוס.
  • הפרמטר radius מגדיר רדיוס במטרים שבו יתבצע חיפוש של פנורמה, כשהמרכז הוא קו הרוחב וקו האורך שצוינו. אם לא מציינים ערך, ברירת המחדל היא 50.
  • הפרמטר source מציין את מקור התמונות הפנורמיות לחיפוש. הערכים התקינים הם:
    • ‫default משתמש במקורות ברירת המחדל של Street View. החיפושים לא מוגבלים למקורות ספציפיים.
    • האפשרות outdoor מגבילה את החיפושים לאוספים של תמונות שצולמו בחוץ. שימו לב: יכול להיות שאין תמונות פנורמיות של חוץ המבנה במיקום שצוין.

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

הפונקציה getPanorama() צריכה פונקציית קריאה חוזרת כדי לפעול אחרי אחזור תוצאה משירות 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 בהתאמה אישית

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

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

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

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

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

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

תצוגה פנורמית של רחוב בעיר

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

כדור עם תצוגה פנורמית של רחוב על פני השטח שלו

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

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

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

כשהאובייקט StreetViewPanorama נטען בפעם הראשונה, כברירת מחדל מוצגת תמונה שמורכבת מ-25% (קשת של 90 מעלות) מהרוחב האופקי של הפנורמה ברמת זום 1. התצוגה הזו תואמת פחות או יותר לשדה הראייה הרגיל של בני אדם. הקטנת התצוגה (zoom out) מברירת המחדל הזו מספקת קשת רחבה יותר, והגדלת התצוגה (zoom in) מצמצמת את שדה הראייה לקשת קטנה יותר. ‫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, ובכל רמת זום גבוהה יותר יש 4zoomLevel משבצות. (לדוגמה, ברמת זום 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

async function init(): Promise<void> {
    // Request needed libraries.
    const [{ StreetViewPanorama }, { Size }] = await Promise.all([
        google.maps.importLibrary('streetView'),
        google.maps.importLibrary('core'),
    ]);

    // Construct the appropriate StreetViewPanoramaData given
    // the passed pano IDs.
    function getCustomPanorama(
        pano: string
    ): google.maps.StreetViewPanoramaData | null {
        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 Size(1024, 512),
                    worldSize: new Size(2048, 1024),
                    // The heading in degrees at the origin of the panorama
                    // tile set.
                    centerHeading: 105,
                    getTileUrl: getCustomPanoramaTileUrl,
                },
            };
        }
        return null;
    }

    // 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 StreetViewPanorama(document.getElementById('map')!, {
        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-${String(zoom)}-${String(tileX)}-${String(tileY)}.jpg`;
}

void init();

JavaScript

async function init() {
    // Request needed libraries.
    const [{ StreetViewPanorama }, { Size }] = await Promise.all([
        google.maps.importLibrary('streetView'),
        google.maps.importLibrary('core'),
    ]);

    // 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 Size(1024, 512),
                    worldSize: new Size(2048, 1024),
                    // The heading in degrees at the origin of the panorama
                    // tile set.
                    centerHeading: 105,
                    getTileUrl: getCustomPanoramaTileUrl,
                },
            };
        }
        return null;
    }

    // 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 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-${String(zoom)}-${String(tileX)}-${String(tileY)}.jpg`;
}

void init();

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>
        <script>
            // prettier-ignore
            (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
                key: "GOOGLE_MAPS_API_KEY"
            });
        </script>
    </head>
    <body>
        <div id="map"></div>
    </body>
</html>
להצגת דוגמה

דוגמה לניסיון

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

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

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>
להצגת דוגמה