【问题标题】:MapBox - detect zoomLevel changesMapBox - 检测缩放级别的变化
【发布时间】:2018-11-01 11:20:20
【问题描述】:

如何简单地检测缩放级别的变化?有可能吗?

当缩放级别不够时,我只需要隐藏我的注释视图。

regionDidChange:animated: 不适合我。还有什么办法吗?

我需要在这里隐藏我的标签:

并在这里展示它们:

这是我目前对标签所做的:

类 CardAnnotation:MGLPointAnnotation { var卡:卡 初始化(卡:卡){ self.card = 卡片 超级初始化() 让坐标 = card.border.map { $0.coordinate } 让 sumLatitudes = coordinates.map { $0.latitude }.reduce(0, +) 让 sumLongitudes = coordinates.map { $0.longitude }.reduce(0, +) 让 averageLatitude = sumLatitudes / Double(coordinates.count) 让 averageLongitude = sumLongitudes / Double(coordinates.count) 坐标= CLLocationCoordinate2D(纬度:平均纬度,经度:平均经度) } 需要初始化?(编码器 aDecoder:NSCoder){ fatalError("init(coder:) 尚未实现") } }
var annotations = [CardAnnotation]()
mapView.addAnnotations(annotations)

【问题讨论】:

  • 您能否详细说明为什么 regionDidChange:animated: 不适用于您的用例?
  • 因为在该函数中我删除了注释并添加并再次显示所有注释。它滞后...

标签: ios swift mapbox


【解决方案1】:

在两个主要的ways to add overlaysMGLMapView 中,运行时样式API 更适合文本标签,也更适合根据缩放级别改变外观。在此过程中,您也可以使用相同的 API 创建多边形。

首先为您想要着色的区域创建多边形特征:

var cards: [MGLPolygonFeature] = []
var coordinates: [CLLocationCoordinate2D] = […]
let card = MGLPolygonFeature(coordinates: &coordinates, count: UInt(coordinates.count))
card.attributes = ["address": 123]
// …
cards.append(card)

在地图加载完成后运行的任何方法中,例如MGLMapViewDelegate.mapView(_:didFinishLoading:),将包含这些特征的形状源添加到当前样式:

let cardSource = MGLShapeSource(identifier: "cards", features: cards, options: [:])
mapView.style?.addSource(cardSource)

使用适当的形状源,创建一个样式层,将多边形特征呈现为淡紫色填充:

let fillLayer = MGLFillStyleLayer(identifier: "card-fills", source: cardSource)
fillLayer.fillColor = NSExpression(forConstantValue: #colorLiteral(red: 0.9098039216, green: 0.8235294118, blue: 0.9647058824, alpha: 1))
mapView.style?.addLayer(fillLayer)

然后创建另一个样式层,在每个多边形要素的质心处呈现标签。 (MGLSymbolStyleLayer 自动计算质心,考虑不规则形状的多边形。)

// Same source as the fillLayer.
let labelLayer = MGLSymbolStyleLayer(identifier: "card-labels", source: cardSource)
// Each feature’s address is an integer, but text has to be a string.
labelLayer.text = NSExpression(format: "CAST(address, 'NSString')")
// Smoothly interpolate from transparent at z16 to opaque at z17.
labelLayer.textOpacity = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)",
                                      [16: 0, 17: 1])
mapView.style?.addLayer(labelLayer)

当您自定义这些样式层时,请特别注意MGLSymbolStyleLayer 上控制附近符号是否因碰撞而自动隐藏的选项。您可能会发现自动碰撞检测使得无需指定textOpacity 属性。


创建源时,可以传递给MGLShapeSource 初始化程序的选项之一是MGLShapeSourceOption.clustered。但是,为了使用该选项,您必须创建 MGLPointFeatures,而不是 MGLPolygonFeatures。幸运的是,MGLPolygonFeature 有一个 coordinate 属性,让您无需手动计算即可找到质心:

var cardCentroids: [MGLPointFeature] = []
var coordinates: [CLLocationCoordinate2D] = […]
let card = MGLPolygonFeature(coordinates: &coordinates, count: UInt(coordinates.count))
let cardCentroid = MGLPointFeature()
cardCentroid.coordinate = card.coordinate
cardCentroid.attributes = ["address": 123]
cardCentroids.append(cardCentroid)
// …
let cardCentroidSource = MGLShapeSource(identifier: "card-centroids", features: cardCentroids, options: [.clustered: true])
mapView.style?.addSource(cardCentroidSource)

此集群源只能与MGLSymbolStyleLayerMGLCircleStyleLayer 一起使用,而不是MGLFillStyleLayerThis example 更详细地展示了如何使用聚类点。

【讨论】:

  • 我稍后会看看,如果一切正常,我会奖励你;)
  • 您的代码不起作用;)Cannot assign NSExpression to type MGLStyleValue<NSString>!。你怎么看?我尝试将文本分配给 labelLayer。
  • 啊,NSExpression 仅在 v4.0.0 及更高版本中支持。在 v3.x 中,使用恒等插值函数:mapbox.com/ios-sdk/api/3.7.8/…
  • 留给我一件事。如何将每张卡片的名称属性分配为MGLSymbolStyleLayer的文本? labelLayer.text = MGLStyleValue(rawValue: "name") //NSExpression(format: "CAST(name, 'NSString')") 暂时不起作用。
  • 现在我知道了:layer.text = MGLStyleValue(rawValue: "{name}")
【解决方案2】:

一种选择是将标签添加为MGLSymbolStyleLayer,然后根据缩放级别确定textOpacity

如果您使用的是 iOS 版 Maps SDK 的当前版本,您可以尝试以下操作:

symbols.textOpacity = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", [16.9: 0, 17: 1])

dynamically styled interactive points 示例显示了解决此问题的一种方法。

【讨论】:

  • 嗨,我如何使用MGLSymbolStyleLayer 添加我的标签?我刚刚用我当前的代码更新了这个问题。如果你能帮助我,我会奖励你;)谢谢你
  • MGLSymbolStyleLayer 是运行时样式 API 的一部分,这是一种向地图添加内容的比注解更低级别的方式。运行时样式 API 非常适合像您这样涉及文本的用例。更多信息在这里:mapbox.com/ios-sdk/api/4.0.0/adding-markers-to-a-map.html
  • 不是专门针对你想要做的事情,所以我发布了stackoverflow.com/a/50483520/4585461 来引导你了解基础知识。正如@jmkiley 指出的那样,mapbox.com/ios-sdk/examples/runtime-multiple-annotations 显示了类似的内容,并通过在用户点击某个功能时显示标注更进一步。
【解决方案3】:

问题是当你缩小时,你的注释靠得太近了?如果是这样,最好将它们组合在一起而不是完全隐藏它们。见Decluttering a Map with MapKit Annotation Clustering

【讨论】:

  • 仅供参考,这个问题是关于 iOS 版 Mapbox Maps SDK,而不是 MapKit。 Mapbox SDK 支持集群形状源,但不支持注释。
  • 哎呀,这些说明适用于 MapKit。请忽略此答案。
猜你喜欢
  • 1970-01-01
  • 2013-12-22
  • 1970-01-01
  • 1970-01-01
  • 2011-12-02
  • 2016-06-07
  • 2011-05-20
  • 1970-01-01
  • 2020-07-16
相关资源
最近更新 更多