我有自定义地图注释,当它们位于屏幕中心附近时,它们会显示标签。我不确定如何计算地图注释在地图上的物理位置。使用滚动视图和几何阅读器执行此操作非常简单,但是如何使用地图视图来完成此操作?
我尝试使用这个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()
})
您可以创建自定义注释类,如下所示
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
}