סמנים

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

מפה עם כמה סמנים

סמנים מזהים מיקומים במפה. סמן ברירת המחדל משתמש בסמל סטנדרטי, שמתאים למראה ולתחושה של מפות Google. אפשר לשנות את הצבע, התמונה או נקודת העיגון של הסמל באמצעות ה-API. סמנים הם אובייקטים מסוג Marker, והם מתווספים למפה באמצעות השיטה GoogleMap.addMarker(markerOptions).

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

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

הוסף סמן

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

Kotlin

// Add a marker in Sydney, Australia,
// and move the map's camera to the same location.
val sydney = LatLng(-33.852, 151.211)
val marker = map.addMarker(
    MarkerOptions()
        .position(sydney)
        .title("Marker in Sydney")
)
marker?.let {
    val position = it.position
    val title = it.title
    val snippet = it.snippet
    val isDraggable = it.isDraggable
    val isFlat = it.isFlat
    val isVisible = it.isVisible
    val alpha = it.alpha
    val rotation = it.rotation
    val zIndex = it.zIndex
}
map.moveCamera(CameraUpdateFactory.newLatLng(sydney))

      

Java

// Add a marker in Sydney, Australia,
// and move the map's camera to the same location.
LatLng sydney = new LatLng(-33.852, 151.211);
Marker marker = map.addMarker(new MarkerOptions()
    .position(sydney)
    .title("Marker in Sydney"));
map.moveCamera(CameraUpdateFactory.newLatLng(sydney));

      

הצגת מידע נוסף על סמן

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

שיוך נתונים לסמן

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

Kotlin

val PERTH = LatLng(-31.952854, 115.857342)
val SYDNEY = LatLng(-33.87365, 151.20689)
val BRISBANE = LatLng(-27.47093, 153.0235)

val markerPerth = map.addMarker(
    MarkerOptions()
        .position(PERTH)
        .title("Perth")
)
markerPerth?.tag = 0

val markerSydney = map.addMarker(
    MarkerOptions()
        .position(SYDNEY)
        .title("Sydney")
)
markerSydney?.tag = 0

val markerBrisbane = map.addMarker(
    MarkerOptions()
        .position(BRISBANE)
        .title("Brisbane")
)
markerBrisbane?.tag = 0

// Set a listener for marker click.
map.setOnMarkerClickListener { marker ->
    // Retrieve the data from the marker.
    val clickCount = marker.tag as? Int

    // Check if a click count was set, then display the click count.
    clickCount?.let {
        val newClickCount = it + 1
        marker.tag = newClickCount
        Toast.makeText(
            context,
            "${marker.title} has been clicked $newClickCount times.",
            Toast.LENGTH_SHORT
        ).show()
    }

    // Return false to indicate default behavior.
    false
}

      

Java

final LatLng PERTH = new LatLng(-31.952854, 115.857342);
final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
final LatLng BRISBANE = new LatLng(-27.47093, 153.0235);

Marker markerPerth = map.addMarker(new MarkerOptions()
    .position(PERTH)
    .title("Perth"));
markerPerth.setTag(0);

Marker markerSydney = map.addMarker(new MarkerOptions()
    .position(SYDNEY)
    .title("Sydney"));
markerSydney.setTag(0);

Marker markerBrisbane = map.addMarker(new MarkerOptions()
    .position(BRISBANE)
    .title("Brisbane"));
markerBrisbane.setTag(0);

// Set a listener for marker click.
map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
    @Override
    public boolean onMarkerClick(final Marker marker) {
        // Retrieve the data from the marker.
        Integer clickCount = (Integer) marker.getTag();

        // Check if a click count was set, then display the click count.
        if (clickCount != null) {
            clickCount = clickCount + 1;
            marker.setTag(clickCount);
            Toast.makeText(context,
                marker.getTitle() + " has been clicked " + clickCount + " times.",
                Toast.LENGTH_SHORT).show();
        }

        // Return false to indicate default behavior should occur.
        return false;
    }
});

      

ריכזנו כאן כמה דוגמאות לתרחישים שבהם כדאי לאחסן ולאחזר נתונים באמצעות סמנים:

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

הפיכת סמן לניתן לגרירה

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

כברירת מחדל, אי אפשר לגרור את הסמנים. צריך להגדיר במפורש שהסמן ניתן לגרירה, באמצעות MarkerOptions.draggable(boolean) לפני שמוסיפים אותו למפה, או באמצעות Marker.setDraggable(boolean) אחרי שמוסיפים אותו למפה. אפשר להאזין לאירועי גרירה של הסמן, כמו שמתואר במאמר אירועי גרירה של סמן.

קטע הקוד הבא מוסיף סמן שניתן לגרירה בפרת', אוסטרליה.

Kotlin

val perthLocation = LatLng(-31.90, 115.86)
val perth = map.addMarker(
    MarkerOptions()
        .position(perthLocation)
        .draggable(true)
)
map.moveCamera(com.google.android.gms.maps.CameraUpdateFactory.newLatLngZoom(perthLocation, 10f))

      

Java

final LatLng perthLocation = new LatLng(-31.90, 115.86);
Marker perth = map.addMarker(
    new MarkerOptions()
        .position(perthLocation)
        .draggable(true));
map.moveCamera(com.google.android.gms.maps.CameraUpdateFactory.newLatLngZoom(perthLocation, 10f));

      

התאמה אישית של סמן

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

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

אפשר להתאים אישית סמנים באמצעות המאפיינים הבאים:

מיקום (חובה)
הערך של LatLng למיקום של הסמן במפה. זוהי המאפיין היחיד שנדרש לאובייקט Marker.
עוגן
הנקודה בתמונה שתמוקם במיקום LatLng של הסמן. ברירת המחדל היא באמצע החלק התחתון של התמונה.
אלפא
ההגדרה הזו קובעת את רמת האטימות של הסמן. ברירת המחדל היא 1.0.
כותרת
מחרוזת שמוצגת בחלון המידע כשהמשתמש מקיש על הסמן.
קטע טקסט
טקסט נוסף שמוצג מתחת לכותרת.
סמל
מפת סיביות (bitmap) שמוצגת במקום תמונת הסמן שמוגדרת כברירת מחדל.
ניתן לגרירה
מגדירים את הערך true אם רוצים לאפשר למשתמש להזיז את הסמן. ברירת המחדל היא false.
גלוי
מגדירים את הערך false כדי להסתיר את הסמן. ברירת המחדל היא true.
כיוון שטוח או כיוון של שלט חוצות
כברירת מחדל, הסמנים מוצגים בכיוון של שלט חוצות, כלומר הם משורטטים בכיוון של מסך המכשיר ולא בכיוון של פני השטח של המפה. סיבוב, הטיה או שינוי מרחק התצוגה של המפה לא משנים את הכיוון של הסמן. אפשר להגדיר את הכיוון של סמן כך שיהיה שטוח על פני כדור הארץ. סמנים שטוחים מסתובבים כשמסובבים את המפה, ומשנים את הפרספקטיבה כשמטים את המפה. בדומה לסמני שלטי חוצות, סמנים שטוחים שומרים על הגודל שלהם כשמגדילים או מקטינים את התצוגה של המפה.
סיבוב
הכיוון של הסמן, מצוין במעלות בכיוון השעון. מיקום ברירת המחדל משתנה אם הסמן שטוח. מיקום ברירת המחדל של סמן שטוח הוא צפון. אם הסמן לא שטוח, מיקום ברירת המחדל הוא כלפי מעלה והסיבוב הוא כזה שהסמן תמיד פונה אל המצלמה.

קטע הקוד שלמטה יוצר סמן פשוט עם סמל ברירת המחדל.

Kotlin

val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
)

      

Java

final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(
    new MarkerOptions()
        .position(melbourneLocation));

      

התאמה אישית של צבע הסמן

אפשר להתאים אישית את הצבע של תמונת ברירת המחדל של הסמן על ידי העברת אובייקט BitmapDescriptor ל-method‏()icon. אתם יכולים להשתמש בקבוצה של צבעים מוגדרים מראש באובייקט BitmapDescriptorFactory, או להגדיר צבע סמן בהתאמה אישית באמצעות השיטה BitmapDescriptorFactory.defaultMarker(float hue). הגוון הוא ערך בין 0 ל-360, שמייצג נקודות בגלגל הצבעים.

Kotlin

val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
)

      

Java

final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(
    new MarkerOptions()
        .position(melbourneLocation)
        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));

      

התאמה אישית של אטימות הסמן

אתם יכולים לשלוט באטימות של סמן באמצעות השיטה MarkerOptions.alpha()‎. ערך האלפא צריך להיות מספר עשרוני בין 0.0 ל-1.0, כאשר 0 הוא שקוף לחלוטין ו-1 הוא אטום לחלוטין.

Kotlin

val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
        .alpha(0.7f)
)

      

Java

final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(new MarkerOptions()
    .position(melbourneLocation)
    .alpha(0.7f));

      

התאמה אישית של תמונת הסמן

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

fromAsset(String assetName)
יוצר סמן בהתאמה אישית באמצעות השם של תמונת Bitmap בספריית הנכסים.
fromBitmap(Bitmap image)
יוצר סמן בהתאמה אישית מתמונת Bitmap.
fromFile(String fileName)
יוצר סמל בהתאמה אישית באמצעות השם של קובץ תמונה מסוג Bitmap שנמצא באחסון הפנימי.
fromPath(String absolutePath)
יוצר סמן בהתאמה אישית מנתיב קובץ מוחלט של תמונת Bitmap.
fromResource(int resourceId)
יוצרת סמן בהתאמה אישית באמצעות מזהה המשאב של תמונת Bitmap.

בקטע הקוד שבהמשך נוצר סמן עם סמל מותאם אישית.

Kotlin

val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
        .title("Melbourne")
        .snippet("Population: 4,137,400")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow))
)

      

Java

final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(
    new MarkerOptions()
        .position(melbourneLocation)
        .title("Melbourne")
        .snippet("Population: 4,137,400")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));

      

איך משטחים סמן

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

כדי לשנות את הכיוון של הסמן, מגדירים את המאפיין flat של הסמן לערך true.

Kotlin

val perthLocation = LatLng(-31.90, 115.86)
val perth = map.addMarker(
    MarkerOptions()
        .position(perthLocation)
        .flat(true)
)

      

Java

final LatLng perthLocation = new LatLng(-31.90, 115.86);
Marker perth = map.addMarker(
    new MarkerOptions()
        .position(perthLocation)
        .flat(true));

      

סיבוב של סמן

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

בדוגמה הבאה, הסמן מסתובב ב-90 מעלות. הגדרת נקודת העיגון ל-0.5,0.5 גורמת לסמן להסתובב סביב המרכז שלו, ולא סביב הבסיס שלו.

Kotlin

val perthLocation = LatLng(-31.90, 115.86)
val perth = map.addMarker(
    MarkerOptions()
        .position(perthLocation)
        .anchor(0.5f, 0.5f)
        .rotation(90.0f)
)

      

Java

final LatLng perthLocation = new LatLng(-31.90, 115.86);
Marker perth = map.addMarker(
    new MarkerOptions()
        .position(perthLocation)
        .anchor(0.5f,0.5f)
        .rotation(90.0f));

      

אינדקס Z של הסמן

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

מגדירים את ה-z-index באובייקט האפשרויות של הסמן באמצעות קריאה ל-MarkerOptions.zIndex(), כמו שמוצג בקטע הקוד הבא:

Kotlin

map.addMarker(
    MarkerOptions()
        .position(LatLng(10.0, 10.0))
        .title("Marker z1")
        .zIndex(1.0f)
)

      

Java

map.addMarker(new MarkerOptions()
    .position(new LatLng(10, 10))
    .title("Marker z1")
    .zIndex(1.0f));

      

כדי לגשת ל-z-index של הסמן, אפשר להפעיל את Marker.getZIndex(), וכדי לשנות אותו אפשר להפעיל את Marker.setZIndex().

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

בהמשך המאמר מוסבר על ההשפעה של z-index על אירועי קליקים.

טיפול באירועים של סמנים

‫Maps API מאפשר להאזין לאירועים של סמנים ולהגיב להם. כדי להאזין לאירועים האלה, צריך להגדיר את ה-listener המתאים באובייקט GoogleMap שאליו שייכים הסמנים. כשהאירוע מתרחש באחד מהסמנים במפה, הקריאה החוזרת של המאזין תופעל עם אובייקט Marker המתאים שמועבר כפרמטר. כדי להשוות את האובייקט Marker הזה להפניה שלכם לאובייקט Marker, צריך להשתמש ב-equals() ולא ב-==.

אפשר להאזין לאירועים הבאים:

אירועים מסוג קליק על סמן

אפשר להשתמש ב-OnMarkerClickListener כדי להאזין לאירועים מסוג קליק על הסמן. כדי להגדיר את המאזין הזה במפה, קוראים ל-GoogleMap.setOnMarkerClickListener(OnMarkerClickListener). כשמשתמש לוחץ על סמן, הפונקציה onMarkerClick(Marker) נקראת והסמן מועבר כארגומנט. השיטה הזו מחזירה ערך בוליאני שמציין אם השתמשתם באירוע (כלומר, אתם רוצים לבטל את פעולת ברירת המחדל). אם הפונקציה מחזירה false, ההתנהגות שמוגדרת כברירת מחדל תתרחש בנוסף להתנהגות המותאמת אישית. פעולת ברירת המחדל של אירוע מסוג קליק על סמן היא להציג את חלון המידע שלו (אם הוא זמין) ולהזיז את המצלמה כך שהסמן יהיה במרכז המפה.

ההשפעה של z-index על אירועי מסוג קליק:

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

אירועי גרירה של סמנים

אפשר להשתמש ב-OnMarkerDragListener כדי להאזין לאירועי גרירה של סמן. כדי להגדיר את המאזין הזה במפה, קוראים ל-GoogleMap.setOnMarkerDragListener. כדי לגרור סמן, המשתמש צריך ללחוץ עליו לחיצה ארוכה. כשהמשתמש מסיר את האצבע מהמסך, הסמן נשאר במיקום הזה. כשגוררים סמן, מתבצעת קריאה ראשונית ל-onMarkerDragStart(Marker). בזמן שגוררים את הסמן, מתבצעת קריאה קבועה ל-onMarkerDrag(Marker). בסיום הגרירה, הפונקציה onMarkerDragEnd(Marker) מופעלת. אפשר לקבל את המיקום של הסמן בכל שלב על ידי קריאה ל-Marker.getPosition().