在MKMapView上旋转注解图像

我想旋转一个图像,添加到MKMapView作为注释。

这是代码:

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation: (id<MKAnnotation>)annotation { if (! [annotation isKindOfClass:[IGAMapAnnotation class]]) { //return default view if annotation is NOT of type IGAMapAnnotation... return nil; } MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"IGAMapAnnotation"]; if (annotationView == nil) { annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"IGAMapAnnotation"]; annotationView.enabled = YES; annotationView.canShowCallout = YES; annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; } else { annotationView.annotation = annotation; } IGAMapAnnotation *myLocation = (IGAMapAnnotation *) annotation; // THIS IS IT! if ([myLocation.type isEqual: @"PLANE"]) { UIImage *planeImage = [UIImage imageNamed:@"planetracked.png"]; UIImageView *planeImageView = [[UIImageView alloc]initWithImage:planeImage]; planeImageView.transform = CGAffineTransformMakeRotation(M_PI_2); annotationView.image = planeImageView; } return annotationView; } 

它显然给了我一个错误,因为注释View.image应该分配一个图像,而不是UIImageView。 我已经尝试过各种旋转图像的方法,例如:

 - (UIImage *)rotateImage:(UIImage *)image onDegrees:(NSString *)heading { double angle = [heading doubleValue]; CGSize s = {image.size.width, image.size.height}; UIGraphicsBeginImageContext(s); CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(ctx, 0,image.size.height); CGContextScaleCTM(ctx, 1.0, -1.0); CGContextRotateCTM(ctx, 2*M_PI*angle/360); CGContextDrawImage(ctx,CGRectMake(0,0,image.size.width, image.size.height),image.CGImage); UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

他们也不工作 – 没有图像出现在地图上。

任何人都知道如何旋转MKMapView上的注释图像?

万分感谢!

代替:

 annotationView.image = planeImageView; 

这是肯定错误的( image属性是UIImageplaneImageView是一个UIImageView ),使用addSubview:UIImageView添加到注释视图(留下视图的image属性nil和未使用)。

但是,您还需要进行其他调整,以便:

  • 图像完全以坐标(而不是其angular落)为中心
  • 点击图像上的任何位置都会显示标注(而不是只显示一个特定的angular落)

要做这些事情,增加两个视图的帧大小,以考虑从旋转(假设图像是方形的原始宽度的2倍的平方根)可能的最大宽度,并将图像视图的contentMode为“center”所以图像不会因这些帧大小变化而失真。

另一个大问题是,如果你有IGAMapAnnotation type不是“PLANE”,他们可能是:

  • 如果创build了新的注解视图,则不可见(因为未设置image也没有将任何子视图添加到注释视图中),或者,
  • 显示一个“平面”图像与其他注释的标题,因为注释视图已经出队(并正在重新使用另一个注释)。

为了避免两种types的注释(“平面”/“不是平面”)重复使用彼此的视图,我build议为每个types不是每个注释)使用不同的重用标识符,并将types特定的更改应用于视图。

修改后的viewForAnnotation方法如下所示:

 -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { if (! [annotation isKindOfClass:[IGAMapAnnotation class]]) { //return default view if annotation is NOT of type IGAMapAnnotation... return nil; } IGAMapAnnotation *myLocation = (IGAMapAnnotation *)annotation; BOOL typeIsPlane = [myLocation.type isEqualToString:@"PLANE"]; int planeImageViewTag = 42; NSString *reuseId = typeIsPlane ? @"IGAMapAnnotationPlane" : @"IGAMapAnnotationOther"; MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseId]; if (annotationView == nil) { annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId]; annotationView.enabled = YES; annotationView.canShowCallout = YES; annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; if (typeIsPlane) { //Here, just add the image view to the annotation view with no //rotation. Only want to add the image view to the annotation //view ONCE when the annotation view is initially created. If //view is dequeued, it will already have an image view and we //just update its rotation. UIImage *planeImage = [UIImage imageNamed:@"planetracked.png"]; UIImageView *planeImageView = [[UIImageView alloc] initWithImage:planeImage]; planeImageView.tag = planeImageViewTag; planeImageView.contentMode = UIViewContentModeCenter; [annotationView addSubview: planeImageView]; CGRect avFrame = annotationView.frame; //"1.5" on next line is the square root of 2 rounded up a bit. avFrame.size = CGSizeMake(planeImage.size.width*1.5, planeImage.size.height*1.5); annotationView.frame = avFrame; planeImageView.frame = annotationView.frame; } else { //If this IGAMapAnnotation is not a "plane", //show some other default image. //(Or, you could return nil to show a default red pin.) annotationView.image = [UIImage imageNamed:@"NotAPlane.png"]; //May or may not need to set centerOffset. //Either remove or adjust 0,0 as needed to //center the image on the coordinates. annotationView.centerOffset = CGPointMake(0, 0); } } else { annotationView.annotation = annotation; } //At this point, we have a new or dequeued annotation view ready //and pointing to the current annotation. //Now make any annotation-specific changes to the view... if (typeIsPlane) { UIImageView *planeImageView = (UIImageView *)[annotationView viewWithTag:planeImageViewTag]; planeImageView.transform = CGAffineTransformMakeRotation(M_PI_2); //Replace M_PI_2 with rotation specific to this annotation's heading. } return annotationView; } 

顺便说一句,使用isEqualToString:而不是isEqual:NSString s。


对于removeAnnotations:问题,必须是mapLocations包含注释的实例。 要删除现有的注释,您必须提供对原来添加的完全相同对象的引用。

如果您总是删除所有注释并重新添加所有注释,则可以执行[self.mapView removeAnnotations:self.mapView.annotations];

如果你只是删除一些注释,你需要保持引用最初添加或迭代通过地图视图的annotations数组,并确定哪些应该被删除(保留一个临时的NSMutableArray作为“删除注释”列表)然后调用removeAnnotations:将该注释列表删除。

以下似乎工作。 百万感谢安娜,没有它没有它!

 -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { if (! [annotation isKindOfClass:[IGAMapAnnotation class]]) { return nil; } IGAMapAnnotation *myLocation = (IGAMapAnnotation *) annotation; BOOL typeIsPlane = [myLocation.navaidType isEqualToString:@"PLANE"]; BOOL typeIsOne = [myLocation.navaidType isEqualToString:@"ONE"]; BOOL typeIsTwo = [myLocation.navaidType isEqualToString:@"TWO"]; BOOL typeIsThree = [myLocation.navaidType isEqualToString:@"THREE"]; int planeImageViewTag = 42; NSString *reuseId; if (typeIsPlane) reuseId = @"IGAMapAnnotationPlane"; else if (typeIsOne) reuseId = @"IGAMapAnnotationOne"; else if (typeIsTwo) reuseId = @"IGAMapAnnotationTwo"; else if (typeIsThree) reuseId = @"IGAMapAnnotationThree"; else reuseId = @"IGAMapAnnotationOther"; MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseId]; if (annotationView == nil) { annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId]; annotationView.enabled = YES; annotationView.canShowCallout = YES; annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; if (typeIsPlane) { UIImage *planeImage = [UIImage imageNamed:@"mapPLANE.png"]; UIImageView *planeImageView = [[UIImageView alloc] initWithImage:planeImage]; planeImageView.tag = planeImageViewTag; planeImageView.contentMode = UIViewContentModeCenter; [annotationView addSubview: planeImageView]; CGRect avFrame = annotationView.frame; //"1.5" on next line is the square root of 2 rounded up a bit. avFrame.size = CGSizeMake(planeImage.size.width*1.5, planeImage.size.height*1.5); annotationView.frame = avFrame; planeImageView.frame = annotationView.frame; } else if (typeIsOne) { annotationView.image = [UIImage imageNamed:@"one.png"]; annotationView.centerOffset = CGPointMake(0, 0); } else if (typeIsTwo) { annotationView.image = [UIImage imageNamed:@"two.png"]; annotationView.centerOffset = CGPointMake(0, 0); } else if (typeIsThree) { annotationView.image = [UIImage imageNamed:@"three.png"]; annotationView.centerOffset = CGPointMake(0, 0); } else return nil; } else { annotationView.annotation = annotation; } if (typeIsPlane) { // Convert current heading string to double double headingDouble = [currentHeading doubleValue]; UIImageView *planeImageView = (UIImageView *)[annotationView viewWithTag:planeImageViewTag]; planeImageView.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(headingDouble)); } return annotationView; }