在屏幕中心 Swift UI 获取地图注释

问题描述 投票:0回答:1

我有自定义地图注释,当它们位于屏幕中心附近时,它们会显示标签。我不确定如何计算地图注释在地图上的物理位置。使用滚动视图和几何阅读器执行此操作非常简单,但是如何使用地图视图来完成此操作?

我尝试使用这个SO解决方案,但它不起作用,因为我需要使用MKMapView视图控制器。我无法找到一种将自定义注释与 MKMapView 视图控制器一起使用的方法。此外,我想计算地图的缩放或比例以修改注释的大小。任何指示将不胜感激。

复制可粘贴代码

import SwiftUI
import MapKit

struct LocationsView: View {
    @EnvironmentObject private var vm: LocationsViewModel
    @State var scale: CGFloat = 0.0
    
    var body: some View {
        ZStack {
            mapLayer.ignoresSafeArea()
        }
    }
}

// --- WARNINGS HERE --

extension LocationsView {
    private var mapLayer: some View {
        Map(coordinateRegion: $vm.mapRegion,
            annotationItems: vm.locations,
            annotationContent: { location in
            MapAnnotation(coordinate: location.coordinates) {
                //my custom map annotations
                Circle().foregroundStyle(.red).frame(width: 50, height: 50)
                    .onTapGesture {
                        vm.showNextLocation(location: location)
                    }
            }
        })
    }
}

class LocationsViewModel: ObservableObject {
    @Published var locations: [LocationMap]    // All loaded locations
    @Published var mapLocation: LocationMap {    // Current location on map
        didSet {
            updateMapRegion(location: mapLocation)
        }
    }
    @Published var mapRegion: MKCoordinateRegion = MKCoordinateRegion() // Current region on map
    let mapSpan = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
    
    init() {
        let locations = LocationsDataService.locations
        self.locations = locations
        self.mapLocation = locations.first!
        
        self.updateMapRegion(location: locations.first!)
    }
    private func updateMapRegion(location: LocationMap) {
        withAnimation(.easeInOut) {
            mapRegion = MKCoordinateRegion(
                center: location.coordinates,
                span: mapSpan)
        }
    }
    func showNextLocation(location: LocationMap) {
        withAnimation(.easeInOut) {
            mapLocation = location
        }
    }
}

struct LocationMap: Identifiable {
    var id: String = UUID().uuidString
    let name: String
    let cityName: String
    let coordinates: CLLocationCoordinate2D
}

class LocationsDataService {
    static let locations: [LocationMap] = [
        LocationMap(name: "Colosseum", cityName: "Rome", coordinates: CLLocationCoordinate2D(latitude: 41.8902, longitude: 12.4922)),
        LocationMap(name: "Pantheon", cityName: "Rome", coordinates: CLLocationCoordinate2D(latitude: 41.8986, longitude: 12.4769)),
        LocationMap(name: "Trevi Fountain", cityName: "Rome", coordinates: CLLocationCoordinate2D(latitude: 41.9009, longitude: 12.4833))
    ]
}

struct SwiftfulMapAppApp: View {
    @StateObject private var vm = LocationsViewModel()
    var body: some View {
        VStack {
            LocationsView().environmentObject(vm)
        }
    }
}

#Preview(body: {
    SwiftfulMapAppApp()
})
swift swiftui mapkit mkmapview mkannotation
1个回答
0
投票

您可以创建自定义注释类,如下所示

    class CustomAnnotation: NSObject, MKAnnotation {
    var coordinate: CLLocationCoordinate2D
    
    var location: SearchLocation?
    var sizeOf : CGRect?
    var title: String?
    var subtitle: String?
    
    init(location: SearchLocation? , sizeOf: CGRect? , coordinate: CLLocationCoordinate2D) {
        self.location = location
        self.sizeOf = sizeOf
        self.coordinate = coordinate
        self.title = location?.title ?? ""
        self.subtitle = location?.full_address ?? ""
    }
}



class CustomAnnotationView: MKAnnotationView {    
    override var annotation: MKAnnotation? {
        willSet {
            guard let customAnnotation = newValue as? CustomAnnotation else { return }
            
            canShowCallout = false
            // Create a container view
            let containerView = UIView(frame: customAnnotation.sizeOf ?? CGRect(x: 0, y: 0, width: 40, height: 40))
            
            // Create the image view for the user photo
            let imageView = UIImageView(frame: CGRect(x: 8, y: 2, width: 24, height: 24))
            let url = URL(string: Constant.COMMON_IMG_URL + (customAnnotation.location?.vendor_image ?? "") )
            print(url)
            imageView.kf.setImage(with: url,placeholder: offerPlaceHolderSquare)
            imageView.contentMode = .scaleAspectFill
            imageView.layer.cornerRadius = 12
            imageView.clipsToBounds = true
            
            // Add the image view to the container view
            containerView.addSubview(imageView)
            
            // Create the pin background
            let pinImageView = UIImageView(frame: containerView.bounds)
            pinImageView.image = UIImage(named: "pin2") // Add your custom pin background image to your assets
            containerView.insertSubview(pinImageView, at: 0)
            
            // Set the container view as the annotation view
            addSubview(containerView)
            
            // Set the frame of the annotation view to fit the container view
            frame = containerView.frame
            centerOffset = CGPoint(x: 0, y: -frame.size.height / 2)
        }
    }
}

之后您可以像下面的代码一样应用它

  func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            guard let customAnnotation = annotation as? CustomAnnotation else { return nil }
            
            let identifier = "CustomAnnotationView"
            
            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? CustomAnnotationView
            
            if annotationView == nil {
                annotationView = CustomAnnotationView(annotation: customAnnotation, reuseIdentifier: identifier)
            } else {
                annotationView?.annotation = customAnnotation
            }
            
            return annotationView
        }

您可以像下面这样进行放大和缩小

 func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    view.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
}
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
    view.transform = CGAffineTransform.identity
}
© www.soinside.com 2019 - 2024. All rights reserved.