Mapbox图片标记

我正在构建一个iOS应用程序,其中涉及使用不同的MapBox图像标记来说明不同餐厅的位置。

像这样(接受我想要多个图像):https://docs.mapbox.com/ios/assets/maps-sdk-image-annotation-example-480-8ce20af3475bd6b27381fda012a5b10b.webp

我目前正在做什么:

我目前正在输入本地城镇周围10家不同餐馆的坐标,并在屏幕上显示一个徽标(MapBox中的比萨徽标)。

func mapView(_ mapView: MGLMapView,imageFor annotation: MGLAnnotation) -> MGLAnnotationImage? {
        // Try to reuse the existing ‘pisa’ annotation image,if it exists.
        var annotationImage = mapView.dequeueReusableAnnotationImage(withIdentifier: "pisa")

        if annotationImage == nil {
            // Leaning Tower of Pisa by Stefan Spieler from the Noun Project.
            var image = UIImage(named: "pisavector")!

            image = image.withAlignmentRectInsets(UIEdgeInsets(top: 0,left: 0,bottom: image.size.height/2,right: 0))

            // Initialize the ‘pisa’ annotation image with the UIImage we just loaded.
            annotationImage = MGLAnnotationImage(image: image,reuseIdentifier: "pisa")
        }

        return annotationImage
    }

我要实现的目标:

我想在Firebase的数据库中存储单独的坐标和图像,因此当我收购新餐厅时,可以在firebase上添加坐标和图像,以便可以在不更新地图的情况下更新地图。

我需要什么帮助:

我需要创建一个或多个函数的帮助,该函数使我可以输入每个餐厅的坐标数组和图像URL,并像上面的链接一样显示。

欢迎任何帮助:)

*******编辑*******  Mapbox GEO JSON是否有可能

teamoxiaoluo 回答:Mapbox图片标记

我用func mapView(_ mapView: MGLMapView,viewFor annotation: MGLAnnotation) -> MGLAnnotationView?完成了类似的工作。作为参考,这是我的Mapbox实现的外观:

my app

我创建了一个名为UIView的自定义EventImageView,它有2个UIImageView,一个显示了一个图钉,另一个则在该图钉上放置了一个图标图像,用于传达事件的含义(例如您可能是快餐店的炸薯条图标,也可能是亚洲餐馆的面条图标。这里还有一些功能,可以使图钉动画到位,从CGSize.zero的大小扩展到合适的图钉大小。>

import Foundation
import Mapbox
import MaterialComponents

// MGLAnnotationView subclass
class CustomEventAnnotationView: MGLAnnotationView {

    //The parent view controller (in this case always a mapVC)
    var parentVC: MapViewController!
    //The imageview that has the colored pin
    var pinImageView = UIImageView()
    //The image view above the pin image view that shows us the category icon
    var categoryImageView = UIImageView()
    //The activity indicator for when the categoryImageView is loading
    var activityIndicator = MDCActivityIndicator()
    var categoryImage: UIImage!
    var hasLoaded = false

    override func layoutSubviews() {
        //Set the offset
        centerOffset = CGVector(dx: 0,dy: -20)

        //Set the frames of the subviews
        pinImageView.frame = CGRect(x: self.bounds.midX,y: self.bounds.maxY,width: 0,height: 0)
        categoryImageView.frame = pinImageView.frame
        activityIndicator.frame = CGRect(x: categoryImageView.frame.minX + 8,y: categoryImageView.frame.minY - 16,width: categoryImageView.frame.width - 15,height: categoryImageView.frame.height - 15)
        activityIndicator.isHidden = true
        activityIndicator.cycleColors = [UIColor.hootLightBlue]
        addSubview(activityIndicator)

        //Run growpin,which animates the pin growing from invisible to full size
        growPin()
    }

    override func prepareForReuse() {
        hasLoaded = false
    }

    func loadPinImageView(with imageNamed: String) {
        pinImageView.image = UIImage(named: imageNamed)
        self.addSubview(pinImageView)
    }

    func loadCategoryImageViewFromPreload(with image: UIImage) {
        categoryImageView.image = image
        self.addSubview(categoryImageView)
    }

    //Loads the category image view from a request to the url (this is called if the image hasn't already been preloaded)
    func loadCategoryImageViewFromRequest(with url: String) {
        if categoryImage == nil {
            //Social,job,commerce,and misc have their icons loaded onto the device,so we will pass their names in the url parameter
            switch url {
            case "Social":
                self.categoryImageView.image = UIImage(named: "social")
            case "Job":
                self.categoryImageView.image = UIImage(named: "job")
            case "Commerce":
                self.categoryImageView.image = UIImage(named: "commerce")
            case "Misc":
                self.categoryImageView.image = UIImage(named: "misc")
            default:
                //If the category is neither social,nor misc,then we show and animate the activity indicator...
                activityIndicator.isHidden = false
                activityIndicator.startAnimating()
                let task = URLSession.shared.dataTask(with: URL(string: url)!) {(data,response,error) in
                    //...request the image from the respective url
                    //Load the image from the data
                    let image: UIImage = UIImage(data: data!)!
                    DispatchQueue.main.async {
                        //Then set the image we received then hide the activityIndicator on the main thread
                        self.categoryImageView.image = image
                        self.activityIndicator.stopAnimating()
                        self.activityIndicator.isHidden = true
                    }
                }
                task.resume()
            }
        }
    }

    func growPin() {
        //This is the animation that grows the views from a size of CGPoint(height: 0,width: 0) to their respective heights
        self.addSubview(self.categoryImageView)
        UIView.animate(withDuration: 0.25) {
            self.pinImageView.frame = self.bounds
            self.categoryImageView.frame = CGRect(x: self.bounds.minX + 11,y: self.bounds.minY + 6,width: self.bounds.width - 22,height: self.bounds.width - 22)
        }
    }

    func shrinkPin(completion:@escaping (() -> Void)) {
        //Opposite of growPin,not called in code as of yet
        UIView.animate(withDuration: 0.25,animations: {
            self.pinImageView.frame = CGRect(x: self.bounds.midX,height: 0)
            self.categoryImageView.frame = CGRect(x: self.bounds.midX,height: 0)
        }) { (bool) in
            completion()
        }
    }
}

我也将MGLAnnotation子类化,以创建具有存储的Event属性的自定义注释。您可以在自定义注释中使用自定义餐厅对象。

import Mapbox
class EventAnnotation: NSObject,MGLAnnotation {

    // As a reimplementation of the MGLAnnotation protocol,we have to add mutable coordinate and (sub)title properties ourselves.
    var coordinate: CLLocationCoordinate2D
    var title: String?
    var subtitle: String?
    var bundlePoint: CLLocationCoordinate2D?

    var event: Event!

    init(coordinate: CLLocationCoordinate2D,event: Event,title: String,subtitle: String) {
        self.coordinate = coordinate
        self.event = event
        self.title = title
        self.subtitle = subtitle
    }
}

然后我在func mapView(_ mapView: MGLMapView,viewFor annotation: MGLAnnotation) -> MGLAnnotationView?中使用MapViewController创建每个注释视图:

import UIKit
import Mapbox
class MapViewController: UIViewController {
    ...
}

extension MapViewController: MGLMapViewDelegate {

    func mapView(_ mapView: MGLMapView,viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
        let eventAnnotation = annotation as? EventAnnotation

        //All annotation views with the same event category look the same,so we reuse them. 
        //If you have some sort of identifier for the type of restaurant each annotation represents,you'll want to use this restaurant identifier as your reuse identifier (assuming all pins for,say,Asian restaurants look the same)
        var reuseIdentifier: reuseIdentifier = eventAnnotation?.event.categories.first ?? ""

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

        // If there’s no reusable annotation view available,initialize a new one.
        if annotationView == nil {
            annotationView = CustomEventAnnotationView(reuseIdentifier: reuseIdentifier)
            annotationView!.bounds = CGRect(x: 0,y: 0,width: 40,height: 40)

            if let eventAnnotation = annotation as? EventAnnotation {
                for category in allCategories {
                    if category.id == eventAnnotation.event.categories.first {

                        //Return the correct image depending on what kind of event we're dealing with (social,misc)
                        switch category.type! {
                        case .social:
                            annotationView!.loadPinImageView(with:"redPin")
                        case .job:
                            annotationView!.loadPinImageView(with:"bluePin")
                        case .commerce:
                            annotationView!.loadPinImageView(with:"greenPin")
                        case .misc:
                            annotationView!.loadPinImageView(with:"grayPin")
                        }

                        //Actually load the image from the main thread
                        DispatchQueue.main.async {
                            if category.preloadedImage != nil {
                                    annotationView!.loadCategoryImageViewFromPreload(with: category.preloadedImage)
                            } else {
                                    annotationView!.loadCategoryImageViewFromRequest(with: category.imageURL ?? category.name)
                            }
                        }
                    }
                }
            }

            //This checks the rotation of the mapView.
            //The z-position of our annotation views need to be adjusted if,the top of the map points south and the bottom points north
            if mapView.direction > 90 && mapView.direction < 270 {
                annotationView?.layer.zPosition = CGFloat(90-(-(eventAnnotation?.coordinate.latitude)!))
            } else {
                if annotationView != nil && eventAnnotation != nil {
                    annotationView?.layer.zPosition = CGFloat(90-(eventAnnotation?.coordinate.latitude)!)
                }
            }
            return annotationView
        }
    }
}

请务必注意,我正在将自定义事件注释添加到我的MGLMapView中。这是通过请求适当的数据来完成的,一旦完成对事件(或餐厅)数据的异步请求,就可以通过以下方式初始化自定义注释:

someAsyncRequestForEvents { (newEvents) in
    //newEvents is of type [Event]
    var newEventAnnotations: [EventAnnotation] = []
    for newEvent in newEvents {
        let newAnnotation = EventAnnotation(coordinate: CLLocationCoordinate2D(latitude: Double(newEvent.lat),longitude: Double(newEvent.long)),event: newEvent,title: newEvent.id!,subtitle: newEvent.id!)
        newEventAnnotations.append(newEvent)
    }
    mapView.addAnnotations(newEventAnnotations)
}

抱歉,这是一个漫长的答复。我只知道很难为特定框架(如iOS的Mapbox)获得SO方面的帮助。想通了,我会分享一些代码,并希望给您一个关于您可以做什么的想法。

本文链接:https://www.f2er.com/3019535.html

大家都在问