在MKMapView上旋转注释图像 [英] Rotate annotation image on MKMapView

查看:99
本文介绍了在MKMapView上旋转注释图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试旋转作为注释添加到MKMapView的图像.

I am trying to rotate an image that is added to MKMapView as an annotation.

这是代码:

-(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;
}

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

It obviously gives me an error as annotationView.image should assign an image and not UIImageView. I have tried various methods rotating just an image, for example this:

- (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;
}

它们也不起作用-地图上没有图像.

They do not work either -- no image appears on the map.

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

Anyone knows how to rotate an annotation image on MKMapView?

百万感谢!

推荐答案

而不是:

annotationView.image = planeImageView;

这绝对是错误的(image属性是UIImage,而planeImageViewUIImageView),请使用addSubview:UIImageView添加到注释视图中(保留视图的image属性nil和未使用).

which is definitely wrong (the image property is a UIImage while planeImageView is a UIImageView), use addSubview: to add the UIImageView to the annotation view (leaving the view's image property nil and unused).

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

However, you'll also need to make some other adjustments so that:

  • 图像正好位于坐标中心(而不是其角),并且
  • 在图像上的任意位置点击都会调出标注(而不只是一个特定的角)

要执行这些操作,请增加两个视图的帧大小,以考虑旋转可能产生的最大宽度(假设图像是正方形,则为原始宽度的2倍的平方根),然后设置图像视图的居中",这样图像就不会因这些帧大小的变化而失真.

To do these things, increase the frame sizes of both views to account for the maximum width possible from a rotation (which is the square root of 2 times the original width assuming image is a square) and set the image view's contentMode to "center" so the image is not distorted by these frame size changes.

另一个大问题是,如果您的IGAMapAnnotationtype不是"PLANE",它们将是:

The other big issue is that if you have IGAMapAnnotations whose type is not "PLANE", they will either be:

  • 如果创建了 new 注释视图(因为未设置image或未将任何子视图添加到注释视图),则不可见,或者
  • 显示一个带有其他 other 批注标题的平面"图像,因为该批注视图已出队(并且已被重新用于另一个批注).
  • Invisible if a new annotation view is created (because image is not set nor is any subview added to the annotation view), or,
  • Showing a "plane" image with the heading of some other annotation because the annotation view was dequeued (and is being re-used for another annotation).

为避免两种类型的注释(平面"/非平面")重复使用彼此的视图,我建议为每种 type (不是每个注释),然后将特定于类型的更改应用于视图.

To avoid the two types of annotations ("plane"/"not plane") from re-using each other's views, I suggest using a different re-use identifier for each type (not each annotation) and apply type-specific changes to the view.

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

The revised viewForAnnotation method would look like this:

-(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;
}

顺便说一句,在NSString中使用isEqualToString:代替isEqual:.


对于removeAnnotations:问题,必须是mapLocations包含地图上注释的 new 实例.要删除现有注释,您必须提供与最初添加的对象完全相同的引用.

By the way, use isEqualToString: instead of isEqual: with NSStrings.


For the removeAnnotations: problem, it must be that mapLocations contains new instances of the annotations on the map. To remove existing annotations, you have to provide a reference to the exact same objects that were added originally.

如果您始终删除 all 注释并重新添加 all 注释,则只需执行[self.mapView removeAnnotations:self.mapView.annotations];.

If you are always removing all annotations and re-adding all annotations, you can just do [self.mapView removeAnnotations:self.mapView.annotations];.

如果仅删除 some 批注,则需要保留对最初添加的批注的引用,或通过地图视图的annotations数组进行迭代,并标识应删除的批注(保持临时NSMutableArray作为要删除的注释"列表),然后使用要删除的注释列表调用removeAnnotations:.

If you are only removing some annotations, you'll need to keep references to the ones originally added or iterate through the map view's annotations array and identify which ones should be deleted (keep a temporary NSMutableArray as the list of "annotations to remove") and then call removeAnnotations: with that list of annotations to remove.

这篇关于在MKMapView上旋转注释图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆