• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios - 可见区域外的目标注释方向

[复制链接]
菜鸟教程小白 发表于 2022-12-13 06:05:43 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我想在屏幕的所有侧面显示方向图像。例如。如果目标的位置是用户位置的右侧并且在可见 map 区域之外,那么我想添加一个方向图像,如下图所示(绿色注释是用户位置,红色是目标的方向,超出屏幕范围): enter image description here

执行此操作的标准方法是什么?



Best Answer-推荐答案


最简单的方法是在 map 上方的每个基点处放置四个“指针” View 。然后,随着用户移动 map (使用 mapView:regionDidChangeAnimated: 委托(delegate)方法)确定应该显示哪个指针。隐藏所有其他的;然后显示正确的。此外,对指针应用变换,以便如您所做的那样表示方位角。

以下是具有上述配置的 Storyboard 的屏幕截图: storyboard

这是一个示例实现(当然,代码不是最佳的。):

//
//  MapViewController.m
//  AnimationTest
//
//  Created by Scott Atkinson on 4/17/15.
//

#import "MapViewController.h"

@import MapKit;

typedef NS_ENUM(NSInteger, CardinalPoint) {
    North,
    South,
    East,
    West
};

@interface MapViewController () <MKMapViewDelegate>

@property (weak, nonatomic) IBOutlet MKMapView *mapView;

// Views that show cardinal points on the map (Only one should be shown at a time)
@property (weak, nonatomic) IBOutlet UIView *northPointerView;
@property (weak, nonatomic) IBOutlet UIView *eastPointerView;
@property (weak, nonatomic) IBOutlet UIView *westPointerView;
@property (weak, nonatomic) IBOutlet UIView *southPointerView;

// Location to show on the map
@property (strong, nonatomic) CLLocation * targetLocation;

@end

@implementation MapViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self hidePointerViews];

    // Add the location to the map
    self.targetLocation = [[CLLocation alloc] initWithLatitude:37.331898 longitude:-122.029824];
    MKPlacemark * placemark = [[MKPlacemark alloc] initWithCoordinate:self.targetLocation.coordinate addressDictionary:nil];
    [self.mapView addAnnotation:placemark];
}


// ******************** MKMapViewDelegate ********************
#pragma mark - MKMapViewDelegate

// As the map moves, update the cardinal pointer views
- (void) mapViewMKMapView *)mapView regionDidChangeAnimatedBOOL)animated {
    if([self isCurrentLocationVisible] && ![self isTargetLocationVisible]) {
        // The user location is visible, but the target is not, so show a pointer
        double bearing = [self bearingToLocation:self.targetLocation fromLocation:self.mapView.userLocation.location];
        [self showCardinalPointDirection:bearing];

    } else {
        // Hide the pointers
        [self hidePointerViews];
    }
}


// ******************** Coordinate Helpers ********************
#pragma mark - Coordinate Helpers

- (BOOL) isCurrentLocationVisible {
    return MKMapRectContainsPoint(self.mapView.visibleMapRect,
                                  MKMapPointForCoordinate(self.mapView.userLocation.coordinate));
}

- (BOOL) isTargetLocationVisible {
    return MKMapRectContainsPoint(self.mapView.visibleMapRect,
                                  MKMapPointForCoordinate(self.targetLocation.coordinate));
}

// From: http://stackoverflow.com/questions/3925942/cllocation-category-for-calculating-bearing-w-haversine-function
double DegreesToRadians(double degrees) {return degrees * M_PI / 180.0;};
double RadiansToDegrees(double radians) {return radians * 180.0/M_PI;};

/// Calculate the bearing between two points
-(double) bearingToLocationCLLocation *) destinationLocation fromLocationCLLocation *) fromLocation {

    double lat1 = DegreesToRadians(fromLocation.coordinate.latitude);
    double lon1 = DegreesToRadians(fromLocation.coordinate.longitude);

    double lat2 = DegreesToRadians(destinationLocation.coordinate.latitude);
    double lon2 = DegreesToRadians(destinationLocation.coordinate.longitude);

    double dLon = lon2 - lon1;

    double y = sin(dLon) * cos(lat2);
    double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
    double radiansBearing = atan2(y, x);

    if(radiansBearing < 0.0)
        radiansBearing += 2*M_PI;

    return RadiansToDegrees(radiansBearing);
}

// ******************** Pointer View ********************
#pragma mark - Pointer View

- (void) hidePointerViews {
    self.northPointerView.hidden =
    self.southPointerView.hidden =
    self.eastPointerView.hidden =
    self.westPointerView.hidden = YES;
}

- (void) showCardinalPointDirectiondouble) bearing {
    CardinalPoint point = [self cardinalPointWithBearing:bearing];

    // Determine which pointer should be shown based on the bearing
    UIView * activePointer;
    switch (point) {
        case North:
            activePointer = self.northPointerView;
            break;
        case South:
            activePointer = self.southPointerView;
            break;
        case East:
            activePointer = self.eastPointerView;
            break;
        case West:
            activePointer = self.westPointerView;
            break;
    }

    // Rotate the pointer to show the bearing
    activePointer.transform = CGAffineTransformMakeRotation(DegreesToRadians(bearing));

    // Hide all pointers except the pertinent one
    [self hidePointerViews];
    activePointer.hidden = NO;
}

/// Returns the cardinal point for a given bearing (in Degrees)
- (CardinalPoint) cardinalPointWithBearingdouble) bearing {
    if (bearing > 45.0 && bearing <= 135.0) {
        return East;
    } else if (bearing > 135.0 && bearing <= 225.0) {
        return South;
    } else if (bearing > 225.0 && bearing <= 315.0) {
        return West;
    } else {
        return North;
    }
}
@end

此外,指针旋转基于userLocationtargetLocation 之间的方位。感觉有点奇怪。根据其他点进行旋转可能更好。也许在那一刻可见区域的中心......

关于ios - 可见区域外的目标注释方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29271692/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap