【问题标题】:iOS Dev: Using a custom image for the user annotation in MapBoxiOS 开发:在 MapBox 中为用户注释使用自定义图像
【发布时间】:2018-12-13 01:41:58
【问题描述】:

我对 IOS 开发非常陌生,所以其中一些可能看起来很明显。我尝试结合customize the user annotationmarking a place on the map with an image 的示例

我觉得我需要添加以下代码行并以某种方式将此代码附加到第一个链接中描述的用户注释中,但我不知道如何执行此操作。我猜我也可以将其中一些函数插入到 customUserLocationAnnotationView 中,但是没有明显的指示可以将其放置在该类中的哪个位置。

func mapView(_ mapView: MGLMapView, imageFor annotation: MGLAnnotation) -> MGLAnnotationImage? {
var annotationImage = mapView.dequeueReusableAnnotationImage(withIdentifier: "pisa")

if annotationImage == nil {
          var image = UIImage(named: "pisavector")!
          image = image.withAlignmentRectInsets(UIEdgeInsets(top: 0, left: 0, bottom: image.size.height/2, right: 0))
          annotationImage = MGLAnnotationImage(image: image, reuseIdentifier: "pisa")
     }
     return annotationImage
}

func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
     return true
}

编辑

我不只是想将图像放在这样的随机位置

我希望图片以用户标注为中心,当用户移动时,图片也会随之移动,如下图所示

附注

我也收到错误“无法为 ViewController (BYZ-38-tOr) 渲染和更新自动布局状态:代理崩溃 Main.storyboard”,但我认为这并不重要,因为我的程序仍然在模拟器上构建并运行良好。

【问题讨论】:

  • 您能分享一下您使用的是哪个版本的 Mapbox Maps SDK?
  • @jmkiley 我不知道什么版本。应该是最近的一个。我只是用 cocoapods 下载的。

标签: ios swift mapbox


【解决方案1】:
override func viewDidLoad() {
    super.viewDidLoad()
    let mapView = MGLMapView(frame: view.bounds)
    mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    mapView.delegate = self

    mapView.userTrackingMode = .followWithHeading
    mapView.showsUserHeadingIndicator = true
    view.addSubview(mapView)
}  

func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
// Substitute our custom view for the user location annotation. This custom view is defined below.
    if annotation is MGLUserLocation && mapView.userLocation != nil {
        return CustomUserLocationAnnotationView()
    }
    return nil
}

// Create a subclass of MGLUserLocationAnnotationView.
class CustomUserLocationAnnotationView: MGLUserLocationAnnotationView {
    ...
}

看看这个例子:https://www.mapbox.com/ios-sdk/maps/examples/user-location-annotation/

CustomUserLocationAnnotationView 中有一个名为 setupLayers 的方法。变量 dot 是一个 CALayer,因此您可以将 UIImage 添加到 CALayer。更改私有函数 setupLayers() 中的代码,如下所示:

dot = CALayer()
let myImage = UIImage(named: "star")?.cgImage
dot.contents = myImage
layer.addSublayer(dot)

【讨论】:

  • 当我将底部代码添加到我的 viewDidLoad 函数时,我收到错误 Cannot use optional chaining on non-optional value of type 'MGLMapView'。当我删除可选链接时,构建就会失败。 .......另外,我正在尝试更改userAnnotation,这是要这样做吗?我关心的是具体的经纬度坐标,因为图像应该设置在用户的坐标上。
  • @Jacob 我编辑了底部代码,错误是因为我定义了我的 mapView 可选而你定义了非可选。对于您需要设置用户位置而不是示例坐标的坐标。将此代码用于用户位置:annotation.coordinate = mapView.userLocation.coordinate 顶部代码将更改注释图像。
  • 这不是我想要的。我在问题中发布了一个编辑供您查看。我希望能够更改中心的那个蓝点,以便它显示我的图像。当用户改变位置时,图像随用户移动。
  • @Jacob 好的,您要自定义用户位置注释,我编辑了答案。
  • 是的,我在我的问题中发布了一个感谢示例的链接,但我真的不知道要更改 CustomUserLocationAnnotation 中的哪些内容才能使注释成为图像。
【解决方案2】:

此代码适用于我(使用 Mapbox iOS SDK 3.6.0/Swift 4.2/iOS 12.1)。使用的图像是 24 位 PNG。将其保存为标称尺寸的 2 倍或 4 倍,可以得到干净、无锯齿的图像(我无法区分两者之间的区别)。

func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
        // Substitute our custom view for the user location annotation. This custom view is defined below.
        if annotation is MGLUserLocation  { // && mapView.userLocation != nil
            let reuseIdentifier = "userLocationView"

            // For better performance, always try to reuse existing annotations.
            var userLocAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)

            // If there’s no reusable annotation view available, initialize a new one.
            if userLocAnnotationView == nil {
                userLocAnnotationView =  CustomUserLocationAnnotationView(reuseIdentifier: reuseIdentifier)
            }

            return userLocAnnotationView
        }
        else if annotation is MGLAnnotationView{
            // return another kind of annotation
        }

        return nil
    }


    class CustomUserLocationAnnotationView: MGLUserLocationAnnotationView {
        let size: CGFloat = 36
        var dot: CALayer!

        // -update is a method inherited from MGLUserLocationAnnotationView. It updates the appearance of the user location annotation when needed. This can be called many times a second, so be careful to keep it lightweight.
        override func update() {
            if frame.isNull {
                frame = CGRect(x: 0, y: 0, width: size, height: size)
                return setNeedsLayout()
            }

            setupLayers()
        }

        private func setupLayers() {
            // This dot forms the base of the annotation.
            if dot == nil {
                dot = CALayer()
                dot.bounds = CGRect(x: 0, y: 0, width: size, height: size)

                let image = UIImage(named: "locationPip")?.cgImage

                dot.contents = image

                dot.contentsScale = UIScreen.main.scale
                layer.addSublayer(dot)
            }
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-17
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多