将MKMapView置于引脚下方的N点像素上

eri*_*ric 34 objective-c core-location mapkit ios

想要将MKMapView置于给定引脚下方的N个像素点(在当前MapRect中可能会或可能不会显示).

我一直试图用各种戏剧解决这个问题但-(CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view没有成功.

任何人都走在这条路上(没有双关语)?

在此输入图像描述

Rob*_*Rob 81

最简单的方法是只要在地图下移,说从其中40%coordinate将是,以优势spanregionMKMapView.如果您不需要实际的像素,只需要向下移动以使有CLLocationCoordinate2D问题的地方靠近地图的顶部(比如说距离顶部10%):

CLLocationCoordinate2D center = coordinate;
center.latitude -= self.mapView.region.span.latitudeDelta * 0.40;
[self.mapView setCenterCoordinate:center animated:YES];
Run Code Online (Sandbox Code Playgroud)

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

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

  • 将其转换为CLLocation;

  • 计算当前用户位置与新的所需位置的距离;

  • 将相机移动距离地图相机当前标题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
Run Code Online (Sandbox Code Playgroud)

哪里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
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,即使相机倾斜并且在正北以外的航向上,这也会移动用户的位置(位于下部十字准线的中心位置)上方150像素(上部十字准线处),产生类似于:

在此输入图像描述

显然,你应该意识到退化的情况(例如,你距离南极1公里,你试图将地图向上移动2公里;你使用的摄像机角度到目前为止所需的屏幕位置已经超过地平线;等等,但对于实际的,现实世界的场景,像上面这样的东西可能就足够了.显然,如果你不让用户改变相机的音高,答案就更容易了.


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

如果你有CLLocationCoordinate2D,你可以将它转换为a 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];
}
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式致电:

[self moveCenterByOffset:CGPointMake(0, 100) from:coordinate];
Run Code Online (Sandbox Code Playgroud)

不幸的是,这仅coordinate在您开始之前可见时才有效,因此您可能必须先转到原始坐标,然后调整中心.


n13*_*n13 7

可靠地执行此操作的唯一方法是使用以下内容:

- (void)setVisibleMapRect:(MKMapRect)mapRect edgePadding:(UIEdgeInsets)insets animated:(BOOL)animate
Run Code Online (Sandbox Code Playgroud)

为了在给定您想要居中的地图区域的情况下执行此操作,您必须将地图区域转换为MKMapRect.显然,使用边缘填充作为像素偏移.

请参阅此处: 将MKCoordinateRegion转换为MKMapRect

评论:我觉得很奇怪,这是唯一的方法,因为MKMapRect不是通常用于MKMapView的东西 - 所有转换方法都适用于MKMapRegion.但是,好吧,至少它有效.在我自己的项目中测试过.


Ste*_*omp 6

对于斯威夫特:

import MapKit

extension MKMapView {

func moveCenterByOffSet(offSet: CGPoint, coordinate: CLLocationCoordinate2D) {
    var point = self.convert(coordinate, toPointTo: self)

    point.x += offSet.x
    point.y += offSet.y

    let center = self.convert(point, toCoordinateFrom: self)
    self.setCenter(center, animated: true)
}

func centerCoordinateByOffSet(offSet: CGPoint) -> CLLocationCoordinate2D {
    var point = self.center

    point.x += offSet.x
    point.y += offSet.y

    return self.convert(point, toCoordinateFrom: self)
}
}
Run Code Online (Sandbox Code Playgroud)