מצלמה ותצוגה

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

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

דוגמאות קוד

המאגר ApiDemos ב-GitHub כולל דוגמה שממחישה את תכונות המצלמה:

מבוא

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

הערה: להיטל מרקטור יש רוחב סופי לאורך קו האורך, אבל גובה אינסופי לאורך קו הרוחב. אנחנו "חותכים" את התמונות של מפת הבסיס באמצעות היטל מרקטור בערך ב-85 מעלות +/- כדי ליצור מפה בצורת ריבוע, שמאפשרת לוגיקה קלה יותר לבחירת משבצות.

‫SDK של מפות ל-Android מאפשר לשנות את נקודת המבט של המשתמש במפה על ידי שינוי המצלמה של המפה.

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

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

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

מיקום המצלמה

תצוגת המפה מעוצבת כמצלמה שמשקיפה על מישור שטוח. מיקום המצלמה (ולכן גם הרינדור של המפה) נקבע לפי המאפיינים הבאים: target (מיקום קו רוחב/קו אורך), bearing, tilt ו-zoom.

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

טירגוט (מיקום)

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

קו הרוחב יכול להיות בין ‎-85 ל-85 מעלות, כולל. ערכים שגבוהים או נמוכים מהטווח הזה יוצמדו לערך הקרוב ביותר בטווח. לדוגמה, אם מציינים קו רוחב של 100, הערך שיוגדר יהיה 85. קו האורך נע בין ‎-180 ל-180 מעלות, כולל. ערכים שגבוהים מהטווח הזה או נמוכים ממנו יוגבלו כך שיהיו בטווח (‎-180, 180). לדוגמה, הערכים 480, 840 ו-1,200 יומרו ל-120 מעלות.

כיוון (אוריינטציה)

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

כיוון של 0 פירושו שהחלק העליון של המפה מצביע לכיוון צפון אמיתי. ערך הכיוון 90 מציין שחלקו העליון של המפה מצביע מזרחה (90 מעלות במצפן). הערך 180 מציין שהחלק העליון של המפה פונה לכיוון דרום.

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

הטיה (זווית צפייה)

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

בתמונות הבאות, זווית הצפייה היא 0 מעלות. בתמונה הראשונה מוצג תרשים של המצב הזה: מיקום 1 הוא מיקום המצלמה, ומיקום 2 הוא המיקום הנוכחי במפה. המפה שנוצרה מוצגת מתחתיו.

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

בתמונות שלמטה, זווית הצפייה היא 45 מעלות. שימו לב שהמצלמה זזה לאורך חצי קשת בין נקודה ישרה מעל הראש (0 מעלות) לבין הקרקע (90 מעלות), כדי להגיע למיקום 3. המצלמה עדיין מכוונת לנקודת המרכז של המפה, אבל עכשיו אפשר לראות את האזור שמיוצג על ידי הקו במיקום 4.

צילום מסך של מפה עם מצלמה בזווית צפייה של 45 מעלות, ברמת זום של 18.
המפה מוצגת בזווית צפייה של 45 מעלות.
תרשים שמראה את זווית הצפייה של המצלמה מוגדרת ל-45 מעלות, ורמת הזום עדיין מוגדרת ל-18.
זווית צפייה של 45 מעלות במצלמה.

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

Zoom

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

הגדלת רמת הזום ב-1 מכפילה את רוחב העולם במסך. לכן, ברמת זום N, רוחב העולם הוא בערך 256 * 2N dp. לדוגמה, ברמת זום 2, הרוחב של העולם כולו הוא בערך 1024dp.

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

  • ‫1: העולם
  • ‫5: מסת יבשה/יבשת
  • ‫10: עיר
  • ‫15: רחובות
  • ‫20: מבנים
בתמונות הבאות אפשר לראות את המראה החזותי של רמות זום שונות:
צילום מסך של מפה ברמת זום 5
מפה ברמת זום 5.
צילום מסך של מפה ברמת זום של 15
מפה ברמת זום 15.
צילום מסך של מפה ברמת זום 20
מפה ברמת זום 20.

הזזת המצלמה

באמצעות Maps API אפשר לשנות את החלק בעולם שמוצג במפה. השינוי מתבצע על ידי שינוי המיקום של המצלמה (בניגוד להזזת המפה).

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

כדי לשנות את מיקום המצלמה, צריך לציין לאן רוצים להזיז אותה באמצעות CameraUpdate. ‫Maps API מאפשר ליצור סוגים רבים ושונים של CameraUpdate באמצעות CameraUpdateFactory. אלה האפשרויות הזמינות:

שינוי רמת הזום והגדרת זום מינימלי/מקסימלי

‫CameraUpdateFactory.zoomIn() ו-CameraUpdateFactory.zoomOut() מחזירים CameraUpdate שמשנה את רמת הזום ב-1.0, ושומר על כל שאר המאפיינים ללא שינוי.

‫CameraUpdateFactory.zoomTo(float) נותן לכם CameraUpdate שמשנה את רמת הזום לערך שצוין, בלי לשנות את שאר המאפיינים.

‫CameraUpdateFactory.zoomBy(float) ו-CameraUpdateFactory.zoomBy(float, Point) נותנים CameraUpdate שמגדיל (או מקטין, אם הערך שלילי) את רמת הזום לפי הערך שצוין. האפשרות השנייה מקבעת את הנקודה שצוינה במסך כך שהיא תישאר באותו מיקום (קו רוחב/קו אורך), ולכן יכול להיות שהיא תשנה את המיקום של המצלמה כדי להשיג את זה.

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

Kotlin

map.setMinZoomPreference(6.0f)
map.setMaxZoomPreference(14.0f)

      

Java

map.setMinZoomPreference(6.0f);
map.setMaxZoomPreference(14.0f);

      

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

שינוי מיקום המצלמה

יש שתי שיטות נוחות לשינוי המיקום. CameraUpdateFactory.newLatLng(LatLng) מחזיר CameraUpdate שמשנה את קו הרוחב וקו האורך של המצלמה, תוך שמירה על כל המאפיינים האחרים. CameraUpdateFactory.newLatLngZoom(LatLng, float) מחזיר CameraUpdate שמשנה את קו הרוחב, קו האורך והזום של המצלמה, תוך שמירה על כל שאר המאפיינים.

כדי לשנות את מיקום המצלמה בצורה הכי גמישה, משתמשים ב-CameraUpdateFactory.newCameraPosition(CameraPosition), שנותן CameraUpdate שמזיז את המצלמה למיקום שצוין. אפשר לקבל CameraPosition ישירות באמצעות new CameraPosition() או באמצעות CameraPosition.Builder באמצעות new CameraPosition.Builder().

הזזה (גלילה)

‫CameraUpdateFactory.scrollBy(float, float) יוצר CameraUpdate שמשנה את קו הרוחב וקו האורך של המצלמה כך שהמפה זזה במספר הפיקסלים שצוין. ערך חיובי של x גורם למצלמה לזוז ימינה, כך שנראה שהמפה זזה שמאלה. ערך חיובי של y גורם למצלמה לנוע למטה, כך שנראה שהמפה נעה למעלה. לעומת זאת, ערכי x שליליים גורמים למצלמה לזוז שמאלה, כך שנראה שהמפה זזה ימינה, וערכי y שליליים גורמים למצלמה לזוז למעלה. הגלילה היא יחסית לכיוון הנוכחי של המצלמה. לדוגמה, אם למצלמה יש כיוון של 90 מעלות, אז מזרח הוא "למעלה".

הגדרת גבולות

הגדרת גבולות המפה

לפעמים כדאי להזיז את המצלמה כך שכל האזור הרצוי יהיה גלוי ברמת הזום הגבוהה ביותר. לדוגמה, אם אתם מציגים את כל תחנות הדלק ברדיוס של 8 ק"מ מהמיקום הנוכחי של המשתמש, יכול להיות שתרצו להזיז את המצלמה כך שכולן יהיו גלויות על המסך. כדי לעשות את זה, קודם מחשבים את LatLngBounds שרוצים שיוצג על המסך. אחר כך אפשר להשתמש ב-CameraUpdateFactory.newLatLngBounds(LatLngBounds bounds, int padding) כדי לקבל CameraUpdate שמשנה את מיקום המצלמה כך ש-LatLngBounds הנתון יתאים כולו למפה, תוך התחשבות בשוליים (בפיקסלים) שצוינו. הערך המוחזר CameraUpdate מבטיח שהמרווח (בפיקסלים) בין הגבולות שצוינו לבין קצה המפה יהיה לפחות כמו הריווח שצוין. שימו לב שההטיה והכיוון של המפה יהיו 0.

Kotlin

val australiaBounds = LatLngBounds(
    LatLng((-44.0), 113.0),  // SW bounds
    LatLng((-10.0), 154.0) // NE bounds
)
map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0))

      

Java

LatLngBounds australiaBounds = new LatLngBounds(
        new LatLng(-44, 113), // SW bounds
        new LatLng(-10, 154)  // NE bounds
);
map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0));

      

מרכוז המפה באזור מסוים

במקרים מסוימים, יכול להיות שתרצו למרכז את המצלמה בתוך גבולות מסוימים במקום לכלול את הגבולות הקיצוניים. לדוגמה, כדי למרכז את המצלמה על מדינה מסוימת תוך שמירה על זום קבוע. במקרה כזה, אפשר להשתמש בשיטה דומה: יוצרים LatLngBounds ומשתמשים ב-CameraUpdateFactory.newLatLngZoom(LatLng latLng, float zoom) עם LatLngBounds.שיטה אחת (getCenter()). השיטה getCenter()‎ תחזיר את המרכז הגיאוגרפי של LatLngBounds.

Kotlin

val australiaBounds = LatLngBounds(
    LatLng((-44.0), 113.0),  // SW bounds
    LatLng((-10.0), 154.0) // NE bounds
)
map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.center, 10f))

      

Java

LatLngBounds australiaBounds = new LatLngBounds(
        new LatLng(-44, 113), // SW bounds
        new LatLng(-10, 154)  // NE bounds
);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.getCenter(), 10));

      

עומס יתר של השיטה, newLatLngBounds(boundary, width, height, padding), מאפשר לציין רוחב וגובה בפיקסלים למלבן, במטרה שהם יתאימו לממדי המפה. המיקום של המלבן הוא כזה שהמרכז שלו זהה למרכז של אזור התצוגה במפה (כך שאם המידות שצוינו זהות למידות של אזור התצוגה במפה, המלבן חופף לאזור התצוגה במפה). האובייקט CameraUpdate שמוחזר יזיז את המצלמה כך שהאובייקטים שצוינו ב-LatLngBounds יופיעו במרכז המסך בתוך המלבן הנתון ברמת הזום הגבוהה ביותר האפשרית, תוך התחשבות במרווח הפנימי הנדרש.

הערה: השתמשו בשיטה הפשוטה יותר newLatLngBounds(boundary, padding) כדי ליצור CameraUpdate רק אם היא תשמש להזזת המצלמה אחרי שהמפה עברה פריסה. במהלך הפריסה, ה-API מחשב את גבולות התצוגה של המפה שנדרשים כדי להקרין בצורה נכונה את התיבה התוחמת. לעומת זאת, אתם יכולים להשתמש ב-CameraUpdate שמוחזר על ידי השיטה המורכבת יותר newLatLngBounds(boundary, width, height, padding) בכל שלב, אפילו לפני שהמפה עברה פריסה, כי ה-API מחשב את גבולות התצוגה מהארגומנטים שאתם מעבירים.

הגבלת ההזזה של המשתמש לאזור נתון

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

Kotlin

// Create a LatLngBounds that includes the city of Adelaide in Australia.
val adelaideBounds = LatLngBounds(
    LatLng(-35.0, 138.58),  // SW bounds
    LatLng(-34.9, 138.61) // NE bounds
)

// Constrain the camera target to the Adelaide bounds.
map.setLatLngBoundsForCameraTarget(adelaideBounds)

      

Java

// Create a LatLngBounds that includes the city of Adelaide in Australia.
LatLngBounds adelaideBounds = new LatLngBounds(
        new LatLng(-35.0, 138.58), // SW bounds
        new LatLng(-34.9, 138.61)  // NE bounds
);

// Constrain the camera target to the Adelaide bounds.
map.setLatLngBoundsForCameraTarget(adelaideBounds);

      

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

תרשים שמציג את LatLngBounds של המצלמה, שגדול יותר מאזור התצוגה.

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

דיאגרמה שמראה את יעד המצלמה בפינה הימנית התחתונה של LatLngBounds של המצלמה.

בתרשים הבא, למטרת המצלמה יש גבולות מוגבלים מאוד, ולכן למשתמש יש מעט מאוד אפשרויות לגלול או להזיז את המפה. הצלב מייצג את המטרה של המצלמה:

תרשים שמציג את LatLngBounds של המצלמה, שקטן יותר מאזור התצוגה.

עדכון השידור מהמצלמה

כדי להחיל CameraUpdate על המפה, אתם יכולים להזיז את המצלמה באופן מיידי או להנפיש את המצלמה בצורה חלקה. כדי להזיז את המצלמה באופן מיידי באמצעות CameraUpdate, אפשר להפעיל את GoogleMap.moveCamera(CameraUpdate).

כדי לשפר את חוויית המשתמש, במיוחד בתנועות קצרות, אפשר להוסיף אנימציה לשינוי. כדי לעשות זאת במקום להתקשר אל GoogleMap.moveCamera מתקשרים אל GoogleMap.animateCamera. המפה תעבור בצורה חלקה למאפיינים החדשים. הצורה המפורטת ביותר של השיטה הזו,‏ GoogleMap.animateCamera(cameraUpdate, duration, callback),‏ כוללת שלושה ארגומנטים:

cameraUpdate
ההנחיה CameraUpdate שמתארת לאן להזיז את המצלמה.
callback
‫
אובייקט שמטמיע את GoogleMap.CancellableCallback. הממשק הכללי הזה לטיפול במשימות מגדיר שתי שיטות: `onCancel()‎` ו-`onFinished()‎`. באנימציה, השיטות נקראות בנסיבות הבאות:
onFinish()
מופעל אם האנימציה מסתיימת בלי הפרעה.
onCancel()

מופעל אם האנימציה מופסקת על ידי קריאה ל-stopAnimation() או הפעלה של תנועת מצלמה חדשה.

השגיאה יכולה להופיע גם אם קוראים ל-GoogleMap.stopAnimation().

duration
משך הזמן הרצוי של האנימציה, באלפיות השנייה, בתור int.

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

Kotlin

val sydney = LatLng(-33.88, 151.21)
val mountainView = LatLng(37.4, -122.1)

// Move the camera instantly to Sydney with a zoom of 15.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15f))

// Zoom in, animating the camera.
map.animateCamera(CameraUpdateFactory.zoomIn())

// Zoom out to zoom level 10, animating with a duration of 2 seconds.
map.animateCamera(CameraUpdateFactory.zoomTo(10f), 2000, null)

// Construct a CameraPosition focusing on Mountain View and animate the camera to that position.
val cameraPosition = CameraPosition.Builder()
    .target(mountainView) // Sets the center of the map to Mountain View
    .zoom(17f)            // Sets the zoom
    .bearing(90f)         // Sets the orientation of the camera to east
    .tilt(30f)            // Sets the tilt of the camera to 30 degrees
    .build()              // Creates a CameraPosition from the builder
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))

      

Java

LatLng sydney = new LatLng(-33.88, 151.21);
LatLng mountainView = new LatLng(37.4, -122.1);

// Move the camera instantly to Sydney with a zoom of 15.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15));

// Zoom in, animating the camera.
map.animateCamera(CameraUpdateFactory.zoomIn());

// Zoom out to zoom level 10, animating with a duration of 2 seconds.
map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);

// Construct a CameraPosition focusing on Mountain View and animate the camera to that position.
CameraPosition cameraPosition = new CameraPosition.Builder()
        .target(mountainView)      // Sets the center of the map to Mountain View
        .zoom(17)                   // Sets the zoom
        .bearing(90)                // Sets the orientation of the camera to east
        .tilt(30)                   // Sets the tilt of the camera to 30 degrees
        .build();                   // Creates a CameraPosition from the builder
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));