【问题标题】:How to rotate the arrow image along with MKMapview rotation如何随 MKMapview 旋转一起旋转箭头图像
【发布时间】:2023-04-03 00:35:01
【问题描述】:

我的视图控制器有两个自定义注释视图作为源和目标。我成功地在它们之间建立了一个覆盖路径,并将目标箭头图标的方向设置在同一行覆盖路径中。现在,当我通过按键盘上的“Alt”键在模拟器上旋转地图时,箭头图标不会随覆盖路径方向旋转。为了旋转箭头图标,我采用了地图视图摄像机角度并尝试通过该摄像机角度更新箭头图标方向,但似乎无法正常工作。下面是代码sn-p。我怎样才能做到这一点 ?有没有更好的解决方案?任何形式的帮助都会非常显着。谢谢。

在我的 ViewController.m 文件中 -

#import "MoreController.h"
#import "Annotation.h"

@interface MoreController ()
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property (strong, nonatomic) Annotation *destination;
@end

@implementation MoreController

- (void) makeOverlayPathBetweenConsecutiveLocation:(Annotation *)source toDest:(Annotation *)destination {
    MKMapPoint startPoint = MKMapPointForCoordinate(source.coordinate);
    MKMapPoint endPoint = MKMapPointForCoordinate(destination.coordinate);

    MKMapPoint *pointArray = malloc(sizeof(CLLocationCoordinate2D) * 2);
    pointArray[0] = startPoint;
    pointArray[1] = endPoint;
    MKPolyline *routeLine = [MKPolyline polylineWithPoints:pointArray count:2];
    [self.mapView addOverlay:routeLine];
}

- (CLLocationDirection) getDirection:(Annotation *)source toDest:(Annotation *)destination {
    CLLocation *startLocation = [source getLocation];
    CLLocation *endLocation = [destination getLocation];

    //Determine the direction
    double lat1 = startLocation.coordinate.latitude * M_PI / 180.0;
    double lon1 = startLocation.coordinate.longitude * M_PI / 180.0;
    double lat2 = endLocation.coordinate.latitude * M_PI / 180.0;
    double lon2 = endLocation.coordinate.longitude * M_PI / 180.0;

    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);

    CLLocationDirection directionBetweenPoints = radiansBearing * 180.0 / M_PI;

    return directionBetweenPoints;
}


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    CLLocationCoordinate2D sourceCoordinate = {
        51.0455555556,
        1.94722222222
    };

    CLLocationCoordinate2D destCoordinate = {
        51.0491666667,
        1.80805555556
    };

    Annotation *sourceAnnotation = [[Annotation alloc] initWithCoordinate:sourceCoordinate forTitle:@"Source" forSubTitle:@"From"];
    [sourceAnnotation setTypeOfAnnotation:PIN_ANNOTATION];

    Annotation *destAnnotation = [[Annotation alloc] initWithCoordinate:destCoordinate forTitle:@"Destination" forSubTitle:@"To"];
    [destAnnotation setTypeOfAnnotation:ARROW_ANNOTATION];

    [destAnnotation setDirection:[self getDirection:sourceAnnotation toDest:destAnnotation]];
    [self makeOverlayPathBetweenConsecutiveLocation:sourceAnnotation toDest:destAnnotation];

    [self.mapView addAnnotation:sourceAnnotation];
    [self.mapView addAnnotation:destAnnotation];
    [self.mapView setRegion:MKCoordinateRegionMake(destCoordinate, MKCoordinateSpanMake(0.3, 0.3))
                   animated:YES];

    self.destination = destAnnotation;
}

- (MKOverlayRenderer *) mapView:(MKMapView *) mapView viewForOverlay:(id) overlay {
    if ([overlay isKindOfClass:[MKPolyline class]]) {
        MKPolyline *route = overlay;
        MKPolylineRenderer *routeRenderer = [[MKPolylineRenderer alloc] initWithPolyline:route];
        routeRenderer.strokeColor = [UIColor blueColor];
        routeRenderer.lineWidth = 2.0;
        return routeRenderer;
    } else {
        return nil;
    }
}

//Determine the direction of arrow icon
- (UIImage*)rotatedImage:(UIImage*)sourceImage byDegreesFromNorth:(double)degrees {
    CGSize rotateSize =  sourceImage.size;
    UIGraphicsBeginImageContext(rotateSize);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, rotateSize.width/2, rotateSize.height/2);
    CGContextRotateCTM(context, ( degrees * M_PI/180.0 ) );
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextDrawImage(UIGraphicsGetCurrentContext(),
                       CGRectMake(-rotateSize.width/2,-rotateSize.height/2,rotateSize.width, rotateSize.height),
                       sourceImage.CGImage);
    UIImage *rotatedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return rotatedImage;
}

//Make custom annotaion pin if the annotation is of ship's current position
- (MKAnnotationView *) mapView:(MKMapView *) mapView viewForAnnotation: (id) annotation {
    MKAnnotationView *customAnnotationView;
    NSString *reuseId = @"custom";

    if ([annotation isKindOfClass:[Annotation class]]){
        Annotation *_annotation = (Annotation*)annotation;
        if ([[_annotation typeOfAnnotation] isEqualToString:PIN_ANNOTATION]) {
            customAnnotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
            [customAnnotationView setCanShowCallout:YES];
        } else {
            customAnnotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];

            //Determine the direction
            UIImage *arrowImage = [UIImage imageNamed:@"arrow"];
            double direction = [_annotation direction];
            [customAnnotationView setImage:[self rotatedImage:arrowImage byDegreesFromNorth:direction]];
            [customAnnotationView setCanShowCallout:YES];
        }
    } else {
        return nil;
    }

    return customAnnotationView;
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    MKMapCamera *camera = self.mapView.camera;
    CLLocationDirection mapAngle = camera.heading;
    NSLog(@"map angle :  %f", mapAngle);

    if (mapAngle && (self.destination != nil)) {
        //Determine the arrow icon direction
        [self.mapView removeAnnotation:self.destination];
        [self.destination setDirection:mapAngle];
        [self.mapView addAnnotation:self.destination];
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

和我的自定义注释文件 -

#import "Annotation.h"

@implementation Annotation

@synthesize coordinate=_coordinate;

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate forTitle:(NSString *)title forSubTitle:(NSString *)territory {
    self = [super init];

    if (self != nil) {
        _coordinate = coordinate;
        _name = title;
        _territory = territory;
    }

    return self;
}

-(CLLocation *) getLocation {
    return [[CLLocation alloc] initWithLatitude: _coordinate.latitude longitude: _coordinate.longitude];
}


//Add a Callout
- (NSString*) title {
    return self.name;
}

//Add a Callout
- (NSString*) subtitle {
    return self.territory;
}

@end

【问题讨论】:

    标签: ios objective-c annotations mkmapview cllocationmanager


    【解决方案1】:

    它在哪些方面工作不正常?

    您的代码中至少有一个明显的错误。根据 CoreLocation 文档,CLLocationDirection 必须为正,负值表示方向无效。要在您的 getDirection 方法中强制此替换字符串:

    CLLocationDirection directionBetweenPoints = radiansBearing * 180.0 / M_PI;
    

    有两个如下:

    double angle = radiansBearing * 180.0 / M_PI;
    CLLocationDirection directionBetweenPoints = (angle>=0)? angle : 360+angle;
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-07
      • 1970-01-01
      • 2011-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多