将地图注释居中到屏幕的上四分之一
Centering a map annotation to the top quarter of the screen
所以我想在单击注释 (Mapbox) 时从图像 1 转到图像 2:
https://i.stack.imgur.com/OFIFa.png
通过在 Mapbox 委托函数之一中调用 mapView.setCenter(),可以很容易地让地图以注释为中心,如下所示:
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
mapView.setCenter(annotation.coordinate, animated: true)
}
显然,这会将注释居中放置在屏幕中间,但我需要注释 'centered' 位于弹出视图上方的区域,这样它仍然可见(理想情况下,它会与 'View' 的顶部和屏幕的顶部边缘等距。
我正在考虑在 setCenter 中设置 zoomLevel,然后缩放到注释以南的特定距离,但这样做的问题是 iOS 设备上的各种屏幕尺寸会使注释居中不同。
我也在想也许我可以在屏幕上进行某种从地图到 CGPoint 的坐标转换,但我真的不确定如何正确地实现它(我只使用过 mapView.convert( CGPoint,toCoordinateFrom: mapView),这在这里没有用)。我不确定如何解决这个问题。任何帮助将不胜感激,无论它只是让我开始一条道路,还是您已经有了更好的解决方案。谢谢!
您可以将地图框的大小调整为该正方形,然后将坐标居中。这意味着该视图将不再在 mapview 上弹出操作,尽管它看起来是。
这可以通过以下方式完成:
(your MKMapView).frame = CGRect(x: , y: , width: , height: )
x 和 y 是 superview(mapview 后面的视图)坐标系中的起始坐标。然后 width 和 height 参数创建一个矩形,这些矩形的尺寸从 x 和 y 开始。小心起点,它有时在左下角,有时在左上角,视情况而定。根据您的实施,您可能还必须修改弹出视图框架。
-如果您的地图始终连接到屏幕顶部,您可以使用
(your MKMapView).frame = CGRect(x: self.view.origin.x, y: self.view.origin.y, width: self.view.frame.width, height: self.view.frame.height/2)
我不使用 MapBox,但如果您可以访问区域的跨度(地图的水平和垂直距离)
您可以从注释的坐标中减去所需的纬度跨度,然后设置地图的中心。
///Centers the map region by placing the passed annotation in the center of the I quadrant
func centerTop(annotation: SpecialAnnot){
//Find a 4th of the span (The horizontal and vertical span representing the amount of map to display.)
let latCorrection = region.span.latitudeDelta/4 + region.span.latitudeDelta/8
self.region = MKCoordinateRegion(center: .init(latitude: annotation.coordinate.latitude - latCorrection, longitude: annotation.coordinate.longitude), span: region.span)
}
这是一些 SwiftUI 代码。
import SwiftUI
import MapKit
class SpecialAnnot: NSObject, MKAnnotation, Identifiable{
let id: UUID = .init()
var coordinate: CLLocationCoordinate2D
init(coordinate: CLLocationCoordinate2D) {
self.coordinate = coordinate
super.init()
}
}
struct QuarterCenteredView: View {
@State var region: MKCoordinateRegion = MKCoordinateRegion()
let annotationCoordinate: [SpecialAnnot] = [SpecialAnnot(coordinate: .init(latitude: 40.748817, longitude: -73.985428))]
var body: some View {
VStack{
Button("center quadrant I", action: {
centerTop(annotation: annotationCoordinate.first!)
})
Map(coordinateRegion: $region, annotationItems: annotationCoordinate, annotationContent: { annot in
MapAnnotation(coordinate: annot.coordinate, content: {
Image(systemName: "mappin").foregroundColor(.red)
})
})
.onAppear(perform: {
DispatchQueue.main.async {
region = MKCoordinateRegion(center: annotationCoordinate.first!.coordinate, span: region.span)
}
})
}
}
///Centers the map region by placing the passed annotation in the center of the I quadrant
func centerTop(annotation: SpecialAnnot){
//Find a 4th of the span (The horizontal and vertical span representing the amount of map to display.)
let latCorrection = region.span.latitudeDelta/4 + region.span.latitudeDelta/8
self.region = MKCoordinateRegion(center: .init(latitude: annotation.coordinate.latitude - latCorrection, longitude: annotation.coordinate.longitude), span: region.span)
}
}
struct QuarterCenteredView_Previews: PreviewProvider {
static var previews: some View {
QuarterCenteredView()
}
}
所以我想在单击注释 (Mapbox) 时从图像 1 转到图像 2:
https://i.stack.imgur.com/OFIFa.png
通过在 Mapbox 委托函数之一中调用 mapView.setCenter(),可以很容易地让地图以注释为中心,如下所示:
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
mapView.setCenter(annotation.coordinate, animated: true)
}
显然,这会将注释居中放置在屏幕中间,但我需要注释 'centered' 位于弹出视图上方的区域,这样它仍然可见(理想情况下,它会与 'View' 的顶部和屏幕的顶部边缘等距。
我正在考虑在 setCenter 中设置 zoomLevel,然后缩放到注释以南的特定距离,但这样做的问题是 iOS 设备上的各种屏幕尺寸会使注释居中不同。
我也在想也许我可以在屏幕上进行某种从地图到 CGPoint 的坐标转换,但我真的不确定如何正确地实现它(我只使用过 mapView.convert( CGPoint,toCoordinateFrom: mapView),这在这里没有用)。我不确定如何解决这个问题。任何帮助将不胜感激,无论它只是让我开始一条道路,还是您已经有了更好的解决方案。谢谢!
您可以将地图框的大小调整为该正方形,然后将坐标居中。这意味着该视图将不再在 mapview 上弹出操作,尽管它看起来是。
这可以通过以下方式完成:
(your MKMapView).frame = CGRect(x: , y: , width: , height: )
x 和 y 是 superview(mapview 后面的视图)坐标系中的起始坐标。然后 width 和 height 参数创建一个矩形,这些矩形的尺寸从 x 和 y 开始。小心起点,它有时在左下角,有时在左上角,视情况而定。根据您的实施,您可能还必须修改弹出视图框架。
-如果您的地图始终连接到屏幕顶部,您可以使用
(your MKMapView).frame = CGRect(x: self.view.origin.x, y: self.view.origin.y, width: self.view.frame.width, height: self.view.frame.height/2)
我不使用 MapBox,但如果您可以访问区域的跨度(地图的水平和垂直距离)
您可以从注释的坐标中减去所需的纬度跨度,然后设置地图的中心。
///Centers the map region by placing the passed annotation in the center of the I quadrant
func centerTop(annotation: SpecialAnnot){
//Find a 4th of the span (The horizontal and vertical span representing the amount of map to display.)
let latCorrection = region.span.latitudeDelta/4 + region.span.latitudeDelta/8
self.region = MKCoordinateRegion(center: .init(latitude: annotation.coordinate.latitude - latCorrection, longitude: annotation.coordinate.longitude), span: region.span)
}
这是一些 SwiftUI 代码。
import SwiftUI
import MapKit
class SpecialAnnot: NSObject, MKAnnotation, Identifiable{
let id: UUID = .init()
var coordinate: CLLocationCoordinate2D
init(coordinate: CLLocationCoordinate2D) {
self.coordinate = coordinate
super.init()
}
}
struct QuarterCenteredView: View {
@State var region: MKCoordinateRegion = MKCoordinateRegion()
let annotationCoordinate: [SpecialAnnot] = [SpecialAnnot(coordinate: .init(latitude: 40.748817, longitude: -73.985428))]
var body: some View {
VStack{
Button("center quadrant I", action: {
centerTop(annotation: annotationCoordinate.first!)
})
Map(coordinateRegion: $region, annotationItems: annotationCoordinate, annotationContent: { annot in
MapAnnotation(coordinate: annot.coordinate, content: {
Image(systemName: "mappin").foregroundColor(.red)
})
})
.onAppear(perform: {
DispatchQueue.main.async {
region = MKCoordinateRegion(center: annotationCoordinate.first!.coordinate, span: region.span)
}
})
}
}
///Centers the map region by placing the passed annotation in the center of the I quadrant
func centerTop(annotation: SpecialAnnot){
//Find a 4th of the span (The horizontal and vertical span representing the amount of map to display.)
let latCorrection = region.span.latitudeDelta/4 + region.span.latitudeDelta/8
self.region = MKCoordinateRegion(center: .init(latitude: annotation.coordinate.latitude - latCorrection, longitude: annotation.coordinate.longitude), span: region.span)
}
}
struct QuarterCenteredView_Previews: PreviewProvider {
static var previews: some View {
QuarterCenteredView()
}
}