بيانات نقاط المجموعات في iOS SDK (معاينة)

إشعار

خرائط Azure إيقاف iOS SDK

تم الآن إهمال خرائط Azure Native SDK لنظام التشغيل iOS وسيتم إيقافه في 3/31/25. لتجنب انقطاع الخدمة، قم بالترحيل إلى خرائط Azure Web SDK بحلول 3/31/25. لمزيد من المعلومات، راجع دليل ترحيل خرائط Azure iOS SDK.

عند عرض العديد من نقاط البيانات على الخريطة، قد تتداخل نقاط البيانات مع بعضها البعض. قد يتسبب التداخل في أن تصبح الخريطة غير قابلة للقراءة وصعبة الاستخدام. تجميع بيانات نقطة هي عملية دمج نقاط البيانات القريبة من بعضها البعض وتمثيلها على الخريطة كنقطة بيانات واحدة مجمعة. عندما يكبر المستخدم في الخريطة، تتقسم المجموعات إلى نقاط البيانات الفردية. عند العمل مع عدد كبير من نقاط البيانات، استخدم عمليات تكوين أنظمة المجموعات لتحسين تجربة المستخدم.

عرض إنترنت الأشياء - بيانات نقطة التجميع في Azure Maps

المتطلبات الأساسية

تأكد من إكمال الخطوات الواردة في تشغيل سريع: أنشئ تطبيق مستند iOS. يمكن إدراج كتل التعليمة البرمجية في هذه المقالة في وظيفة viewDidLoad الخاصة بـ ViewController.

تمكين التجميع على مصدر بيانات

تمكين التجميع في الفئة DataSource عن طريق تعيين الخيار cluster إلى true. تعيين clusterRadius لتحديد نقاط البيانات القريبة ودمجها في نظام مجموعة. قيمة clusterRadius بالنقاط. استخدم clusterMaxZoom لتحديد مستوى التكبير/التصغير لتعطيل منطق تكوين أنظمة المجموعات. فيما يلي مثال على كيفية تمكين التجميع في مصدر بيانات.

// Create a data source and enable clustering.
let source = DataSource(options: [
    //Tell the data source to cluster point data.
    .cluster(true),

    //The radius in points to cluster data points together.
    .clusterRadius(45),

    //The maximum zoom level in which clustering occurs.
    //If you zoom in more than this, all points are rendered as symbols.
    .clusterMaxZoom(15)
])

تنبيه

يعمل تكوين أنظمة المجموعات مع ميزات Point فحسب. إذا كان مصدر البيانات يحتوي على ميزات لأنواع هندسة أخرى، مثل Polyline أو Polygon، فسيحدث خطأ.

تلميح

إذا كانت نقطتا البيانات قريبتين معًا على أرض الواقع، فمن المحتمل ألا تنفصل المجموعة أبدًا، بغض النظر عن مدى التكبير الذي يُجريه المستخدم. لمعالجة ذلك، يمكنك تعيين الخيار clusterMaxZoom لتعطيل منطق تكوين أنظمة المجموعات وعرض كل شيء ببساطة.

توفر الفئة DataSource الطرق التالية المتعلقة بتكوين أنظمة المجموعات أيضًا.

الأسلوب نوع الإرجاع ‏‏الوصف
children(of cluster: Feature) [Feature] استرداد العناصر الفرعية للمجموعة المحددة في مستوى التكبير/التصغير التالي. قد تكون هذه العناصر الفرعية مزيجاً من المزايا والمجموعات الفرعية. تصبح المجموعات الفرعية ميزات مع خصائص مطابقة ClusteredProperties.
zoomLevel(forExpanding cluster: Feature) Double حساب مستوى التكبير/التصغير الذي يبدأ فيه نظام المجموعة في التوسع أو التفريق.
leaves(of cluster: Feature, offset: UInt, limit: UInt) [Feature] استرداد كافة النقاط في مجموعة. تعيين limit إلى إرجاع مجموعة فرعية من النقاط، واستخدام offset الصفحة إلى خلال النقاط.

عرض المجموعات باستخدام طبقة فقاعية

تعد الطبقة الفقاعية طريقة رائعة لعرض النقاط المُجمّعة. استخدم التعبيرات لتوسيع نطاق نصف القطر وتغيير اللون استنادًا إلى عدد النقاط في نظام المجموعة. إذا قمت بعرض مجموعات باستخدام طبقة فقاعية، يجب عليك استخدام طبقة منفصلة لعرض نقاط بيانات غير مُجمّعة.

لعرض حجم المجموعة أعلى الفقاعة، استخدم طبقة الرمز مع النص، ولا تستخدم الأيقونة.

تعرض التعليمات البرمجية التالية النقاط المُجمّعة باستخدام طبقة فقاعة، وعدد النقاط في كل نظام مجموعة باستخدام طبقة الرمز. يتم استخدام طبقة رمز ثانية لعرض نقاط فردية غير موجودة داخل نظام مجموعة.

// Create a data source and enable clustering.
let source = DataSource(options: [
    // Tell the data source to cluster point data.
    .cluster(true),

    // The radius in points to cluster data points together.
    .clusterRadius(45),

    // The maximum zoom level in which clustering occurs.
    // If you zoom in more than this, all points are rendered as symbols.
    .clusterMaxZoom(15)
])

// Import the geojson data and add it to the data source.
let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
source.importData(fromURL: url)

// Add data source to the map.
map.sources.add(source)

// Create a bubble layer for rendering clustered data points.
map.layers.addLayer(
    BubbleLayer(
        source: source,
        options: [
            // Scale the size of the clustered bubble based on the number of points in the cluster.
            .bubbleRadius(
                from: NSExpression(
                    forAZMStepping: NSExpression(forKeyPath: "point_count"),
                    // Default of 20 point radius.
                    from: NSExpression(forConstantValue: 20),
                    stops: NSExpression(forConstantValue: [

                        // If point_count >= 100, radius is 30 points.
                        100: 30,

                        // If point_count >= 750, radius is 40 points.
                        750: 40
                    ])
                )
            ),

            // Change the color of the cluster based on the value on the point_count property of the cluster.
            .bubbleColor(
                from: NSExpression(
                    forAZMStepping: NSExpression(forKeyPath: "point_count"),
                    // Default to green.
                    from: NSExpression(forConstantValue: UIColor.green),
                    stops: NSExpression(forConstantValue: [

                        // If the point_count >= 100, color is yellow.
                        100: UIColor.yellow,

                        // If the point_count >= 100, color is red.
                        750: UIColor.red
                    ])
                )
            ),
            .bubbleStrokeWidth(0),

            // Only rendered data points which have a point_count property, which clusters do.
            .filter(from: NSPredicate(format: "point_count != NIL"))
        ]
    )
)

// Create a symbol layer to render the count of locations in a cluster.
map.layers.addLayer(
    SymbolLayer(
        source: source,
        options: [
            // Hide the icon image.
            .iconImage(nil),

            // Display the point count as text.
            .textField(from: NSExpression(forKeyPath: "point_count")),
            .textOffset(CGVector(dx: 0, dy: 0.4)),
            .textAllowOverlap(true),

            // Allow clustered points in this layer.
            .filter(from: NSPredicate(format: "point_count != NIL"))
        ]
    )
)

// Create a layer to render the individual locations.
map.layers.addLayer(
    SymbolLayer(
        source: source,
        options: [
            // Filter out clustered points from this layer.
            .filter(from: NSPredicate(format: "point_count = NIL"))
        ]
    )
)

تظهر الصورة التالية ميزات نقطة مجمعة لعرض التعليمات البرمجية أعلاه في طبقة فقاعية، محددة الحجم وملونة استنادًا إلى عدد النقاط في نظام المجموعة. يتم عرض النقاط غير المتفاوتة باستخدام طبقة رمز.

تتفكك المواقع المجمعة في الخرائط أثناء تكبير الخريطة.

عرض المجموعات باستخدام طبقة الرمز

عند عرض نقاط البيانات، تخفي طبقة الرمز تلقائيا الرموز التي تتداخل مع بعضها البعض لضمان واجهة مستخدم أكثر نظافة. قد يكون هذا السلوك الافتراضي غير مرغوب فيه إذا كنت تريد إظهار كثافة نقاط البيانات على الخريطة. ومع ذلك، يمكن تغيير هذه الإعدادات. لعرض كافة الرموز، قم بتعيين الخيار iconAllowOverlap لطبقة الرموز إلى true.

استخدم تكوين أنظمة المجموعات لإظهار كثافة نقاط البيانات مع الحفاظ على واجهة مستخدم نقية. يوضح لك النموذج التالي كيفية إضافة رموز مخصصة وتمثيل المجموعات ونقاط البيانات الفردية باستخدام طبقة الرمز.

// Load all the custom image icons into the map resources.
map.images.add(UIImage(named: "earthquake_icon")!, withID: "earthquake_icon")
map.images.add(UIImage(named: "warning-triangle-icon")!, withID: "warning-triangle-icon")

// Create a data source and add it to the map.
let source = DataSource(options: [
    // Tell the data source to cluster point data.
    .cluster(true)
])

// Import the geojson data and add it to the data source.
let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
source.importData(fromURL: url)

// Add data source to the map.
map.sources.add(source)

// Create a layer to render the individual locations.
map.layers.addLayer(
    SymbolLayer(
        source: source,
        options: [
            .iconImage("earthquake_icon"),

            // Filter out clustered points from this layer.
            .filter(from: NSPredicate(format: "point_count = NIL"))
        ]
    )
)

// Create a symbol layer to render the clusters.
map.layers.addLayer(
    SymbolLayer(
        source: source,
        options: [
            .iconImage("warning-triangle-icon"),
            .textField(from: NSExpression(forKeyPath: "point_count")),
            .textOffset(CGVector(dx: 0, dy: -0.4)),

            // Allow clustered points in this layer.
            .filter(from: NSPredicate(format: "point_count != NIL"))
        ]
    )
)

بالنسبة لهذه العينة، تُحمل الصورة الموضحة أدناه في مجلد الأصول للتطبيق.

صورة أيقونة الزلزال صورة أيقونة الطقس من زخات من المطر
earthquake-icon.png warning-triangle-icon.png

تُظهر الصورة التالية التعليمات البرمجية أعلاه التي تعرض ميزات نقطة مجمعة وغير مجمعة باستخدام أيقونات مخصصة.

يتم عرض خريطة النقاط المجمعة باستخدام طبقة رمز.

التجميع وطبقة خريطة التمثيل اللوني

تُعد خرائط التمثيل اللوني طريقة رائعة لعرض كثافة البيانات على الخريطة. يمكن لطريقة التصور معالجة عدد كبير من نقاط البيانات بمفردها. إذا تم تجميع نقاط البيانات وتم استخدام حجم نظام المجموعة كوزن لخريطة التمثيل اللوني، يمكن لخريطة التمثيل اللوني معالجة المزيد من البيانات. لتحقيق هذا الخيار، قم بتعيين heatmapWeight خيار طبقة خريطة التمثيل اللوني إلى NSExpression(forKeyPath: "point_count"). عندما يكون نصف قطر نظام المجموعة صغيرا، تبدو خريطة التمثيل اللوني متطابقة تقريبا مع خريطة التمثيل اللوني باستخدام نقاط البيانات غير المتفاوتة المسافات، ولكنها تؤدي أداء أفضل. ومع ذلك، كلما كان نصف قطر نظام المجموعة أصغر، زادت دقة خريطة التمثيل اللوني، ولكن مع فوائد أداء أقل.

// Create a data source and enable clustering.
let source = DataSource(options: [
    // Tell the data source to cluster point data.
    .cluster(true),

    // The radius in points to cluster points together.
    .clusterRadius(10)
])

// Import the geojson data and add it to the data source.
let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
source.importData(fromURL: url)

// Add data source to the map.
map.sources.add(source)

// Create a heat map and add it to the map.
map.layers.insertLayer(
    HeatMapLayer(
        source: source,
        options: [
            // Set the weight to the point_count property of the data points.
            .heatmapWeight(from: NSExpression(forKeyPath: "point_count")),

            // Optionally adjust the radius of each heat point.
            .heatmapRadius(20)
        ]
    ),
    below: "labels"
)

تظهر الصورة التالية التعليمات البرمجية أعلاه التي تعرض خريطة التمثيل اللوني المحسنة باستخدام ميزات النقطة المجمعة وعدد نظام المجموعة كوزن في خريطة التمثيل اللوني.

تعيين خريطة تمثيل لوني محسّنة باستخدام نقاط مجمعة كوزن.

اضغط على الأحداث على نقاط البيانات المجمعة

عند وقوع أحداث الضغط على طبقة تحتوي على نقاط بيانات مجمعة، تعود نقطة البيانات المجمعة إلى الحدث ككائن ميزة نقطة GeoJSON. تحتوي ميزة النقطة هذه على الخصائص التالية:

اسم الخاصية كتابة الوصف
cluster boolean تشير إلى ما إذا كانت الميزة تمثل مجموعة.
point_count رقم عدد النقاط التي تحتوي عليها المجموعة.
point_count_abbreviated سلسلة سلسلة تختصر القيمة point_count إذا كانت طويلة. (على سبيل المثال، 4,000 يصبح 4K)

يأخذ هذا المثال طبقة فقاعة تعرض نقاط نظام المجموعة وتضيف حدث ضغط. عند تشغيل حدث الضغط، تقوم التعليمات البرمجية بحساب الخريطة وتكبيرها إلى مستوى التكبير/التصغير التالي، حيث تنفصل المجموعة. يتم تنفيذ هذه الوظيفة باستخدام zoomLevel(forExpanding:) أسلوب الفئة DataSource.

// Create a data source and enable clustering.
let source = DataSource(options: [
    // Tell the data source to cluster point data.
    .cluster(true),

    // The radius in points to cluster data points together.
    .clusterRadius(45),

    // The maximum zoom level in which clustering occurs.
    // If you zoom in more than this, all points are rendered as symbols.
    .clusterMaxZoom(15)
])

// Set data source to the class property to use in events handling later.
self.source = source

// Import the geojson data and add it to the data source.
let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
source.importData(fromURL: url)

// Add data source to the map.
map.sources.add(source)

// Create a bubble layer for rendering clustered data points.
let clusterBubbleLayer = BubbleLayer(
    source: source,
    options: [
        // Scale the size of the clustered bubble based on the number of points in the cluster.
        .bubbleRadius(
            from: NSExpression(
                forAZMStepping: NSExpression(forKeyPath: "point_count"),
                // Default of 20 point radius.
                from: NSExpression(forConstantValue: 20),
                stops: NSExpression(forConstantValue: [
                    // If point_count >= 100, radius is 30 points.
                    100: 30,

                    // If point_count >= 750, radius is 40 points.
                    750: 40
                ])
            )
        ),

        // Change the color of the cluster based on the value on the point_count property of the cluster.
        .bubbleColor(
            from: NSExpression(
                forAZMStepping: NSExpression(forKeyPath: "point_count"),
                // Default to green.
                from: NSExpression(forConstantValue: UIColor.green),
                stops: NSExpression(forConstantValue: [
                    // If the point_count >= 100, color is yellow.
                    100: UIColor.yellow,

                    // If the point_count >= 100, color is red.
                    750: UIColor.red
                ])
            )
        ),
        .bubbleStrokeWidth(0),

        // Only rendered data points which have a point_count property, which clusters do.
        .filter(from: NSPredicate(format: "point_count != NIL"))
    ]
)

// Add the clusterBubbleLayer to the map.
map.layers.addLayer(clusterBubbleLayer)

// Create a symbol layer to render the count of locations in a cluster.
map.layers.addLayer(
    SymbolLayer(
        source: source,
        options: [
            // Hide the icon image.
            .iconImage(nil),

            // Display the point count as text.
            .textField(from: NSExpression(forKeyPath: "point_count_abbreviated")),

            // Offset the text position so that it's centered nicely.
            .textOffset(CGVector(dx: 0, dy: 0.4)),

            // Allow text overlapping so text is visible anyway
            .textAllowOverlap(true),

            // Allow clustered points in this layer.
            .filter(from: NSPredicate(format: "point_count != NIL"))
        ]
    )
)

// Create a layer to render the individual locations.
map.layers.addLayer(
    SymbolLayer(
        source: source,
        options: [
            // Filter out clustered points from this layer.
            .filter(from: NSPredicate(format: "point_count = NIL"))
        ]
    )
)

// Add the delegate to handle taps on the clusterBubbleLayer only.
map.events.addDelegate(self, for: [clusterBubbleLayer.id])
func azureMap(_ map: AzureMap, didTapOn features: [Feature]) {
    guard let source = source, let cluster = features.first else {
        // Data source have been released or no features provided
        return
    }

    // Get the cluster expansion zoom level. This is the zoom level at which the cluster starts to break apart.
    let expansionZoom = source.zoomLevel(forExpanding: cluster)

    // Update the map camera to be centered over the cluster.
    map.setCameraOptions([
        // Center the map over the cluster points location.
        .center(cluster.coordinate),

        // Zoom to the clusters expansion zoom level.
        .zoom(expansionZoom),

        // Animate the movement of the camera to the new position.
        .animationType(.ease),
        .animationDuration(200)
    ])
}

تظهر الصورة التالية التعليمات البرمجية أعلاه التي تعرض نقاطا مجمعة على خريطة عند الضغط عليها، قم بالتكبير/التصغير في مستوى التكبير/التصغير التالي الذي يبدأ نظام المجموعة في التقسيم والتوسيع.

خريطة الميزات المجمعة التي يتم تكبيرها وتقسميها عند الضغط عليها.

عرض منطقة نظام المجموعة

تنتشر بيانات النقطة التي تمثلها المجموعة عبر المنطقة. في هذا النموذج عند الضغط على نظام مجموعة، يحدث سلوكان رئيسيان. أولا، نقاط البيانات الفردية المضمنة في نظام المجموعة المستخدمة لحساب بنية محدبة. بعد ذلك، يتم عرض بنية convex على الخريطة لإظهار منطقة. إن الهيكل المحدب هو مضلع يلف مجموعة من النقاط مثل شريط مطاطي ويمكن حسابه باستخدام طريقة convexHull(from:). يمكن استرداد جميع النقاط الموجودة في نظام مجموعة من مصدر البيانات باستخدام الأسلوب leaves(of:offset:limit:).

// Create a data source and enable clustering.
let source = DataSource(options: [
    // Tell the data source to cluster point data.
    .cluster(true)
])

// Set data source to the class property to use in events handling later.
self.source = source

// Import the geojson data and add it to the data source.
let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
source.importData(fromURL: url)

// Add data source to the map.
map.sources.add(source)

// Create a data source for the convex hull polygon.
// Since this will be updated frequently it is more efficient to separate this into its own data source.
let polygonDataSource = DataSource()

// Set polygon data source to the class property to use in events handling later.
self.polygonDataSource = polygonDataSource

// Add data source to the map.
map.sources.add(polygonDataSource)

// Add a polygon layer and a line layer to display the convex hull.
map.layers.addLayer(PolygonLayer(source: polygonDataSource))
map.layers.addLayer(LineLayer(source: polygonDataSource))

// Load an icon into the image sprite of the map.
map.images.add(.azm_markerRed, withID: "marker-red")

// Create a symbol layer to render the clusters.
let clusterLayer = SymbolLayer(
    source: source,
    options: [
        .iconImage("marker-red"),
        .textField(from: NSExpression(forKeyPath: "point_count_abbreviated")),
        .textOffset(CGVector(dx: 0, dy: -1.2)),
        .textColor(.white),
        .textSize(14),

        // Only rendered data points which have a point_count property, which clusters do.
        .filter(from: NSPredicate(format: "point_count != NIL"))
    ]
)

// Add the clusterLayer to the map.
map.layers.addLayer(clusterLayer)

// Create a layer to render the individual locations.
map.layers.addLayer(
    SymbolLayer(
        source: source,
        options: [
            // Filter out clustered points from this layer.
            .filter(from: NSPredicate(format: "point_count = NIL"))
        ]
    )
)

// Add the delegate to handle taps on the clusterLayer only
// and then calculate the convex hull of all the points within a cluster.
map.events.addDelegate(self, for: [clusterLayer.id])
func azureMap(_ map: AzureMap, didTapOn features: [Feature]) {
    guard let source = source, let polygonDataSource = polygonDataSource, let cluster = features.first else {
        // Data source have been released or no features provided
        return
    }

    // Get all points in the cluster. Set the offset to 0 and the max int value to return all points.
    let featureLeaves = source.leaves(of: cluster, offset: 0, limit: .max)

    // When only two points in a cluster. Render a line.
    if featureLeaves.count == 2 {

        // Extract the locations from the feature leaves.
        let locations = featureLeaves.map(\.coordinate)

        // Create a line from the points.
        polygonDataSource.set(geometry: Polyline(locations))

        return
    }

    // When more than two points in a cluster. Render a polygon.
    if let hullPolygon = Math.convexHull(from: featureLeaves) {

        // Overwrite all data in the polygon data source with the newly calculated convex hull polygon.
        polygonDataSource.set(geometry: hullPolygon)
    }
}

تظهر الصورة التالية التعليمات البرمجية أعلاه التي تعرض منطقة جميع النقاط داخل نظام مجموعة تم لمسه.

تُظهر الخريطة مضلعاً محدباً لجميع النقاط داخل مجموعة تم الضغط عليها.

تجميع البيانات في نظام مجموعات

غالبًا ما يتم تمثيل المجموعات باستخدام رمز مع عدد النقاط الموجودة داخل نظام المجموعة. ولكن، في بعض الأحيان من المستحسن تخصيص نمط المجموعات بمقاييس إضافية. باستخدام خصائص نظام المجموعة، يمكن إنشاء خصائص مخصصة وتساوي عملية حسابية استناداً إلى الخصائص ضمن كل نقطة في نظام المجموعة. يمكن تعريف خصائص المجموعة في خيار clusterPropertiesمن DataSource.

تحسب التعليمات البرمجية التالية عددًا استنادًا إلى خاصية نوع الكيان لكل نقطة بيانات في نظام مجموعة. عندما يضغط مستخدم على نظام مجموعة، تظهر نافذة منبثقة مع معلومات إضافية حول نظام المجموعة.

// Create a popup and add it to the map.
let popup = Popup()
map.popups.add(popup)

// Set popup to the class property to use in events handling later.
self.popup = popup

// Close the popup initially.
popup.close()

// Create a data source and enable clustering.
let source = DataSource(options: [
    // Tell the data source to cluster point data.
    .cluster(true),

    // The radius in points to cluster data points together.
    .clusterRadius(50),

    // Calculate counts for each entity type in a cluster as custom aggregate properties.
    .clusterProperties(self.entityTypes.map { entityType in
        ClusterProperty(
            name: entityType,
            operator: NSExpression(
                forFunction: "sum:",
                arguments: [
                    NSExpression.featureAccumulatedAZMVariable,
                    NSExpression(forKeyPath: entityType)
                ]
            ),
            map: NSExpression(
                forConditional: NSPredicate(format: "EntityType = '\(entityType)'"),
                trueExpression: NSExpression(forConstantValue: 1),
                falseExpression: NSExpression(forConstantValue: 0)
            )
        )
    })
])

// Import the geojson data and add it to the data source.
let url = URL(string: "https://samples.azuremaps.com/data/geojson/SamplePoiDataSet.json")!
source.importData(fromURL: url)

// Add data source to the map.
map.sources.add(source)

// Create a bubble layer for rendering clustered data points.
let clusterBubbleLayer = BubbleLayer(
    source: source,
    options: [
        .bubbleRadius(20),
        .bubbleColor(.purple),
        .bubbleStrokeWidth(0),

        // Only rendered data points which have a point_count property, which clusters do.
        .filter(from: NSPredicate(format: "point_count != NIL"))
    ]
)

// Add the clusterBubbleLayer to the map.
map.layers.addLayer(clusterBubbleLayer)

// Create a symbol layer to render the count of locations in a cluster.
map.layers.addLayer(
    SymbolLayer(
        source: source,
        options: [
            // Hide the icon image.
            .iconImage(nil),

            // Display the 'point_count_abbreviated' property value.
            .textField(from: NSExpression(forKeyPath: "point_count_abbreviated")),

            .textColor(.white),
            .textOffset(CGVector(dx: 0, dy: 0.4)),

            // Allow text overlapping so text is visible anyway
            .textAllowOverlap(true),

            // Only rendered data points which have a point_count property, which clusters do.
            .filter(from: NSPredicate(format: "point_count != NIL"))
        ]
    )
)

// Create a layer to render the individual locations.
map.layers.addLayer(
    SymbolLayer(
        source: source,
        options: [
            // Filter out clustered points from this layer.
            SymbolLayerOptions.filter(from: NSPredicate(format: "point_count = NIL"))
        ]
    )
)

// Add the delegate to handle taps on the clusterBubbleLayer only
// and display the aggregate details of the cluster.
map.events.addDelegate(self, for: [clusterBubbleLayer.id])
func azureMap(_ map: AzureMap, didTapOn features: [Feature]) {
    guard let popup = popup, let cluster = features.first else {
        // Popup has been released or no features provided
        return
    }

    // Create a number formatter that removes decimal places.
    let nf = NumberFormatter()
    nf.maximumFractionDigits = 0

    // Create the popup's content.
    var text = ""

    let pointCount = cluster.properties["point_count"] as! Int
    let pointCountString = nf.string(from: pointCount as NSNumber)!

    text.append("Cluster size: \(pointCountString) entities\n")

    entityTypes.forEach { entityType in
        text.append("\n")
        text.append("\(entityType): ")

        // Get the aggregated entity type count from the properties of the cluster by name.
        let aggregatedCount = cluster.properties[entityType] as! Int
        let aggregatedCountString = nf.string(from: aggregatedCount as NSNumber)!

        text.append(aggregatedCountString)
    }

    // Create the custom view for the popup.
    let customView = PopupTextView()

    // Set the text to the custom view.
    customView.setText(text)

    // Get the position of the cluster.
    let position = Math.positions(from: cluster).first!

    // Set the options on the popup.
    popup.setOptions([
        // Set the popups position.
        .position(position),

        // Set the anchor point of the popup content.
        .anchor(.bottom),

        // Set the content of the popup.
        .content(customView)
    ])

    // Open the popup.
    popup.open()
}

تتبع النافذة المنبثقة الخطوات الموضحة في عرض مستند منبثق.

تظهر الصورة التالية التعليمات البرمجية أعلاه التي تعرض نافذة منبثقة مع عدد مجمع لكل نوع قيمة كيان لكافة النقاط في النقطة المجمعة التي تم الضغط عليها.

تُظهر الخريطة نافذة منبثقة للتعدادات المجمعة لأنواع الكيانات لجميع النقاط في نظام مجموعة.

معلومات إضافية

لإضافة المزيد من البيانات إلى الخريطة: