Mapbox iOS群集可以工作,但圆形样式层和数字层没有出现/反映了群集的标记密度

Dav*_*pin 4 ios mapbox swift mapbox-gl mapbox-ios

我正在使用Mapbox创建iOS应用程序。应用程序获取对我的API的请求,该请求以JSON格式返回地图边界框内发生的许多事件。

我以前没有使用聚类,因此某些地图注释只是覆盖了其他注释。我正在使用此Mapbox教程该教程MGLShapeCollectionFeature从GeoJSON文件创建,MGLShapeSource从形状收集功能创建,然后将标记层创建为MGLSymbolStyleLayer,将圆圈层创建为MGLCircleStyleLayer,将数字层创建为MGLSymbolStyleLayer。标记层在地理上显示每个事件,圆圈层和数字层合在一起表示每个聚类的标记数。

最终产品应类似于Mapbox示例:

在此处输入图片说明

此示例使用GeoJSON文件在世界地图上显示群集海港。

以下是该示例用于将上述GeoJSON转换为相关源和图层以填充地图的相关代码:

let url = URL(fileURLWithPath: Bundle.main.path(forResource: "ports", ofType: "geojson")!)

let source = MGLShapeSource(identifier: "clusteredPorts",
    url: url,
    options: [.clustered: true, .clusterRadius: icon.size.width])
style.addSource(source)

// Use a template image so that we can tint it with the `iconColor` runtime styling property.
style.setImage(icon.withRenderingMode(.alwaysTemplate), forName: "icon")

// Show unclustered features as icons. The `cluster` attribute is built into clustering-enabled
// source features.
let ports = MGLSymbolStyleLayer(identifier: "ports", source: source)
ports.iconImageName = NSExpression(forConstantValue: "icon")
ports.iconColor = NSExpression(forConstantValue: UIColor.darkGray.withAlphaComponent(0.9))
ports.predicate = NSPredicate(format: "cluster != YES")
style.addLayer(ports)

// Color clustered features based on clustered point counts.
let stops = [
    20: UIColor.lightGray,
    50: UIColor.orange,
    100: UIColor.red,
    200: UIColor.purple
]

// Show clustered features as circles. The `point_count` attribute is built into
// clustering-enabled source features.
let circlesLayer = MGLCircleStyleLayer(identifier: "clusteredPorts", source: source)
circlesLayer.circleRadius = NSExpression(forConstantValue: NSNumber(value: Double(icon.size.width) / 2))
circlesLayer.circleOpacity = NSExpression(forConstantValue: 0.75)
circlesLayer.circleStrokeColor = NSExpression(forConstantValue: UIColor.white.withAlphaComponent(0.75))
circlesLayer.circleStrokeWidth = NSExpression(forConstantValue: 2)
circlesLayer.circleColor = NSExpression(format: "mgl_step:from:stops:(point_count, %@, %@)", UIColor.lightGray, stops)
circlesLayer.predicate = NSPredicate(format: "cluster == YES")
style.addLayer(circlesLayer)

// Label cluster circles with a layer of text indicating feature count. The value for
// `point_count` is an integer. In order to use that value for the
// `MGLSymbolStyleLayer.text` property, cast it as a string.
let numbersLayer = MGLSymbolStyleLayer(identifier: "clusteredPortsNumbers", source: source)
numbersLayer.textColor = NSExpression(forConstantValue: UIColor.white)
numbersLayer.textFontSize = NSExpression(forConstantValue: NSNumber(value: Double(icon.size.width) / 2))
numbersLayer.iconAllowsOverlap = NSExpression(forConstantValue: true)
numbersLayer.text = NSExpression(format: "CAST(point_count, 'NSString')")

numbersLayer.predicate = NSPredicate(format: "cluster == YES")
style.addLayer(numbersLayer)
Run Code Online (Sandbox Code Playgroud)

这是GeoJSON格式,事件从我的API中以返回。这种格式应该正确,因为Mapbox接受它并MGLShapeCollectionFeature根据其数据创建一个。

我的代码与Mapbox示例中的代码非常相似。我首先创建GeoJSON文件

//geoJson is my GeoJSON file as [String: Any]
var shapes: MGLShapeCollectionFeature!

    if let data = try? JSONSerialization.data(withJSONObject: geoJson, options: .prettyPrinted) {

        do {

            shapes = try MGLShape(data: data, encoding: String.Encoding.utf8.rawValue) as! MGLShapeCollectionFeature

        } catch {
            print(error.localizedDescription)
        }
    }
Run Code Online (Sandbox Code Playgroud)

我知道此GeoJSON将被转换MGLShapeCollectionFeature为该应用程序,否则将导致崩溃,并且MGLShapeCollectionFeature创建的应用程序成功创建了一个源,该源是通过/填充地图创建的。所以我MGLShapeSource从中创建一个MGLShapeCollectionFeature

let marker = UIImage(named: "redPin")?.resize(targetSize: CGSize(width: 25, height: 25))
let source = MGLShapeSource(identifier: "clusteredPoints", shape: shapes, options: [.clustered: true, .clusterRadius: 0.5])
self.mapStyle!.addSource(source)


// Use a template image so that we can tint it with the `iconColor` runtime styling property.
self.mapStyle!.setImage(marker!, forName: "marker")
Run Code Online (Sandbox Code Playgroud)

然后,我从“源”创建图层并将其添加到地图样式中。

// Show unclustered features as icons. The `cluster` attribute is built into clustering-enabled
// source features.
let events = MGLSymbolStyleLayer(identifier: "events", source: source)
events.iconImageName = NSExpression(forConstantValue: "marker")
events.iconColor = NSExpression(forConstantValue: UIColor.darkGray.withAlphaComponent(0.9))
events.predicate = NSPredicate(format: "cluster != YES")
self.mapStyle!.addLayer(events)

// Color clustered features based on clustered point counts.
let stops = [
    5: UIColor.lightGray,
    10: UIColor.orange,
    20: UIColor.red,
    30: UIColor.purple
]

// Show clustered features as circles. The `point_count` attribute is built into
// clustering-enabled source features.
let circlesLayer = MGLCircleStyleLayer(identifier: "clusteredEvents", source: source)

circlesLayer.circleRadius = NSExpression(forConstantValue: NSNumber(value: Double(self.mapStyle!.image(forName: "marker")!.size.width) / 2))
circlesLayer.circleOpacity = NSExpression(forConstantValue: 0.75)
circlesLayer.circleStrokeColor = NSExpression(forConstantValue: UIColor.white.withAlphaComponent(0.75))
circlesLayer.circleStrokeWidth = NSExpression(forConstantValue: 2)
circlesLayer.circleColor = NSExpression(format: "mgl_step:from:stops:(point_count, %@, %@)", UIColor.lightGray, stops)
circlesLayer.predicate = NSPredicate(format: "cluster == YES")
self.mapStyle!.addLayer(circlesLayer)


// Label cluster circles with a layer of text indicating feature count. The value for
// `point_count` is an integer. In order to use that value for the
// `MGLSymbolStyleLayer.text` property, cast it as a string.
let numbersLayer = MGLSymbolStyleLayer(identifier: "clusteredEventsNumbers", source: source)
numbersLayer.textColor = NSExpression(forConstantValue: UIColor.white)
numbersLayer.textFontSize = NSExpression(forConstantValue: NSNumber(value: Double(self.mapStyle!.image(forName: "marker")!.size.width) / 2))
numbersLayer.iconAllowsOverlap = NSExpression(forConstantValue: true)
numbersLayer.text = NSExpression(format: "CAST(point_count, 'NSString')")

numbersLayer.predicate = NSPredicate(format: "cluster == YES")
self.mapStyle!.addLayer(numbersLayer)
Run Code Online (Sandbox Code Playgroud)

因此,代码本质上是完全相同的,只是输入的GeoJSON是不同的。但是,当事件标记聚集时,圆圈层和数字层不会出现。见下文:

在此处输入图片说明

我知道问题不在于从URL加载了Mapbox示例的源,而从加载了我的实现的源MGLShapeCollectionFeature,因为我曾尝试将Mapbox示例的海港GeoJSON加载为MGLShapeCollectionFeature和而海港仍显示圆圈/群集时对图层进行编号。

Dav*_*pin 8

所以,我觉得自己是个白痴。

问题出在MGLShapeSource中:

MGLShapeSource(identifier: "clusteredPoints", shape: shapes, options: [.clustered: true, .clusterRadius: 0.5])
Run Code Online (Sandbox Code Playgroud)

无论出于什么原因,我一直在弄乱clusterRadius,并将其设置为0.5(我以磅为单位)。请注意,该示例使用标记的宽度确定聚类半径。

let source = MGLShapeSource(identifier: "clusteredPorts",
url: url,
options: [.clustered: true, .clusterRadius: icon.size.width])
Run Code Online (Sandbox Code Playgroud)

但是,由于某些标记与其他标记重叠时会消失,因此它们正在聚类,但未显示聚类层。它们不是聚类的,我想形状源只能知道它们何时与另一个重叠,并且会相应消失。仅仅因为它们消失并不意味着它们聚集在一起。