简体   繁体   中英

iOS Dev: Using a custom image for the user annotation in MapBox

I'm very new to IOS development so some of this might seem obvious. I've tried combining the examples for customize the user annotation and marking a place on the map with an image

I feel like I need to add the following lines of code and somehow attach this code to the user annotation described in the first link, but I have no idea how to do this. I'm guessing I could also insert some of these functions into the customUserLocationAnnotationView, but there is no obvious indicator of where to place this within that class.

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
}

EDIT

I don't just want to put an image in a random location like this

在此处输入图片说明

I want the image to be centered on the user annotation, and when the user moves, the image will also move, like the image below

在此处输入图片说明

As a side note

I'm also getting the error 'Failed to render and update auto auto layout status for ViewController (BYZ-38-tOr): The agent crashed Main.storyboard' but I don't think that's important, because my program still builds and runs on the simulator fine.

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 {
    ...
}

Take a look at this example: https://www.mapbox.com/ios-sdk/maps/examples/user-location-annotation/

There is a method called setupLayers in CustomUserLocationAnnotationView. variable dot is a CALayer, so you can add a UIImage to a CALayer. Change the code in private func setupLayers() like below:

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

This code works for me (using Mapbox iOS SDK 3.6.0/Swift 4.2/iOS 12.1). The image used is a 24-bit PNG. Saving it at either 2X or 4X the nominal size makes for a clean, non-jaggy image (I can't tell the difference between the two).

样品

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM