מצלמה ותצוגה

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

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

דוגמאות קוד

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

מבוא

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

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

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

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

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

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

מיקום המצלמה

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

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

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

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

קו הרוחב יכול להיות בין ‎-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, הרוחב של העולם כולו הוא בערך 1,024dp.

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

  • ‫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));