如何在 Mapkit MapView 上显示指南针/航向

发布于 2024-09-05 22:57:38 字数 522 浏览 10 评论 0原文

在 iPhone 3GS 上的“地图”应用程序中,您可以单击该图标,该图标通常会显示您的位置两次,蓝点会获得看起来像头灯的光束,基本上会向您显示您在地图上面对的方向并旋转图像因此。

使用 MapKit MapView 可以使用此选项吗?

我知道我可以通过类似

- (void)locationManager:(CLLocationManager *) manager didUpdateHeading:(CLHeading *) newHeading {

// 如果准确性有效,则处理事件来获取标题。

if (newHeading.headingAccuracy > 0) {

    CLLocationDirection theHeading = newHeading.magneticHeading;
    ...
}

我不知道如何在 Mapkit 中获得漂亮的头灯效果,而且似乎没有任何文档。

有什么想法吗?

on the iPhone 3GS in the "Maps" app you can click the icon which usually shows your position twice and the blue dot gains what looks like a beam from a headlamp, basically showing you the direction you are facing on the map and rotating the image accordingly.

Is this option available using MapKit MapView ?

I'm know that I can get my heading with something like

- (void)locationManager:(CLLocationManager *) manager didUpdateHeading:(CLHeading *) newHeading {

// If the accuracy is valid, process the event.

if (newHeading.headingAccuracy > 0) {

    CLLocationDirection theHeading = newHeading.magneticHeading;
    ...
}

}

but I don't know how to get that nice headlamp effect in Mapkit and there doesn't seem to be any documentation.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

秋意浓 2024-09-12 22:57:38

添加用户跟踪模式也有帮助。我知道我迟到了,但可能对像我这样的其他开发人员有帮助:)

self.mapView.userTrackingMode = RMUserTrackingModeFollowWithHeading;

Adding user tracking mode also helps. I know I am late, but possibly a help to other developers like me :)

self.mapView.userTrackingMode = RMUserTrackingModeFollowWithHeading;
尘世孤行 2024-09-12 22:57:38

我找到了一个解决方案:

我使用可用的标题信息旋转地图,

[mapView setTransform:CGAffineTransformMakeRotation(heading.magneticHeading * M_PI / -180.0)];

因此“光束”始终指向设备的顶部。我现在只是在地图顶部显示一个 ImageView 并更改它在 locationManager:didUpdateToLocation:fromLocation: 中的位置:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
        // scroll to new location
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000);
    [self.mapView setRegion:region animated:YES];

        // set position of "beam" to position of blue dot
    self.headingAngleView.center = [self.mapView convertCoordinate:newLocation.coordinate toPointToView:self.view];
        // slightly adjust position of beam
    self.headingAngleView.frameTop -= self.headingAngleView.frameHeight/2 + 8;
 }

其中,frameTop 和frameHeight 是frame.origin.y 和frame.size.height 的快捷方式。
它并不理想,有时当点改变其位置时会缺少一点,但我对解决方案很满意,因为它有效。

看看我的开源框架 MTLocation,它完成了这一切(以及为您提供的许多其他很酷的地图相关内容):

MT位置

I found a solution:

I rotate the map using the available heading-information with

[mapView setTransform:CGAffineTransformMakeRotation(heading.magneticHeading * M_PI / -180.0)];

Therefore the "beam" always points to the top of the device. I now just display an ImageView on top of the map and change it's position in locationManager:didUpdateToLocation:fromLocation:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
        // scroll to new location
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000);
    [self.mapView setRegion:region animated:YES];

        // set position of "beam" to position of blue dot
    self.headingAngleView.center = [self.mapView convertCoordinate:newLocation.coordinate toPointToView:self.view];
        // slightly adjust position of beam
    self.headingAngleView.frameTop -= self.headingAngleView.frameHeight/2 + 8;
 }

Whereby frameTop and frameHeight are shortcuts for frame.origin.y and frame.size.height.
It is not ideal and sometimes lacks a little bit when the dot changes it's position, but I'm happy with the solution b/c it works.

Have a look at my OpenSource framework MTLocation which does this all (and a lot of other cool Map-related stuff for you):

MTLocation

静若繁花 2024-09-12 22:57:38

其他答案的轮换逻辑很好,但是依赖位置管理器委托方法不会产生好的解决方案。 “光束”图像很少会与蓝点位于同一位置,并且会多次反弹。

最好的解决方案是获取对蓝点视图的引用,并将“光束”图像作为子视图添加到其中。我选择了一个正方形的光束图像,光束在顶部,周围都是透明的。想象一下蓝点位于图像的中心。


// An MKMapViewDelegate method. Use this to get a reference to the blue dot annotation view as soon as it gets added
- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views {

    for (MKAnnotationView *annotationView in views) {

        // Get the user location view, check for all of your custom annotation view classes here
        if (![annotationView isKindOfClass:[MKPinAnnotationView class]])
        {
            self.userLocationAnnotationView = annotationView;
            gotUsersLocationView = YES;
        }
    }
}


// Adds the 'viewPortView' to the annotation view. Assumes we have a reference to the annotation view. Call this before you start listening to for heading events.
- (void)addViewportToUserLocationAnnotationView {
    TTDASSERT(self.userLocationAnnotationView != nil);
    if (self.userLocationAnnotationView == nil) {
        // No reference to the view, can't do anything
        return;
    }

    if (self.viewPortView == nil) {
        self.viewPortView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"map_viewport.png"]] autorelease];
    }

    [self.userLocationAnnotationView addSubview:self.viewPortView];
    [self.userLocationAnnotationView sendSubviewToBack:self.viewPortView];

    self.viewPortView.frame = CGRectMake((-1 * self.viewPortView.frame.size.width/2) + self.userLocationAnnotationView.frame.size.width/2,
                                         (-1 * self.viewPortView.frame.size.height/2) + self.userLocationAnnotationView.frame.size.height/2,
                                         self.viewPortView.frame.size.width,
                                         self.viewPortView.frame.size.height);
}

The rotating logic of the other answers are good, however relying on the location manager delegate methods won't result in a good solution. The "beam" image will rarely be in the same place as the blue dot and will bounce around a lot.

The best solution is to get a reference to the blue dot view, and add the "beam" image as a subview to it. I went with a beam image that was a square, with the beam up top and transparency all around it. Imagine the blue dot being in the center of the image.


// An MKMapViewDelegate method. Use this to get a reference to the blue dot annotation view as soon as it gets added
- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views {

    for (MKAnnotationView *annotationView in views) {

        // Get the user location view, check for all of your custom annotation view classes here
        if (![annotationView isKindOfClass:[MKPinAnnotationView class]])
        {
            self.userLocationAnnotationView = annotationView;
            gotUsersLocationView = YES;
        }
    }
}


// Adds the 'viewPortView' to the annotation view. Assumes we have a reference to the annotation view. Call this before you start listening to for heading events.
- (void)addViewportToUserLocationAnnotationView {
    TTDASSERT(self.userLocationAnnotationView != nil);
    if (self.userLocationAnnotationView == nil) {
        // No reference to the view, can't do anything
        return;
    }

    if (self.viewPortView == nil) {
        self.viewPortView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"map_viewport.png"]] autorelease];
    }

    [self.userLocationAnnotationView addSubview:self.viewPortView];
    [self.userLocationAnnotationView sendSubviewToBack:self.viewPortView];

    self.viewPortView.frame = CGRectMake((-1 * self.viewPortView.frame.size.width/2) + self.userLocationAnnotationView.frame.size.width/2,
                                         (-1 * self.viewPortView.frame.size.height/2) + self.userLocationAnnotationView.frame.size.height/2,
                                         self.viewPortView.frame.size.width,
                                         self.viewPortView.frame.size.height);
}
不顾 2024-09-12 22:57:38

我可以想到一种方法,虽然我没有实施,但可能对你有一点帮助。

  1. 首先,您需要一个带有您选择的指针的图像,该指针必须指向上方 90 度。
  2. 现在在您的 MapKit 中关闭当前位置标记。
  3. 在您的 didUpdateHeading 中,使用 x 和 y 值来计算方向的角度。
  4. 使用此角度旋转指针的图像
  5. 使用此旋转图像作为地图中的注释图钉。
  6. 您需要经常更新指针的位置。

请发布您对上述方法的建议/更改。

I could think of one method, though I have not implemented but may help you a bit.

  1. Firstly you need an image with a pointer of your choice, this pointer must be pointing Upwards 90degree.
  2. Now in your MapKit off the Current Location Marker.
  3. In your didUpdateHeading use the x and y values to calculate the angle of the direction.
  4. Use this angle to rotate the image of the pointer
  5. Use this rotated image as a Annotation Pin in your map.
  6. You would require to update the position of the pointer frequently.

Please post your suggestions/changes for the above approach.

奶气 2024-09-12 22:57:38

Swift 3 实施

mapView.userTrackingMode = MKUserTrackingMode.followWithHeading

Swift 3 implementation

mapView.userTrackingMode = MKUserTrackingMode.followWithHeading
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文