ios - 将 MKMapView 居中在 pin 下方的 N 像素点

标签 ios objective-c mapkit core-location

想要将 MKMapView 置于给定引脚下方 N 像素 的点上(在当前 MapRect 中可能可见也可能不可见)。

我一直在尝试使用 -(CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view 来解决这个问题,但没有成功。

有人走这条路吗(没有双关语)?

enter image description here

最佳答案

最简单的技术就是将 map 向下移动,比如从 coordinate 位置向下移动 40%会是,利用 spanregionMKMapView .如果您不需要实际像素,但只需要将其向下移动以便 CLLocationCoordinate2D有问题的是靠近 map 的顶部(比如距离顶部 10%):

CLLocationCoordinate2D center = coordinate;
center.latitude -= self.mapView.region.span.latitudeDelta * 0.40;
[self.mapView setCenterCoordinate:center animated:YES];

如果您想考虑相机的旋转和俯仰,上述技术可能不够。在这种情况下,您可以:

  • 确定要将用户位置移动到的 View 中的位置;

  • 将其转换为 CLLocation ;

  • 计算当前用户位置与新的期望位置的距离;

  • 将相机沿 map 相机当前航向 180° 的方向移动该距离。

例如在 Swift 3 中,类似于:

var point = mapView.convert(mapView.centerCoordinate, toPointTo: view)
point.y -= offset
let coordinate = mapView.convert(point, toCoordinateFrom: view)
let offsetLocation = coordinate.location

let distance = mapView.centerCoordinate.location.distance(from: offsetLocation) / 1000.0

let camera = mapView.camera
let adjustedCenter = mapView.centerCoordinate.adjust(by: distance, at: camera.heading - 180.0)
camera.centerCoordinate = adjustedCenter

在哪里CLLocationCoordinate2D有以下extension :

extension CLLocationCoordinate2D {
    var location: CLLocation {
        return CLLocation(latitude: latitude, longitude: longitude)
    }

    private func radians(from degrees: CLLocationDegrees) -> Double {
        return degrees * .pi / 180.0
    }

    private func degrees(from radians: Double) -> CLLocationDegrees {
        return radians * 180.0 / .pi
    }

    func adjust(by distance: CLLocationDistance, at bearing: CLLocationDegrees) -> CLLocationCoordinate2D {
        let distanceRadians = distance / 6_371.0   // 6,371 = Earth's radius in km
        let bearingRadians = radians(from: bearing)
        let fromLatRadians = radians(from: latitude)
        let fromLonRadians = radians(from: longitude)

        let toLatRadians = asin( sin(fromLatRadians) * cos(distanceRadians)
            + cos(fromLatRadians) * sin(distanceRadians) * cos(bearingRadians) )

        var toLonRadians = fromLonRadians + atan2(sin(bearingRadians)
            * sin(distanceRadians) * cos(fromLatRadians), cos(distanceRadians)
                - sin(fromLatRadians) * sin(toLatRadians))

        // adjust toLonRadians to be in the range -180 to +180...
        toLonRadians = fmod((toLonRadians + 3.0 * .pi), (2.0 * .pi)) - .pi

        let result = CLLocationCoordinate2D(latitude: degrees(from: toLatRadians), longitude: degrees(from: toLonRadians))

        return result
    }
}

因此,即使相机倾斜且航向不是正北,这也会将用户的位置(居中,下十字准线所在的位置)向上移动 150 像素(上十字准线所在的位置),产生如下内容:

enter image description here

显然,您应该注意退化的情况(例如,您距离南极 1 公里,并且您尝试将 map 向上移动 2 公里米;您使用的相机角度倾斜到所需的屏幕位置超出了地平线;等),但对于实际的、真实世界的场景,像上面这样的东西可能就足够了。显然,如果您不让用户改变相机的俯仰角度,答案就更简单了。


原始答案:用于移动注释 n像素

如果你有一个 CLLocationCoordinate2D ,您可以将其转换为 CGPoint , 将其移动 x 像素,然后将其转换回 CLLocationCoordinate2D :

- (void)moveCenterByOffset:(CGPoint)offset from:(CLLocationCoordinate2D)coordinate
{
    CGPoint point = [self.mapView convertCoordinate:coordinate toPointToView:self.mapView];
    point.x += offset.x;
    point.y += offset.y;
    CLLocationCoordinate2D center = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
    [self.mapView setCenterCoordinate:center animated:YES];
}

你可以这样调用:

[self moveCenterByOffset:CGPointMake(0, 100) from:coordinate];

不幸的是,这只适用于 coordinate在开始之前是可见的,所以你可能必须先到原始坐标,然后再调整中心。

关于ios - 将 MKMapView 居中在 pin 下方的 N 像素点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15421106/

相关文章:

iOS Mach-o 链接器错误解析

objective-c - 在 NSTableView 的同一单元格中显示图标和文本

ios - apple mapkit 在中国的 iPhone 设备上能用吗

ios - ios:mapKit viewForAnnotation从PIN消失弹出标题?

iphone - 什么时候用 self 访问属性,什么时候不访问?

ios - NSUndomanager 更改是否在使用 CoreData 的启动之间持续存在

ios - 解析查询不起作用

ios - 键盘扩展 : Is it possible to inherit features and UI from the stock iOS keyboard?

iphone - UIWebView execCommand 剪切、复制、粘贴

ios - MKAnnotation 和 MKPointAnnotation 有什么区别。为什么我要用一个而不是另一个?