MapBox-检测zoomLevel的变化 [英] MapBox - detect zoomLevel changes

查看:506
本文介绍了MapBox-检测zoomLevel的变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

regionDidChange:animated:不适用于我.还有其他方法吗?

我需要在这里隐藏标签:

并在此处显示它们:

这是我目前对标签的处理方式

class CardAnnotation: MGLPointAnnotation {

    var card: Card

    init(card: Card) {
        self.card = card
        super.init()

        let coordinates = card.border.map { $0.coordinate }
        let sumLatitudes = coordinates.map { $0.latitude }.reduce(0, +)
        let sumLongitudes = coordinates.map { $0.longitude }.reduce(0, +)
        let averageLatitude = sumLatitudes / Double(coordinates.count)
        let averageLongitude = sumLongitudes / Double(coordinates.count)

        coordinate = CLLocationCoordinate2D(latitude: averageLatitude, longitude: averageLongitude)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

var annotations = [CardAnnotation]()
mapView.addAnnotations(annotations)

解决方案

两个主要

在地图完成加载后运行的任何方法(例如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.但是,要使用该选项,您必须创建MGLPointFeature,而不是MGLPolygonFeature.幸运的是,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一起使用,不能与MGLFillStyleLayer一起使用. 此示例显示了如何更详细地处理聚类点. >

How can I simply detect zoom level changes? Is it possible?

I simply need to hide my annotation views when zoom level is not enough.

regionDidChange:animated: is not intended to use for me. Any other way?

I need to hide my labels here:

and show them here:

This is what I currently do with my labels:

class CardAnnotation: MGLPointAnnotation {

    var card: Card

    init(card: Card) {
        self.card = card
        super.init()

        let coordinates = card.border.map { $0.coordinate }
        let sumLatitudes = coordinates.map { $0.latitude }.reduce(0, +)
        let sumLongitudes = coordinates.map { $0.longitude }.reduce(0, +)
        let averageLatitude = sumLatitudes / Double(coordinates.count)
        let averageLongitude = sumLongitudes / Double(coordinates.count)

        coordinate = CLLocationCoordinate2D(latitude: averageLatitude, longitude: averageLongitude)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

var annotations = [CardAnnotation]()
mapView.addAnnotations(annotations)

解决方案

Of the two main ways to add overlays to an MGLMapView, the runtime styling API is better suited for text labels and also for varying the appearance based on the zoom level. While you’re at it, you might as well create the polygons using the same API too.

Start by creating polygon features for the areas you want shaded in:

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

Within any method that runs after the map finishes loading, such as MGLMapViewDelegate.mapView(_:didFinishLoading:), add a shape source containing these features to the current style:

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

With the shape source in place, create a style layer that renders the polygon features as mauve fills:

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)

Then create another style layer that renders labels at each polygon feature’s centroid. (MGLSymbolStyleLayer automatically calculates the centroids, accounting for irregularly shaped polygons.)

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

As you customize these style layers, pay particular attention to the options on MGLSymbolStyleLayer that control whether nearby symbols are automatically hidden due to collision. You may find that the automatic collision detection makes it unnecessary to specify the textOpacity property.


When you create the source, one of the options you can pass into the MGLShapeSource initializer is MGLShapeSourceOption.clustered. However, in order to use that option, you’d have to create MGLPointFeatures, not MGLPolygonFeatures. Fortunately, MGLPolygonFeature has a coordinate property that lets you find the centroid without manual calculations:

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)

This clustered source can only be used with MGLSymbolStyleLayer or MGLCircleStyleLayer, not MGLFillStyleLayer. This example shows how to work with clustered points in more detail.

这篇关于MapBox-检测zoomLevel的变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆