Markers

اختَر النظام الأساسي: Android iOS JavaScript

تشير العلامات إلى مواقع فردية على الخريطة. يمكنك تخصيص علاماتك عن طريق تغيير اللون الافتراضي أو استبدال رمز العلامة بصورة مخصصة. يمكن أن توفّر نوافذ المعلومات سياقًا إضافيًا للعلامة.

عيّنات تعليمات برمجية

يتضمن مستودع ApiDemos على GitHub نموذجًا يوضح ميزات العلامات المختلفة:

Java

Kotlin

المقدمة

تحدد العلامات المواقع على الخريطة. تستخدم العلامة الافتراضية رمزًا قياسيًا، شائعًا في شكل ومظهر خرائط Google. من الممكن تغيير لون الأيقونة أو صورتها أو نقطة ارتساءها عبر واجهة برمجة التطبيقات. العلامات هي كائنات من نوع Marker، وتتم إضافتها إلى الخريطة باستخدام طريقة GoogleMap.addMarker(markerOptions).

تم تصميم العلامات بحيث تكون تفاعلية. تتلقّى أحداث click تلقائيًا، وغالبًا ما يتم استخدامها مع أدوات معالجة الأحداث لعرض نوافذ المعلومات. يؤدي ضبط سمة draggable للعلامة على true إلى السماح للمستخدم بتغيير موضع العلامة. استخدم ضغطة طويلة لتنشيط القدرة على تحريك العلامة.

بشكل تلقائي، عندما ينقر مستخدم على علامة، يظهر شريط أدوات الخريطة في الجزء السفلي الأيسر من الخريطة، مما يتيح للمستخدم الوصول السريع إلى تطبيق خرائط Google للجوّال. يمكنك إيقاف شريط الأدوات. لمزيد من المعلومات، راجِع دليل عناصر التحكّم.

الخطوات الأولى لاستخدام العلامات

تتناول هذه الحلقة من بث مباشر على الخرائط أساسيات إضافة علامات إلى خريطتك باستخدام حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط 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.
مرساة
النقطة على الصورة التي سيتم وضعها في موضع خط الطول والعرض للعلامة. وهذا هو الخيار التلقائي في منتصف الجزء السفلي من الصورة.
إصدار أولي
لتعيين درجة تعتيم العلامة. يكون الإعداد التلقائي بالقيمة 1.0.
العنوان
سلسلة يتم عرضها في نافذة المعلومات عندما ينقر المستخدم على العلامة.
المقتطف
نص إضافي يتم عرضه أسفل العنوان.
الرمز
صورة نقطية يتم عرضها بدلاً من صورة محدّد الموقع التلقائية
قابلة للسحب
اضبط القيمة على true إذا كنت تريد السماح للمستخدم بنقل العلامة. يكون الإعداد التلقائي بالقيمة false.
مرئي
اضبط العلامة على false لجعل العلامة غير مرئية. وتكون القيمة التلقائية true.
اتجاه مسطّح أو اتجاه لوحة الإعلانات
تستخدم العلامات بشكل تلقائي اتجاه لوحة الإعلانات، ما يعني أنها مرسومة على شاشة الجهاز بدلاً من وضعها على سطح الخريطة. لا يؤدي تدوير الخريطة أو إمالتها أو تكبيرها/تصغيرها إلى تغيير اتجاه العلامة. يمكنك تعيين اتجاه العلامة ليكون مستويًا على الأرض. يتم تدوير العلامات المسطحة عند تدوير الخريطة، وتغيير المنظور عند إمالة الخريطة. كما هو الحال مع محددات لوحة الإعلانات، تحتفظ العلامات المسطحة بحجمها عند تكبير الخريطة أو تصغيرها.
تدوير
اتجاه العلامة، محدد بالدرجات في اتجاه عقارب الساعة. يتغير الموضع التلقائي إذا كان محدِّد الموقع مسطحًا. الموضع التلقائي للعلامة المسطحة هو المحاذاة إلى الشمال. عندما تكون العلامة غير مسطحة، يكون الوضع التلقائي يشير إلى الأعلى ويكون التدوير بشكل يجعل العلامة موجَّهة دائمًا للكاميرا.

ينشئ المقتطف أدناه علامة بسيطة، باستخدام الرمز التلقائي.

لغة 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))
)

      

تخصيص درجة تعتيم العلامة

يمكنك التحكم في تعتيم العلامة باستخدام طريقة MarkerOptions.alpha(). يجب تحديد ألفا على أنه عدد عائم بين 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)
لإنشاء رمز مخصص باستخدام اسم ملف صورة نقطية موجود في وحدة التخزين الداخلية.
fromPath(String absolutePath)
لإنشاء علامة مخصّصة من مسار ملف مطلق لصورة نقطية.
fromResource(int resourceId)
لإنشاء علامة مخصّصة باستخدام رقم تعريف المورد لصورة الصورة النقطية.

ينشئ المقتطف أدناه علامة عليها رمز مخصّص.

لغة 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 للعلامة

يحدد فهرس z ترتيب تكديس هذه العلامة، بالنسبة إلى العلامات الأخرى على الخريطة. يتم رسم علامة ذات مؤشر 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 منفصلة مقارنةً بالتراكبات الأخرى.

يمكنك الاطّلاع على مزيد من المعلومات عن تأثير مؤشر z على أحداث النقر أدناه.

التعامل مع أحداث محدّد الموقع

تتيح لك واجهة برمجة تطبيقات الخرائط الاستماع إلى أحداث العلامات والاستجابة لها. للاستماع إلى هذه الأحداث، عليك ضبط أداة معالجة البيانات المناسبة على عنصر GoogleMap الذي تنتمي إليه العلامات. عند وقوع الحدث على إحدى العلامات على الخريطة، سيتم استدعاء استدعاء المستمع مع عنصر Marker المقابل الذي تم تمريره كمَعلمة. لمقارنة عنصر Marker هذا بمرجعك الخاص بكائن Marker، يجب استخدام equals() وليس ==.

يمكنك الاستماع إلى الأحداث التالية:

أحداث النقر على العلامة

يمكنك استخدام OnMarkerClickListener للاستماع إلى أحداث النقر على العلامة. لضبط أداة الاستماع هذه على الخريطة، يمكنك الاتصال بالرقم GoogleMap.setOnMarkerClickListener(OnMarkerClickListener). عندما ينقر المستخدم على علامة، سيتم استدعاء onMarkerClick(Marker) وسيتم تمرير العلامة كوسيطة. تعرض هذه الطريقة قيمة منطقية تشير إلى ما إذا كنت قد شاهدت الحدث (أي أنك تريد إيقاف السلوك الافتراضي). وفي حال عرض هذه القيمة false، سيحدث السلوك التلقائي بالإضافة إلى سلوكك المخصّص. يتمثل السلوك التلقائي لحدث النقر على علامة في عرض نافذة المعلومات الخاصة به (إذا كان ذلك متاحًا) وتحريك الكاميرا بحيث يتم توسيط العلامة على الخريطة.

تأثير مؤشر z على أحداث النقر:

  • عندما ينقر المستخدم على مجموعة من العلامات، يبدأ حدث النقر للعلامة ذات الفهرس z الأعلى.
  • يتم بدء حدث واحد على الأكثر لكل نقرة. بمعنى آخر، لا يتم تمرير النقرة إلى العلامات أو التراكبات الأخرى ذات قيم مؤشر z السفلي.
  • يؤدي النقر على مجموعة من العلامات إلى تنقّل النقرات اللاحقة عبر المجموعة، واختيار كل علامة منها تباعًا. يعطي ترتيب الدورة أولاً الأولوية لـ z-index، ثم القرب من نقطة النقر.
  • إذا نقر المستخدم خارج نطاق المجموعة القريبة، ستعيد واجهة برمجة التطبيقات حساب المجموعة وإعادة تعيين حالة دورة النقر بحيث تبدأ من البداية.
  • يقع حدث النقر في مجموعات علامات على الأشكال والتراكبات الأخرى قبل إعادة تشغيل الدورة.
  • وتعتبر العلامات بشكل فعّال أنها في مجموعة فهرس z منفصلة مقارنةً بالتراكبات أو الأشكال الأخرى (الخطوط المتعددة و/أو المضلعات و/أو الدوائر و/أو الطبقات التي تظهر على سطح الأرض)، بغض النظر عن فهرس z للتراكبات الأخرى. في حال تركيب العديد من العلامات أو التراكبات أو الأشكال فوق بعضها، يتم تدوير حدث النقر عبر مجموعة العلامات أولاً، ثم يظهر للتراكبات أو الأشكال الأخرى القابلة للنقر، استنادًا إلى قيم فهرس z.

أحداث سحب العلامات

يمكنك استخدام OnMarkerDragListener للاستماع إلى سحب الأحداث على علامة. لضبط أداة الاستماع هذه على الخريطة، يمكنك الاتصال بالرقم GoogleMap.setOnMarkerDragListener. لسحب علامة، يجب على المستخدم الضغط مع الاستمرار على العلامة. عندما يزيل المستخدم إصبعه عن الشاشة، سيبقى العلامة في هذا الموضع. عند سحب علامة، يتم استدعاء onMarkerDragStart(Marker) في البداية. أثناء سحب العلامة، يتم استدعاء onMarkerDrag(Marker) باستمرار. في نهاية السحب يتم استدعاء onMarkerDragEnd(Marker). يمكنك الحصول على موضع محدّد الموقع في أي وقت عن طريق استدعاء Marker.getPosition().