סמנים

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

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

דוגמאות קוד

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

Java

קוטלין

מבוא

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

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

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

תחילת העבודה עם סמנים

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

הוספת סמן

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

Java


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

      

Kotlin


override fun onMapReady(googleMap: GoogleMap) {
    // Add a marker in Sydney, Australia,
    // and move the map's camera to the same location.
    val sydney = LatLng(-33.852, 151.211)
    googleMap.addMarker(
        MarkerOptions()
            .position(sydney)
            .title("Marker in Sydney")
    )
    googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
}

      

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

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

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

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

Java


/**
 * A demo class that stores and retrieves data objects with each marker.
 */
public class MarkerDemoActivity extends AppCompatActivity implements
    GoogleMap.OnMarkerClickListener,
    OnMapReadyCallback {

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

    private Marker markerPerth;
    private Marker markerSydney;
    private Marker markerBrisbane;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_markers);
        SupportMapFragment mapFragment =
            (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    /** Called when the map is ready. */
    @Override
    public void onMapReady(GoogleMap map) {
        // Add some markers to the map, and add a data object to each marker.
        markerPerth = map.addMarker(new MarkerOptions()
            .position(PERTH)
            .title("Perth"));
        markerPerth.setTag(0);

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

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

        // Set a listener for marker click.
        map.setOnMarkerClickListener(this);
    }

    /** Called when the user clicks a marker. */
    @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(this,
                marker.getTitle() +
                    " has been clicked " + clickCount + " times.",
                Toast.LENGTH_SHORT).show();
        }

        // Return false to indicate that we have not consumed the event and that we wish
        // for the default behavior to occur (which is for the camera to move such that the
        // marker is centered and for the marker's info window to open, if it has one).
        return false;
    }
}

      

Kotlin


/**
 * A demo class that stores and retrieves data objects with each marker.
 */
class MarkerDemoActivity : AppCompatActivity(),
    OnMarkerClickListener, OnMapReadyCallback {
    private val PERTH = LatLng(-31.952854, 115.857342)
    private val SYDNEY = LatLng(-33.87365, 151.20689)
    private val BRISBANE = LatLng(-27.47093, 153.0235)

    private var markerPerth: Marker? = null
    private var markerSydney: Marker? = null
    private var markerBrisbane: Marker? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_markers)
        val mapFragment =
            supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
        mapFragment!!.getMapAsync(this)
    }

    /** Called when the map is ready.  */
    override fun onMapReady(map: GoogleMap) {
        // Add some markers to the map, and add a data object to each marker.
        markerPerth = map.addMarker(
            MarkerOptions()
                .position(PERTH)
                .title("Perth")
        )
        markerPerth?.tag = 0
        markerSydney = map.addMarker(
            MarkerOptions()
                .position(SYDNEY)
                .title("Sydney")
        )
        markerSydney?.tag = 0
        markerBrisbane = map.addMarker(
            MarkerOptions()
                .position(BRISBANE)
                .title("Brisbane")
        )
        markerBrisbane?.tag = 0

        // Set a listener for marker click.
        map.setOnMarkerClickListener(this)
    }

    /** Called when the user clicks a marker.  */
    override fun onMarkerClick(marker: Marker): Boolean {

        // 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(
                this,
                "${marker.title} has been clicked $newClickCount times.",
                Toast.LENGTH_SHORT
            ).show()
        }

        // Return false to indicate that we have not consumed the event and that we wish
        // for the default behavior to occur (which is for the camera to move such that the
        // marker is centered and for the marker's info window to open, if it has one).
        return false
    }
}

      

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

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

הגדרת סמן שניתן לגרור

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

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

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

Java


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

      

Kotlin


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

      

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

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

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

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

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

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

Java


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

      

Kotlin


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

      

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

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

Java


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

      

Kotlin


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

      

התאמה אישית של שקיפות השקיפות

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

Java


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

      

Kotlin


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

      

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

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

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

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

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

      

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))
)

      

שטח

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

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

Java


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

      

Kotlin


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

      

סיבוב של סמן

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

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

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

      

Kotlin


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

      

סמן Z-index

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

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

Java


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

      

Kotlin


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

      

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

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

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

ניהול אירועי סמן

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

אתם יכולים להאזין לאירועים הבאים:

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

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

ההשפעה של אינדקס z על אירועי קליקים:

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

אירועי גרירה של הסמן

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