نظرة عامة
توفّر ميزة "التجوّل الافتراضي من Google" إطلالات بانورامية بزاوية 360 درجة من الطرق المحدّدة في جميع أنحاء منطقة التغطية. تتطابق تغطية واجهة برمجة التطبيقات الخاصة بميزة "التجوّل الافتراضي" مع تغطية تطبيق "خرائط Google" (https://maps.google.com/). ويمكنك الاطّلاع على قائمة المدن التي تتوفّر فيها ميزة "التجوّل الافتراضي" حاليًا على الموقع الإلكتروني لخرائط Google.
يتم عرض نموذج لصورة "التجوّل الافتراضي" أدناه.
توفّر Maps JavaScript API خدمة "التجوّل الافتراضي" للحصول على الصور المستخدَمة في ميزة "التجوّل الافتراضي" من "خرائط Google" ومعالجتها. تتوفّر خدمة "التجوّل الافتراضي" هذه بشكل أصلي ضمن المتصفّح.
استخدام خريطة "التجوّل الافتراضي"
على الرغم من أنّه يمكن استخدام "التجوّل الافتراضي" ضمن عنصر DOM مستقل، إلا أنّه يكون أكثر فائدة عند الإشارة إلى موقع جغرافي على خريطة. يكون "التجوّل الافتراضي" مفعّلاً تلقائيًا على الخريطة، ويظهر عنصر تحكّم "الدليل" الخاص بـ "التجوّل الافتراضي" مدمجًا في عناصر التحكّم في التنقّل (التكبير والتصغير والتنقل). يمكنك إخفاء عنصر التحكّم هذا ضمن MapOptions في الخريطة من خلال ضبط streetViewControl على false. يمكنك أيضًا تغيير الموضع التلقائي لعنصر التحكّم في Street View من خلال ضبط السمة streetViewControlOptions.position الخاصة بـ Map على قيمة ControlPosition جديدة.
يتيح لك عنصر التحكّم "دليل التجوّل الافتراضي" عرض صور بانورامية في "التجوّل الافتراضي" مباشرةً ضمن الخريطة. عندما ينقر المستخدم على "الدليل" مع الاستمرار في الضغط، يتم تعديل الخريطة لعرض خطوط زرقاء حول الشوارع التي تتوفّر فيها ميزة "التجوّل الافتراضي"، ما يوفّر تجربة مستخدم مشابهة لتطبيق "خرائط Google".
عندما يسحب المستخدم علامة "الدليل" إلى شارع، يتم تعديل الخريطة لعرض صورة بانورامية من "التجوّل الافتراضي" للموقع الجغرافي المحدّد.
بانوراما في "التجوّل الافتراضي"
تتوفّر صور "التجوّل الافتراضي" من خلال استخدام العنصر StreetViewPanorama، الذي يوفّر واجهة برمجة تطبيقات لواجهة "عارض" ميزة "التجوّل الافتراضي". تحتوي كل خريطة على بانوراما تلقائية من "التجوّل الافتراضي"، ويمكنك استردادها من خلال استدعاء طريقة getStreetView() الخاصة بالخريطة. عند إضافة عنصر تحكّم في "التجوّل الافتراضي" إلى الخريطة من خلال ضبط الخيار streetViewControl على true، يتم تلقائيًا ربط عنصر التحكّم "الدليل" بلوحة بانوراما "التجوّل الافتراضي" التلقائية هذه.
يمكنك أيضًا إنشاء عنصر StreetViewPanorama خاص بك وضبط الخريطة لاستخدامه بدلاً من العنصر التلقائي، وذلك من خلال ضبط السمة streetView الخاصة بالخريطة بشكل صريح على العنصر الذي تم إنشاؤه. يمكنك إلغاء إعدادات بانوراما التلقائية إذا أردت تعديل السلوك التلقائي، مثل المشاركة التلقائية للتراكبات بين الخريطة والبانوراما. (اطّلِع على التراكبات ضمن "التجوّل الافتراضي" أدناه).
حاويات "التجوّل الافتراضي"
بدلاً من ذلك، قد تريد عرض StreetViewPanorama
ضمن عنصر DOM منفصل، وغالبًا ما يكون عنصر <div>.
ما عليك سوى تمرير عنصر DOM ضمن أداة إنشاء StreetViewPanorama. لضمان عرض الصور على النحو الأمثل، ننصحك باستخدام صور لا يقل حجمها عن 200 بكسل × 200 بكسل.
ملاحظة: على الرغم من أنّ وظيفة Street View مصمّمة ليتم استخدامها مع خريطة، إلا أنّ هذا الاستخدام ليس مطلوبًا. يمكنك استخدام كائن "التجوّل الافتراضي" مستقل بدون خريطة.
المواقع الجغرافية في "التجوّل الافتراضي" ووجهة النظر
تتيح لك الدالة الإنشائية StreetViewPanorama أيضًا ضبط الموقع الجغرافي ونقطة العرض في "التجوّل الافتراضي" باستخدام المَعلمة StreetViewOptions. يمكنك استدعاء
setPosition() وsetPov() على العنصر بعد إنشائه لتغيير موقعه الجغرافي ووجهة نظره.
يحدّد الموقع الجغرافي في "التجوّل الافتراضي" موضع تركيز الكاميرا في الصورة، ولكنّه لا يحدّد اتجاه الكاميرا في تلك الصورة. لهذا الغرض، يحدّد الكائن StreetViewPov سمتَين:
- تحدّد
heading(القيمة التلقائية0) زاوية الدوران حول موضع الكاميرا بالدرجات نسبةً إلى الشمال الحقيقي. يتم قياس العناوين في اتجاه عقارب الساعة (90 درجة هي الشرق الحقيقي). - تحدّد السمة
pitch(القيمة التلقائية0) تباين الزاوية "للأعلى" أو "للأسفل" من زاوية الميل التلقائية الأولية للكاميرا، والتي تكون غالبًا (ولكن ليس دائمًا) أفقية مستوية. (على سبيل المثال، من المرجّح أن تعرض صورة تم التقاطها على تلّ زاوية ميل تلقائية غير أفقية). يتم قياس زوايا الميل باستخدام قيم موجبة عند النظر إلى الأعلى (حتى 90 درجة للأعلى بشكل مستقيم وعمودي على الميل التلقائي) وقيم سالبة عند النظر إلى الأسفل (حتى 90 درجة للأسفل بشكل مستقيم وعمودي على الميل التلقائي).
يُستخدَم العنصر 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>تجربة عيّنة
تتبُّع الحركة على الأجهزة الجوّالة
على الأجهزة التي تتوافق مع أحداث اتجاه الجهاز، تتيح واجهة برمجة التطبيقات للمستخدمين إمكانية تغيير وجهة النظر في "التجوّل الافتراضي" استنادًا إلى حركة الجهاز. يمكن للمستخدمين استكشاف المحيط من خلال تحريك أجهزتهم. ويُعرف ذلك باسم تتبُّع الحركة أو تتبُّع دوران الجهاز.
بصفتك مطوّر تطبيقات، يمكنك تغيير السلوك التلقائي على النحو التالي:
- تفعيل وظيفة تتبُّع الحركة أو إيقافها يكون خيار تتبُّع الحركة مفعَّلاً تلقائيًا على أي جهاز يتوافق معه. يؤدي المثال التالي إلى إيقاف تتبُّع الحركة، ولكن مع إبقاء عنصر التحكّم في تتبُّع الحركة مرئيًا.
(يُرجى العِلم أنّه يمكن للمستخدم تفعيل ميزة "تتبُّع الحركة" من خلال النقر على عنصر التحكّم).
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 initMap() { // Request needed libraries. const { Map } = (await google.maps.importLibrary( 'maps' )) as google.maps.MapsLibrary; // Set the location of Astor Place. const astorPlace = { lat: 40.729884, lng: -73.990988 }; const mapElement = document.querySelector( 'gmp-map' ) as google.maps.MapElement; 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 const cafeMarker = new google.maps.Marker({ position: { lat: 40.730031, lng: -73.991428 }, map: innerMap, title: 'Cafe', icon: cafeIcon.src, }); const bankMarker = new google.maps.Marker({ position: { lat: 40.729681, lng: -73.991138 }, map: innerMap, title: 'Bank', icon: dollarIcon.src, }); const busMarker = new google.maps.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( /** @type {google.maps.StreetViewPov} */ { heading: 265, pitch: 0, } ); } function toggleStreetView(): void { const toggle = panorama.getVisible(); if (toggle == false) { panorama.setVisible(true); } else { panorama.setVisible(false); } } initMap();
JavaScript
let panorama; let innerMap; async function initMap() { // Request needed libraries. const { Map } = (await 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 const cafeMarker = new google.maps.Marker({ position: { lat: 40.730031, lng: -73.991428 }, map: innerMap, title: 'Cafe', icon: cafeIcon.src, }); const bankMarker = new google.maps.Marker({ position: { lat: 40.729681, lng: -73.991138 }, map: innerMap, title: 'Bank', icon: dollarIcon.src, }); const busMarker = new google.maps.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( /** @type {google.maps.StreetViewPov} */ { heading: 265, pitch: 0, }); } function toggleStreetView() { const toggle = panorama.getVisible(); if (toggle == false) { panorama.setVisible(true); } else { panorama.setVisible(false); } } initMap(); 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>
<!-- prettier-ignore -->
<script>(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: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</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 أو تعديل اتجاهها، قد تحتاج إلى تتبُّع عدة أحداث تشير إلى تغييرات في حالة StreetViewPanorama:
- يتم تشغيل
pano_changedكلما تغيّر رقم تعريف بانوراما فردية. لا يضمن هذا الحدث أنّ أي بيانات مرتبطة داخل الصورة البانورامية (مثل الروابط) قد تغيّرت أيضًا بحلول وقت تشغيل هذا الحدث، بل يشير هذا الحدث فقط إلى أنّه تم تغيير معرّف الصورة البانورامية. يُرجى العِلم أنّ معرّف الصورة البانورامية (الذي يمكنك استخدامه للإشارة إلى هذه الصورة البانورامية) يكون ثابتًا فقط خلال جلسة المتصفّح الحالية. - يتم تشغيل الحدث
position_changedكلما تغيّر موضعLatLngالأساسي للصورة البانورامية. لن يؤدي تدوير صورة بانورامية إلى تشغيل هذا الحدث. يُرجى العِلم أنّه يمكنك تغيير الموضع الأساسي لصورة بانورامية بدون تغيير رقم تعريف الصورة البانورامية المرتبط بها، لأنّ واجهة برمجة التطبيقات ستربط تلقائيًا رقم تعريف الصورة البانورامية الأقرب بموضع الصورة البانورامية. - يتم تشغيل الحدث
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"> </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"> </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". يمكنك تغيير مظهر عنصر التحكّم من خلال توفيرStreetViewAddressControlOptionsضمن الحقلaddressControlOptions. - يتيح
fullscreenControlخيار فتح "التجوّل الافتراضي" في وضع ملء الشاشة. يمكنك تغيير مظهر عنصر التحكّم من خلال توفيرFullscreenControlOptionsضمن الحقلfullscreenControlOptions. - تقدّم
motionTrackingControlخيار تفعيل ميزة تتبُّع الحركة أو إيقافها على الأجهزة الجوّالة. لا يظهر عنصر التحكّم هذا إلا على الأجهزة التي تتوافق مع أحداث اتجاه الجهاز. يظهر عنصر التحكّم تلقائيًا بالقرب من أسفل يسار الصورة البانورامية. يمكنك تغيير موضع عنصر التحكّم من خلال توفيرMotionTrackingControlOptions. لمزيد من المعلومات، اطّلِع على القسم الخاص بتتبُّع الحركة. - يوفر
linksControlأسهمًا إرشادية على الصورة للانتقال إلى صور بانورامية مجاورة. - يتيح عنصر التحكّم "إغلاق" للمستخدم إغلاق عارض "التجوّل الافتراضي". يمكنك تفعيل عنصر التحكّم "إغلاق" أو إيقافه من خلال ضبط
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>تجربة عيّنة
الوصول مباشرةً إلى بيانات "التجوّل الافتراضي"
قد تحتاج إلى تحديد مدى توفّر بيانات "التجوّل الافتراضي" آليًا، أو عرض معلومات حول صور بانورامية معيّنة، بدون الحاجة إلى التفاعل المباشر مع خريطة أو صورة بانورامية. يمكنك إجراء ذلك باستخدام عنصر StreetViewService الذي يوفّر واجهة للبيانات المخزّنة في خدمة "التجوّل الافتراضي" من Google.
طلبات الحصول على خدمات "التجوّل الافتراضي"
يتم الوصول إلى خدمة "التجوّل الافتراضي" بشكل غير متزامن، لأنّ Google Maps API تحتاج إلى إجراء طلب إلى خادم خارجي. لهذا السبب، عليك تمرير طريقة ردّ اتصال لتنفيذها عند اكتمال الطلب. تعالج طريقة رد الاتصال هذه النتيجة.
يمكنك بدء الطلبات إلى StreetViewService باستخدام
StreetViewPanoRequest أو
StreetViewLocationRequest.
يعرض الطلب الذي يستخدم StreetViewPanoRequest بيانات بانورامية
بناءً على معرّف مرجعي يحدّد البانوراما بشكل فريد. يُرجى العِلم أنّ معرّفات المراجع هذه تكون ثابتة فقط طوال فترة توفّر صور البانوراما.
يبحث طلب يستخدم StreetViewLocationRequest عن بيانات بانورامية في موقع جغرافي محدّد، وذلك باستخدام المَعلمات التالية:
- يحدّد
locationالموقع الجغرافي (خطوط الطول والعرض) الذي سيتم البحث فيه عن صورة بانورامية. - تحدّد السمة
preferenceخيارًا بشأن الصورة البانورامية التي يجب العثور عليها ضمن نصف القطر: الصورة الأقرب إلى الموقع الجغرافي المقدَّم، أو الصورة الأفضل ضمن نصف القطر. - يحدّد
radiusنصف قطر، محدّدًا بالأمتار، يتم البحث فيه عن صورة بانورامية، متمركزة على خط الطول وخط العرض المحدّدين. يتم ضبط القيمة التلقائية على 50 في حال عدم توفيرها. - تحدّد
sourceمصدر الصور البانورامية المطلوب البحث فيها. القيم الصالحة هي:- يستخدم
defaultالمصادر التلقائية لخدمة "التجوّل الافتراضي"، ولا تقتصر عمليات البحث على مصادر معيّنة. outdoorتحصر عمليات البحث على المجموعات الخارجية. يُرجى العِلم أنّه قد لا تتوفّر صور بانورامية خارجية للموقع الجغرافي المحدّد.
- يستخدم
ردود خدمة "التجوّل الافتراضي"
تحتاج الدالة getPanorama()
إلى دالة ردّ اتصال لتنفيذها عند استرداد نتيجة
من خدمة "التجوّل الافتراضي". تعرض دالة ردّ الاتصال هذه مجموعة من بيانات الصور البانورامية ضمن العنصر 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
بحد ذاته. لإنشاء عنصر "التجوّل الافتراضي" باستخدام هذه البيانات، عليك إنشاء 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.
توضّح الأقسام التالية هذه العملية.
إنشاء صور بانورامية مخصّصة
كل صورة بانورامية في "التجوّل الافتراضي" هي صورة أو مجموعة صور
توفّر عرضًا كاملاً بزاوية 360 درجة من موقع جغرافي واحد.
يستخدم العنصر StreetViewPanorama صورًا تتوافق مع الإسقاط المستطيل المتساوي المساحة (Plate Carrée). يحتوي هذا النوع من العرض على 360 درجة من العرض الأفقي (تغطية كاملة) و180 درجة من العرض العمودي (من الأعلى إلى الأسفل). تؤدي مجالات العرض هذه إلى إنشاء صورة بنسبة عرض إلى ارتفاع تبلغ 2:1. يظهر أدناه بانوراما كاملة بزاوية 360 درجة.

يتم الحصول على صور البانوراما بشكل عام من خلال التقاط صور متعددة من موضع واحد ودمجها معًا باستخدام برنامج بانوراما. (لمزيد من المعلومات، يُرجى الاطّلاع على مقالة مقارنة بين تطبيقات دمج الصور على ويكيبيديا). يجب أن تشترك هذه الصور في موضع "كاميرا" واحد، يتم منه التقاط كل صورة من الصور البانورامية. يمكن بعد ذلك تحديد إسقاط على كرة باستخدام الصورة البانورامية الناتجة بزاوية 360 درجة، مع لف الصورة على السطح الثنائي الأبعاد للكرة.

يُعدّ التعامل مع الصورة البانورامية كإسقاط على كرة باستخدام نظام إحداثيات مستقيم الزوايا مفيدًا عند تقسيم الصورة إلى مربّعات مستقيمة الزوايا وعرض الصور استنادًا إلى إحداثيات المربّعات المحسوبة.
إنشاء مربّعات بانورامية مخصّصة
يتيح "التجوّل الافتراضي" أيضًا مستويات مختلفة من تفاصيل الصور من خلال استخدام عنصر تحكّم في التكبير والتصغير، ما يتيح لك تكبير الصورة وتصغيرها من العرض التلقائي. بشكل عام، يوفّر "التجوّل الافتراضي" خمسة مستويات لدقة التكبير لأي صورة بانورامية. إذا كنت ستعتمد على صورة بانورامية واحدة لعرض جميع مستويات التكبير، سيكون حجم هذه الصورة كبيرًا جدًا، ما سيؤدي إلى تباطؤ تطبيقك بشكل كبير، أو ستكون دقتها منخفضة جدًا عند مستويات التكبير العالية، ما سيؤدي إلى عرض صورة منخفضة الدقة. لحسن الحظ، يمكننا استخدام نمط تصميم مشابه للنمط المستخدَم في عرض مربّعات خرائط Google بمستويات تكبير/تصغير مختلفة، وذلك لتوفير صور بانورامية بدرجة الدقة المناسبة لكل مستوى تكبير/تصغير.
عند تحميل StreetViewPanorama لأول مرة، يعرض تلقائيًا صورة تتألف من %25 (90 درجة من القوس) من العرض الأفقي للصورة البانورامية بمستوى التكبير 1. يتوافق هذا العرض
تقريبًا مع مجال الرؤية العادي لدى الإنسان. يؤدي التصغير "out" من هذا العرض التلقائي إلى توفير قوس أوسع، بينما يؤدي التكبير إلى تضييق مجال العرض إلى قوس أصغر. تحسب
StreetViewPanorama تلقائيًا
مجال الرؤية المناسب لمستوى التكبير المحدّد، ثم تختار
الصور الأكثر ملاءمةً لهذه الدقة من خلال اختيار مجموعة مربعات تتطابق تقريبًا مع أبعاد مجال الرؤية الأفقي. تتطابق مجالات الرؤية التالية مع مستويات التكبير أو التصغير في "التجوّل الافتراضي":
| مستوى التكبير أو التصغير في "التجوّل الافتراضي" | مجال الرؤية (بالدرجات) |
|---|---|
| 0 | 180 |
| 1 (افتراضي) | 90 |
| 2 | 45 |
| 3 | 22.5 |
| 4 | 11.25 |
يُرجى العِلم أنّ حجم الصورة المعروضة ضمن "التجوّل الافتراضي" يعتمد بشكل كامل على حجم شاشة (عرض) حاوية "التجوّل الافتراضي". إذا قدّمت حاوية أوسع، ستظل الخدمة توفّر مجال الرؤية نفسه لأي مستوى تكبير/تصغير معيّن، ولكنها قد تختار مربّعات أكثر ملاءمة لهذه الدقة بدلاً من ذلك.
بما أنّ كل صورة بانورامية تتألف من إسقاط مستطيل متساوي المساحة، فإنّ إنشاء مربّعات الصور البانورامية سهل نسبيًا. بما أنّ عملية العرض توفّر صورة بنسبة عرض إلى ارتفاع تبلغ 2:1، يسهل استخدام المربّعات التي تبلغ نسبة العرض إلى الارتفاع فيها 2:1، مع أنّ المربّعات المربعة قد تحقّق أداءً أفضل على الخرائط المربعة (لأنّ مجال الرؤية سيكون مربعًا).
بالنسبة إلى مربّعات 2:1، تمثّل صورة واحدة تشمل البانوراما بأكملها بانوراما "العالم" بأكمله (الصورة الأساسية) عند مستوى التكبير/التصغير 0، مع توفير كل مستوى تكبير/تصغير متزايد 4zoomLevel مربّع. (على سبيل المثال، عند مستوى التكبير/التصغير 2، تتألف الصورة البانورامية الكاملة من 16 مربّعًا). ملاحظة: لا تتطابق مستويات التكبير أو التصغير في تجانب "التجوّل الافتراضي" بشكل مباشر مع مستويات التكبير أو التصغير المتوفّرة باستخدام عنصر التحكّم في "التجوّل الافتراضي"، بل إنّ مستويات التكبير أو التصغير في عنصر التحكّم في "التجوّل الافتراضي" تختار "مجال رؤية"، يتم من خلاله اختيار التجانب المناسب.

بشكل عام، عليك تسمية مربّعات الصور حتى يمكن اختيارها آليًا. ويتم تناول نظام التسمية هذا أدناه في القسم التعامل مع طلبات Panorama المخصّصة.
التعامل مع طلبات الصور البانورامية المخصّصة
لاستخدام صورة بانورامية مخصّصة، استدعِ الدالة 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>