خدمات «نمای خیابان»

نمای کلی

پلاتفرم را انتخاب کنید: Android iOS JavaScript

«نمای خیابان Google» نماهای تمام‌نمای ۳۶۰ درجه از جاده‌های تعیین‌شده در سراسر منطقه پوشش خود ارائه می‌دهد. پوشش API «نمای خیابان» با پوشش برنامه Google Maps (https://maps.google.com/) یکسان است. فهرست شهرهایی که درحال‌حاضر از «نمای خیابان» پشتیبانی می‌کنند در وب‌سایت Google Maps دردسترس است.

تصویر نمونه‌ای از «نمای خیابان» در زیر نشان داده شده است.


‫Maps JavaScript API سرویس «نمای خیابان» را برای دریافت و دستکاری تصاویر استفاده‌شده در «نمای خیابان» Google Maps ارائه می‌دهد. این سرویس «نمای خیابان» به‌طور بومی در مرورگر پشتیبانی می‌شود.

استفاده از نقشه «نمای خیابان»

اگرچه «نمای خیابان» را می‌توان در عنصر DOM مستقل استفاده کرد، بیشترین کاربرد آن هنگام نشان دادن مکان روی نقشه است. به‌طور پیش‌فرض، «نمای خیابان» در نقشه فعال است و کنترل آدمک نمای خیابان در کنترل‌های ناوبری (زوم و حرکت) یکپارچه می‌شود. با تنظیم streetViewControl روی false، می‌توانید این کنترل را در MapOptions نقشه پنهان کنید. همچنین می‌توانید با تنظیم کردن دارایی MapstreetViewControlOptions.position به ControlPosition جدید، جایگاه پیش‌فرض کنترل «نمای خیابان» را تغییر دهید.

کنترل آدمک «نمای خیابان» به شما امکان می‌دهد پانوراماهای «نمای خیابان» را مستقیماً در نقشه مشاهده کنید. وقتی کاربر روی «آدمک» کلیک می‌کند و نگه می‌دارد، نقشه به‌روز می‌شود تا خطوط آبی اطراف خیابان‌های دارای «نمای خیابان» را نشان دهد، و تجربه کاربری مشابه برنامه Google Maps را ارائه دهد.

وقتی کاربر نشانگر «آدمک» را روی خیابانی رها می‌کند، نقشه به‌روز می‌شود تا عکس تمام‌نمای «نمای خیابان» مکان نشان‌داده‌شده را نمایش دهد.

تمام‌نماهای «نمای خیابان»

تصاویر «نمای خیابان» ازطریق استفاده از شیء StreetViewPanorama پشتیبانی می‌شود که یک میانای برنامه‌سازی کاربردی برای «نمایشگر» «نمای خیابان» ارائه می‌دهد. هر نقشه حاوی یک تمام‌نمای «نمای خیابان» پیش‌فرض است که می‌توانید با فراخوانی روش getStreetView() نقشه آن را بازیابی کنید. وقتی با تنظیم گزینه streetViewControl آن روی true، کنترل «نمای خیابان» را به نقشه اضافه می‌کنید، کنترل «آدمک» را به‌طور خودکار به این پانورامای پیش‌فرض «نمای خیابان» متصل می‌کنید.

همچنین می‌توانید StreetViewPanorama شیء خودتان را بسازید و با تنظیم صریح دارایی streetView نقشه روی آن شیء ساخته‌شده، نقشه را تنظیم کنید تا به‌جای شیء پیش‌فرض از آن استفاده کند. اگر می‌خواهید رفتار پیش‌فرض را تغییر دهید، مثلاً هم‌رسانی خودکار رونهادها بین نقشه و پانوراما، می‌توانید پانورامای پیش‌فرض را ملغی کنید. (به رونهادها در «نمای خیابان» در زیر مراجعه کنید.)

Street View Containers

شاید بخواهید به‌جای آن، StreetViewPanorama را در عنصر DOM جداگانه‌ای، که اغلب عنصر <div> است، نمایش دهید. به‌سادگی عنصر DOM را در سازنده StreetViewPanorama بگذرانید. برای نمایش بهینه تصاویر، حداقل اندازه ۲۰۰ پیکسل در ۲۰۰ پیکسل را توصیه می‌کنیم.

توجه: اگرچه عملکرد «نمای خیابان» برای استفاده همراه با نقشه طراحی شده است، این استفاده الزامی نیست. می‌توانید از یک شیء مستقل «نمای خیابان» بدون نقشه استفاده کنید.

مکان‌های «نمای خیابان» و دیدگاه (POV)

ساخت‌گر StreetViewPanorama همچنین به شما امکان می‌دهد مکان و نقطه دید «نمای خیابان» را بااستفاده از پارامتر StreetViewOptions تنظیم کنید. پس‌از ساختن این شیء می‌توانید با setPosition() و setPov() تماس بگیرید تا مکان و نقطه دید آن را تغییر دهید.

مکان «نمای خیابان» جایگاه کانون دوربین را برای تصویر تعریف می‌کند، اما جهت دوربین را برای آن تصویر تعریف نمی‌کند. برای این منظور، شیء StreetViewPov دو ویژگی را تعریف می‌کند:

  • heading (پیش‌فرض 0) زاویه چرخش را حول مکان دوربین برحسب درجه نسبت‌به شمال واقعی تعریف می‌کند. جهت‌ها به‌صورت ساعت‌گرد اندازه‌گیری می‌شوند (۹۰ درجه شرق واقعی است).
  • ‫pitch (پیش‌فرض 0) انحراف زاویه را از «بالا» یا «پایین» از گام پیش‌فرض اولیه دوربین، که اغلب (اما نه همیشه) افقی مسطح است، تعریف می‌کند. (برای مثال، تصویری که در تپه‌ای گرفته شده است احتمالاً دارای شیب پیش‌فرضی است که افقی نیست.) زاویه‌های گام با مقادیر مثبت که به بالا نگاه می‌کنند (تا +۹۰ درجه مستقیم به بالا و متعامد با گام پیش‌فرض) و مقادیر منفی که به پایین نگاه می‌کنند (تا -۹۰ درجه مستقیم به پایین و متعامد با گام پیش‌فرض) اندازه‌گیری می‌شوند.

از شیء StreetViewPov بیشتر برای تعیین نقطه دید دوربین «نمای خیابان» استفاده می‌شود. همچنین می‌توانید نقطه دید عکاس — معمولاً جهتی که خودرو یا سه‌چرخه به آن سمت بوده است — را با StreetViewPanorama.getPhotographerPov() روش تعیین کنید.

کد زیر نقشه بوستون را با نمای اولیه پارک فنوی نمایش می‌دهد. پارک. انتخاب آدمک و کشیدن آن به مکان پشتیبانی‌شده در نقشه باعث تغییر عکس تمام‌نمای «نمای خیابان» می‌شود:

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 به کاربران امکان می‌دهد دیدگاه «نمای خیابان» را براساس حرکت دستگاه تغییر دهند. کاربران می‌توانند با حرکت دادن دستگاه‌هایشان اطراف را نگاه کنند. به این کار ردیابی حرکت یا ردیابی چرخش دستگاه می‌گویند.

به‌عنوان توسعه‌دهنده نرم‌افزار، می‌توانید رفتار پیش‌فرض را به این صورت تغییر دهید:

  • فعال یا غیرفعال کردن عملکرد ردیابی حرکت. به‌طور پیش‌فرض، ردیابی حرکت در هر دستگاهی که از آن پشتیبانی می‌کند فعال است. نمونه زیر پیگیری حرکت را غیرفعال می‌کند، اما کنترل پیگیری حرکت را نمایان می‌گذارد. (توجه داشته باشید که کاربر می‌تواند با تک‌ضرب زدن روی کنترل، ردیابی حرکت را روشن کند.)
    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
          }
        });

برای دیدن ردیابی حرکت در عمل، نمونه زیر را در دستگاه همراه (یا هر دستگاهی که از رویدادهای جهت‌گیری دستگاه پشتیبانی می‌کند) مشاهده کنید:


مشاهده مثال

هم‌پوشانی‌ها در «نمای خیابان»

شیء پیش‌فرض StreetViewPanorama از نمایش بومی رونهادهای نقشه پشتیبانی می‌کند. لایه‌های رویی معمولاً در «سطح خیابان» ظاهر می‌شوند و در LatLng موقعیت لنگر می‌اندازند. (نشانگرها با دم‌هایشان که به صفحه افقی مکان در پانورامای «نمای خیابان» متصل شده‌اند ظاهر می‌شوند، برای مثال.)

درحال‌حاضر، انواع رونهادهایی که در پانوراماهای «نمای خیابان» پشتیبانی می‌شوند به Marker، InfoWindow، و OverlayView سفارشی محدود می‌شوند. رونهادهایی که در نقشه نمایش می‌دهید ممکن است با درنظر گرفتن تمام‌نما به‌عنوان جایگزینی برای شیء Map، با فراخوانی setMap() و ارسال StreetViewPanorama به‌عنوان آرگومان به‌جای نقشه، در تمام‌نمای «نمای خیابان» نمایش داده شوند. پنجره‌های اطلاعات نیز ممکن است با فراخوانی open() و ارسال StreetViewPanorama() به‌جای نقشه، در پانورامای «نمای خیابان» باز شوند.

علاوه‌براین، هنگام ایجاد نقشه با پیش‌فرض StreetViewPanorama، هر نشانگری که در نقشه ایجاد می‌شود به‌طور خودکار با پانورامای «نمای خیابان» مرتبط با نقشه هم‌رسانی می‌شود، به‌شرطی که پانوراما نمایان باشد. برای بازیابی پانورامای پیش‌فرض «نمای خیابان»، getStreetView() را در شیء Map فراخوانی کنید. توجه داشته باشید که اگر صریحاً دارایی streetView نقشه را روی StreetViewPanorama ساختار خودتان تنظیم کنید، نمای پانورامای پیش‌فرض را ملغی خواهید کرد.

مثال زیر نشانگرهایی را نشان می‌دهد که مکان‌های مختلف اطراف «میدان آستور»، نیویورک را مشخص می‌کنند. نمایشگر را به «نمای خیابان» تغییر دهید تا نشانگرهای هم‌رسانی‌شده در StreetViewPanorama نمایش داده شود.

TypeScript

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('./public/cafe_icon.svg', import.meta.url).href;

    const dollarIcon = document.createElement('img');
    dollarIcon.src = new URL('./public/bank_icon.svg', import.meta.url).href;

    const busIcon = document.createElement('img');
    busIcon.src = new URL('./public/bus_icon.svg', import.meta.url).href;

    // Set up the markers on the map
    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

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('./public/cafe_icon.svg', import.meta.url).href;

    const dollarIcon = document.createElement('img');
    dollarIcon.src = new URL('./public/bank_icon.svg', import.meta.url).href;

    const busIcon = document.createElement('img');
    busIcon.src = new URL('./public/bus_icon.svg', import.meta.url).href;

    // Set up the markers on the map
    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>
مشاهده مثال

رویدادهای «نمای خیابان»

هنگام پیمایش بین «نمای خیابان» یا دستکاری جهت آن، ممکن است بخواهید چندین رویداد را که نشان‌دهنده تغییرات وضعیت StreetViewPanorama است نظارت کنید:

  • هرگاه شناسه پانورامای تکی تغییر کند، pano_changed راه‌اندازی می‌شود. این رویداد تضمین نمی‌کند که هرگونه داده مرتبط در پانوراما (مثل پیوندها) نیز تا زمانی که این رویداد راه‌اندازی می‌شود تغییر کرده باشد؛ این رویداد فقط نشان می‌دهد که شناسه پانوراما تغییر کرده است. توجه داشته باشید که شناسه پانوراما (که می‌توانید از آن برای ارجاع دادن به این پانوراما استفاده کنید) فقط در جلسه مرورگر فعلی پایدار است.
  • هرزمان که موقعیت زیرین (LatLng) پانوراما تغییر کند، position_changed فعال می‌شود. چرخاندن پانوراما باعث راه‌اندازی این رویداد نخواهد شد. توجه داشته باشید که می‌توانید موقعیت زیرین نمای پانوراما را بدون تغییر دادن شناسه پانورامای مرتبط تغییر دهید، زیرا «میانای برنامه‌سازی کاربردی» به‌طور خودکار نزدیک‌ترین شناسه پانوراما را به موقعیت نمای پانوراما مرتبط می‌کند.
  • pov_changed هر زمان که StreetViewPov «نمای خیابان» تغییر کند، فعال می‌شود. توجه داشته باشید که این رویداد ممکن است زمانی فعال شود که موقعیت و شناسه پانوراما ثابت باقی بمانند.
  • links_changed هرگاه پیوندهای «نمای خیابان» تغییر کند، اجرا می‌شود. توجه داشته باشید که این رویداد ممکن است به‌صورت ناهمزمان پس‌از تغییر در شناسه پانوراما که ازطریق pano_changed نشان داده می‌شود فعال شود.
  • هرگاه رؤیت‌پذیری «نمای خیابان» تغییر کند، visible_changed فعال می‌شود. توجه داشته باشید که این رویداد ممکن است به‌صورت ناهمگام پس‌از تغییر در شناسه پانوراما که ازطریق 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>
مشاهده مثال

کنترل‌های «نمای خیابان»

هنگام نمایش StreetViewPanorama، انواع مختلفی از کنترل‌ها به‌طور پیش‌فرض روی تمام‌نما ظاهر می‌شوند. با تنظیم کردن فیلدهای مناسب در StreetViewPanoramaOptions به true یا false می‌توانید این کنترل‌ها را فعال یا غیرفعال کنید:

  • panControl راهی برای چرخاندن تمام‌نما ارائه می‌دهد. این کنترل به‌طور پیش‌فرض به‌عنوان قطب‌نمای یکپارچه استاندارد و کنترل چرخش ظاهر می‌شود. می‌توانید با ارائه PanControlOptions در فیلد panControlOptions، جایگاه کنترل را تغییر دهید.
  • zoomControl روشی برای زوم‌پیش کردن در تصویر ارائه می‌دهد. این کنترل به‌طور پیش‌فرض نزدیک پایین سمت چپ تمام‌نما نشان داده می‌شود. با ارائه ZoomControlOptions در فیلد zoomControlOptions می‌توانید ظاهر کنترل را تغییر دهید.
  • addressControl رونهادی نوشتاری ارائه می‌دهد که نشانی مکان منسوب را نشان می‌دهد و پیوندی برای باز کردن مکان در Google Maps ارائه می‌دهد. با ارائه StreetViewAddressControlOptions در فیلد addressControlOptions می‌توانید ظاهر کنترل را تغییر دهید.
  • fullscreenControl گزینه باز کردن «نمای خیابان» در حالت تمام‌صفحه را ارائه می‌دهد. می‌توانید ظاهر کنترل را با ارائه FullscreenControlOptions در فیلد fullscreenControlOptions تغییر دهید.
  • motionTrackingControl گزینه فعال یا غیرفعال کردن ردیابی حرکت در دستگاه‌های همراه را ارائه می‌دهد. این کنترل فقط در دستگاه‌هایی که از رویدادهای جهت دستگاه پشتیبانی می‌کنند ظاهر می‌شود. به‌طور پیش‌فرض، کنترل در نزدیکی پایین سمت چپ پانوراما ظاهر می‌شود. با ارائه MotionTrackingControlOptions می‌توانید جایگاه کنترل را تغییر دهید. برای اطلاعات بیشتر، بخش مربوط به ردیابی حرکت را ببینید.
  • linksControl در تصویر برای رفتن به تصاویر تمام‌نمای مجاور، پیکان‌های راهنما ارائه می‌دهد.
  • کنترل «بستن» به کاربر اجازه می‌دهد نمایشگر «نمای خیابان» را ببندد. می‌توانید با تنظیم enableCloseButton روی true یا false، کنترل «بستن» را فعال یا غیرفعال کنید.

مثال زیر کنترل‌های نمایش‌داده‌شده در «نمای خیابان» مرتبط را تغییر می‌دهد و پیوندهای نما را برمی‌دارد:

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>
مشاهده مثال

دسترسی مستقیم به داده‌های «نمای خیابان»

ممکن است بخواهید دردسترس بودن داده‌های «نمای خیابان» را به‌صورت برنامه‌نویسی‌شده تعیین کنید یا اطلاعات مربوط به تمام‌نماهای خاص را بدون نیاز به دستکاری مستقیم نقشه/تمام‌نما برگردانید. می‌توانید این کار را بااستفاده از شیء StreetViewService انجام دهید که واسطی برای داده‌های ذخیره‌شده در سرویس «نمای خیابان Google» ارائه می‌دهد.

درخواست‌های خدمات «نمای خیابان»

دسترسی به سرویس «نمای خیابان» ناهمزمان است، زیرا Google Maps API باید با سرور خارجی تماس بگیرد. به همین دلیل، باید یک روش بازخوانی را برای اجرا پس‌از تکمیل درخواست ارسال کنید. این روش فراخوانی نتیجه را پردازش می‌کند.

می‌توانید بااستفاده از StreetViewPanoRequest یا StreetViewLocationRequest درخواست‌هایی را به StreetViewService ارسال کنید.

درخواست بااستفاده از StreetViewPanoRequest داده‌های پانوراما را با شناسه مرجعی که پانوراما را به‌طور منحصربه‌فرد شناسایی می‌کند برمی‌گرداند. توجه داشته باشید که این شناسه‌های مرجع فقط برای طول عمر تصویر آن پانوراما پایدار هستند.

درخواستی که از StreetViewLocationRequest استفاده می‌کند داده‌های پانوراما را در مکان مشخصی بااستفاده از پارامترهای زیر جستجو می‌کند:

  • ‫location مکان (عرض و طول جغرافیایی) را برای جستجوی پانوراما مشخص می‌کند.
  • preference اولویت را برای اینکه کدام عکس تمام‌نما باید در شعاع پیدا شود تعیین می‌کند: نزدیک‌ترین عکس به مکان ارائه‌شده، یا بهترین عکس در شعاع.
  • ‫radius شعاعی را که برحسب متر مشخص شده است تنظیم می‌کند تا در آن شعاع به‌دنبال پانوراما بگردد، پانوراما در عرض و طول جغرافیایی داده‌شده مرکزیت دارد. اگر ارائه نشود، به‌طور پیش‌فرض روی ۵۰ تنظیم می‌شود.
  • ‫source منبع پانوراماها را برای جستجو مشخص می‌کند. مقادیر معتبر عبارت‌اند از:
    • ‫default از منابع پیش‌فرض برای «نمای خیابان» استفاده می‌کند؛ جستجوها به منابع خاص محدود نمی‌شود.
    • ‫outdoor جستجوها را به مجموعه‌های فضای باز محدود می‌کند. توجه داشته باشید که ممکن است برای مکان مشخص‌شده، تمام‌نمای فضای باز وجود نداشته باشد.

پاسخ‌های سرویس «نمای خیابان»

تابع getPanorama() برای اجرا شدن پس‌از بازیابی نتیجه از سرویس «نمای خیابان» به تابع کال‌بک نیاز دارد. این تابع برگشتی مجموعه‌ای از داده‌های پانوراما را در شیء StreetViewPanoramaData و کد StreetViewStatus که نشان‌دهنده وضعیت درخواست است به‌ترتیب برمی‌گرداند.

مشخصات شیء StreetViewPanoramaData حاوی فراداده‌ای درباره تمام‌نمای «نمای خیابان» به شکل زیر است:

{
  "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 نیست. برای ایجاد کردن شیء «نمای خیابان» بااستفاده از این داده‌ها، باید StreetViewPanorama ایجاد کنید و setPano() را فراخوانی کنید و شناسه را همان‌طور که در فیلد location.pano برگشتی ذکر شده است به آن منتقل کنید.

کد status ممکن است یکی از مقادیر زیر را برگرداند:

  • OK نشان می‌دهد که سرویس، تمام‌نمای منطبقی پیدا کرده است.
  • ‫ZERO_RESULTS نشان می‌دهد که سرویس نتوانسته است پانورامای منطبقی با معیارهای ارسال‌شده پیدا کند.
  • ‫UNKNOWN_ERROR نشان می‌دهد که درخواست «نمای خیابان» پردازش نشده است، هرچند دلیل دقیق آن مشخص نیست.

کد زیر 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>
مشاهده مثال

ارائه تمام‌نماهای سفارشی «نمای خیابان»

‫Maps JavaScript API از نمایش تمام‌نماهای سفارشی در شیء StreetViewPanorama پشتیبانی می‌کند. بااستفاده از تمام‌نماهای سفارشی، می‌توانید فضای داخلی ساختمان‌ها، نماهای مکان‌های دیدنی، یا هر چیزی را که در تخیلتان است نمایش دهید. حتی می‌توانید این تمام‌نماهای سفارشی را به تمام‌نماهای «نمای خیابان» موجود Google پیوند دهید.

راه‌اندازی مجموعه‌ای از تصاویر تمام‌نمای سفارشی شامل مراحل زیر است:

  • برای هر سراسرنمای سفارشی، یک تصویر سراسرنمای پایه ایجاد کنید. این تصویر پایه باید با بالاترین وضوح تصویری باشد که می‌خواهید تصاویر بزرگ‌نمایی‌شده را ارائه دهید.
  • (اختیاری، اما توصیه می‌شود) مجموعه‌ای از کاشی‌های پانوراما در سطوح مختلف بزرگ‌نمایی از تصویر پایه ایجاد کنید.
  • بین تمام‌نماهای سفارشی‌تان پیوند ایجاد کنید.
  • (اختیاری) پانوراماهای «ورودی» را در تصاویر موجود «نمای خیابان Google» تعیین کنید و پیوندها را به/از مجموعه سفارشی به مجموعه استاندارد سفارشی‌سازی کنید.
  • فراداده را برای هر تصویر پانوراما در شیء StreetViewPanoramaData تعریف کنید.
  • روشی را پیاده‌سازی کنید که داده‌ها و تصاویر پانورامای سفارشی را تعیین کند و آن روش را به‌عنوان مدیریت‌کننده سفارشی خود در شیء StreetViewPanorama تعیین کنید.

بخش‌های زیر این فرایند را توضیح می‌دهند.

درحال ایجاد پانوراماهای سفارشی

هر تمام‌نمای «نمای خیابان» تصویر یا مجموعه‌ای از تصاویر است که نمای ۳۶۰ درجه کامل از یک مکان واحد ارائه می‌دهد. شیء StreetViewPanorama از تصاویری استفاده می‌کند که با طرح تصویر استوانه‌ای (Plate Carrée) مطابقت دارند. چنین طرحی شامل ۳۶۰ درجه نمای افقی (نمای کامل دور) و ۱۸۰ درجه نمای عمودی (از بالا تا پایین) است. این فیلدهای دید منجر به تصویری با نسبت ابعادی ۲:۱ می‌شود. نمای پانورامای ۳۶۰ درجه در زیر نشان داده شده است.

نمای تمام‌نمای خیابان شهر

تصاویر تمام‌نما معمولاً با گرفتن چندین عکس از یک موقعیت و به‌هم چسباندن آن‌ها بااستفاده از نرم‌افزار تمام‌نما به‌دست می‌آیند. (برای اطلاعات بیشتر، به مقایسه برنامه‌های وصله‌دوزی عکس در ویکی‌پدیا مراجعه کنید.) چنین تصاویری باید یک مکان «دوربین» واحد داشته باشند که هریک از تصاویر تمام‌نما از آنجا گرفته شده است. سپس تمام‌نمای ۳۶۰ درجه حاصل می‌تواند تصویری را روی یک کره تعریف کند که تصویر روی سطح دوبعدی کره پیچیده شده است.

کره‌ای با نمای تمام‌نمای خیابان روی سطح آن

درنظر گرفتن سراسرنما به‌عنوان تصویری روی کره با سیستم مختصات راست‌خط هنگام تقسیم تصویر به کاشی‌های راست‌خط و ارائه تصاویر براساس مختصات کاشی محاسبه‌شده، مفید است.

درحال ایجاد کاشی‌های پانورامای سفارشی

«نمای خیابان» همچنین از سطوح مختلف جزئیات تصویر ازطریق استفاده از کنترل بزرگ‌نمایی پشتیبانی می‌کند که به شما امکان می‌دهد از نمای پیش‌فرض بزرگ‌نمایی و کوچک‌نمایی کنید. به‌طورکلی، «نمای خیابان» پنج سطح وضوح بزرگ‌نمایی برای هر تصویر تمام‌نمای معینی ارائه می‌دهد. اگر بخواهید برای ارائه همه سطوح بزرگ‌نمایی به یک تصویر پانوراما تکیه کنید، چنین تصویری یا باید بسیار بزرگ باشد و به‌طور قابل‌توجهی سرعت برنامه‌تان را کاهش دهد، یا در سطوح بزرگ‌نمایی بالاتر وضوح بسیار پایینی داشته باشد و درنتیجه تصویر پیکسلی‌شده‌ای ارائه دهید. خوشبختانه، بااین‌حال، می‌توانیم از الگوی طراحی مشابهی که برای ارائه کاشی‌های نقشه Google در سطوح بزرگ‌نمایی مختلف استفاده می‌شود برای ارائه تصاویر با وضوح مناسب برای پانوراما در هر سطح بزرگ‌نمایی استفاده کنیم.

وقتی StreetViewPanorama برای اولین‌بار بار می‌شود، به‌طور پیش‌فرض تصویری را نمایش می‌دهد که شامل ۲۵٪ (۹۰ درجه قوس) از عرض افقی تمام‌نما در سطح بزرگ‌نمایی ۱ است. این نما تقریباً با میدان دید طبیعی انسان مطابقت دارد. زوم‌پَس کردن از این نمای پیش‌فرض اساساً یک کمان وسیع‌تر ارائه می‌دهد، درحالی‌که زوم‌پیش کردن میدان دید را به یک کمان کوچک‌تر محدود می‌کند. StreetViewPanorama به‌طور خودکار میدان دید مناسب را برای سطح بزرگ‌نمایی انتخاب‌شده محاسبه می‌کند و سپس با انتخاب مجموعه کاشی که تقریباً با ابعاد میدان دید افقی مطابقت دارد، تصویربرداری مناسب‌ترین برای آن وضوح را انتخاب می‌کند. میدان‌های دید زیر با سطوح بزرگ‌نمایی «نمای خیابان» مطابقت دارند:

سطح بزرگ‌نمایی «نمای خیابان» میدان دید (درجه)
0 ۱۸۰
‫۱ (پیش‌فرض) ۹۰
2 ۴۵
3 ۲۲٫۵
4 ۱۱.۲۵

توجه داشته باشید که اندازه تصویر نشان‌داده‌شده در «نمای خیابان» کاملاً به اندازه صفحه‌نمایش (عرض) محفظه «نمای خیابان» بستگی دارد. اگر محفظه پهن‌تری ارائه دهید، سرویس همچنان همان میدان دید را برای هر سطح بزرگ‌نمایی معینی ارائه خواهد داد، هرچند ممکن است کاشی‌های مناسب‌تر برای آن وضوح را انتخاب کند.

ازآنجایی‌که هر پانوراما از یک تصویر استوانه‌ای تشکیل شده است، ایجاد کاشی‌های پانوراما نسبتاً آسان است. ازآنجایی‌که تصویر با نسبت ابعادی ۲:۱ ارائه می‌شود، استفاده از کاشی‌های با نسبت ۲:۱ آسان‌تر است، هرچند کاشی‌های مربعی ممکن است در نقشه‌های مربعی عملکرد بهتری داشته باشند (زیرا میدان دید مربعی خواهد بود).

برای کاشی‌های ۲:۱، یک تصویر واحد که کل تمام‌نما را دربرمی‌گیرد، کل «جهان» تمام‌نما (تصویر پایه) را در سطح بزرگ‌نمایی ۰ نشان می‌دهد، و هر سطح بزرگ‌نمایی افزایشی، zoomLevel کاشی ارائه می‌دهد. (برای نمونه، در سطح بزرگ‌نمایی ۲، کل پانوراما از ۱۶ کاشی تشکیل شده است.) توجه: سطوح بزرگ‌نمایی در کاشی‌بندی «نمای خیابان» مستقیماً با سطوح بزرگ‌نمایی ارائه‌شده بااستفاده از کنترل «نمای خیابان» مطابقت ندارد؛ درعوض، سطوح بزرگ‌نمایی کنترل «نمای خیابان» یک «میدان دید» (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 تنظیم نکنید، زیرا چنین موقعیتی به سرویس «نمای خیابان» دستور می‌دهد تا تصاویر پیش‌فرض «نمای خیابان» را در نزدیکی آن مکان درخواست کند. درعوض، این موقعیت را در فیلد location.latLng شیء StreetViewPanoramaData سفارشی تنظیم کنید.

مثال زیر نمای پانورامای سفارشی از دفتر Google در سیدنی را نشان می‌دهد. توجه داشته باشید که این مثال از نقشه یا تصاویر پیش‌فرض «نمای خیابان» استفاده نمی‌کند:

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.

مثال زیر علاوه‌بر پیکان‌های پیمایش پیش‌فرض «نمای خیابان»، پیکان دیگری به تصویر اضافه می‌کند که به 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>
مشاهده مثال