我正在尝试让
.popover
与“地图”>“标记”一起使用,但似乎无法实现。我尝试通过获取坐标并基于此呈现 .popover
来解决此问题,但我无法让它工作。简单地将 .popover
修饰符放在 Image("Logo")
上似乎也不起作用。这是我当前的代码
import SwiftUI
import MapKit
struct MapView: View {
@State private var region: MKCoordinateRegion
var libraries: [Library]
@State private var selectedLibrary: Library?
init(libraries: [Library]) {
if let firstLibrary = libraries.first {
_region = State(initialValue: MKCoordinateRegion(
center: firstLibrary.coordinate,
span: MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
))
} else {
_region = State(initialValue: MKCoordinateRegion())
}
self.libraries = libraries
}
var body: some View {
ZStack {
Map {
ForEach(libraries) { library in
Marker(coordinate: library.coordinate) {
Image("Logo")
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
}
.tint(.purple)
}
}
.edgesIgnoringSafeArea(.all)
GeometryReader { geometry in
ForEach(libraries) { library in
Button(action: {
self.selectedLibrary = library
}, label: {
Color.clear
})
.frame(width: 44, height: 44)
.position(self.coordinateToPoint(library.coordinate, in: geometry))
.popover(isPresented: Binding<Bool>(
get: { self.selectedLibrary == library },
set: { if !$0 { self.selectedLibrary = nil } }
)) {
Text("Annotation details here")
.padding()
}
}
}
}
}
private func coordinateToPoint(_ coordinate: CLLocationCoordinate2D, in geometry: GeometryProxy) -> CGPoint {
let mapWidthDegrees = region.span.longitudeDelta
let mapHeightDegrees = region.span.latitudeDelta
let widthPerDegree = geometry.size.width / mapWidthDegrees
let heightPerDegree = geometry.size.height / mapHeightDegrees
let xCoordinate = (coordinate.longitude - region.center.longitude + mapWidthDegrees / 2) * widthPerDegree
let yCoordinate = (region.center.latitude - coordinate.latitude + mapHeightDegrees / 2) * heightPerDegree
return CGPoint(x: xCoordinate, y: yCoordinate)
}
}
struct MapView_Previews: PreviewProvider {
static var previews: some View {
MapView(libraries: LibraryData.libraries)
}
}
这是我的图书馆数据和图书馆供参考
import CoreLocation
struct Library: Identifiable, Equatable {
let id = UUID()
let coordinate: CLLocationCoordinate2D
static func == (lhs: Library, rhs: Library) -> Bool {
lhs.id == rhs.id &&
lhs.coordinate.latitude == rhs.coordinate.latitude &&
lhs.coordinate.longitude == rhs.coordinate.longitude
}
}
struct LibraryData {
static let libraries = [
Library(coordinate: CLLocationCoordinate2D(latitude: 37.33182, longitude: -122.03118)),
Library(coordinate: CLLocationCoordinate2D(latitude: 37.34182, longitude: -122.03218)),
Library(coordinate: CLLocationCoordinate2D(latitude: 37.34182, longitude: -122.04118))
]
}
当我点击地图内的标记时,什么也没有发生。任何帮助,将不胜感激。预先感谢。
您可以尝试使用不同的方法,使用
Annotation
而不是 Marker
和 .popover()
。
示例代码展示了如何点击任意
Annotation
并弹出自定义视图。
struct ContentView: View {
var body: some View {
MapView(libraries: LibraryData.libraries)
}
}
struct MapView: View {
@State private var region: MKCoordinateRegion
var libraries: [Library]
@State private var selectedLibrary: Library?
// for testing
@State private var cameraPosition: MapCameraPosition = .camera(
MapCamera(centerCoordinate: CLLocationCoordinate2D(latitude: 37.33182, longitude: -122.03118), distance: 8000.0, heading: 0, pitch: 0)
)
init(libraries: [Library]) {
if let firstLibrary = libraries.first {
_region = State(initialValue: MKCoordinateRegion(
center: firstLibrary.coordinate,
span: MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
))
} else {
_region = State(initialValue: MKCoordinateRegion())
}
self.libraries = libraries
}
@State private var toggler = false // <-- here to toggle the popup view
var body: some View {
Map(position: $cameraPosition) {
ForEach(libraries) { library in
Annotation("", coordinate: library.coordinate) {
ZStack {
Image(systemName: "mappin.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
.onTapGesture {
selectedLibrary = library
toggler.toggle()
}
.foregroundStyle(.white, .purple)
if selectedLibrary == library && toggler {
PopupView(library: selectedLibrary).offset(x: 0, y: -30)
} else {
EmptyView()
}
}
}
}
}
.edgesIgnoringSafeArea(.all)
}
}
// just for testing, adjust the looks as needed
struct PopupView: View {
@State var library: Library?
var body: some View {
if let lib = library {
Button("Poping: \(String(lib.id.uuidString.prefix(4)))") { }
.buttonStyle(.bordered)
.foregroundStyle(.purple)
} else {
Text("no data")
}
}
}