调整MKAnnotationView图像的大小当地图放大和缩小时?

时间:2011-11-27 15:42:15

标签: ios mkmapview mkannotationview

我有什么

我在地图上有大约150个MKAnnotationViews。 每个MKAnnotationView都有一个替换默认引脚的图像。

现在发生了什么

当地图放大时,MKAnnotationViews会变小,而缩小时则相反。

我希望发生什么

我希望它能够成为另一种方式。因为当地图很小时我希望MKAnnotationViews会更小,所以用户可以看到所有这些,当他放大时我希望它们会更大。

到目前为止我的代码

我知道如何获得变焦,我知道我可以将“pMapView.region.span.latitudeDelta”作为缩放量的参考。我知道我可以更改annotationView.frame。

-(void)mapView:(MKMapView *)pMapView regionDidChangeAnimated:(BOOL)animated{
    NSLog(@"mapView.region.span.latitudeDelta = %f",pMapView.region.span.latitudeDelta);
    for (id <MKAnnotation> annotation in pMapView.annotations) {
        MKAnnotationView *annotationView  = [pMapView viewForAnnotation: annotation];
    }
}

有人可以帮助我吗? 的由于 SHANI

5 个答案:

答案 0 :(得分:25)

实际上在默认的MKMapView上 - 注释(例如图钉或图像)和标注(例如气泡)保持与放大或缩小相同的尺寸。他们没有规模。但是当地图放大时,随着地图缩小和缩小,我得到了与地图的关系,它们看起来正在增长。

因此,您的问题有两种解决方案,它们的工作方式略有不同:

  1. 从MKMapViewDelegate协议参考中实施-(void)mapView:(MKMapView *)pMapView regionDidChangeAnimated:(BOOL)animated - 您已经完成了。
  2. UIPinchGestureRecognizer附加到MKMapView对象,然后执行操作。
  3. 选项#1 - mapView:regionDidChangeAnimated:将被调用滚动或缩放事件 - 基本上任何时候地图区域改变顾名思义。这会导致图标的调整大小略微减少,因为地图事件的触发频率较低。

    我的首选项是选项#2 - 将UIPinchGestureRecognizer附加到MKMapView对象,然后执行操作。捏手势事件会相当快速地触发,因此您可以顺利调整图标大小。并且他们只为一个公认的捏事件开火 - 所以他们不会在滚动事件期间开火。

    调用的操作方法必须符合以下签名之一:

      

    - (void)handleGesture;
      - (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer;

    您必须小心不要覆盖地图默认缩放行为。看到这篇文章:“UIMapView:UIPinchGestureRecognizer未被调用”了解更多信息。简短的回答是你必须实现shouldRecognizeSimultaneouslyWithGestureRecognizer:并返回YES。

    这里讲的是一些示例代码:

    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        self.mapView.mapType = MKMapTypeStandard;   // also MKMapTypeSatellite or MKMapTypeHybrid
    
        // Add a pinch gesture recognizer
        UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)];
        pinchRecognizer.delegate = self;
        [self.mapView addGestureRecognizer:pinchRecognizer];
        [pinchRecognizer release];
    }
    
    #pragma mark -
    #pragma mark UIPinchGestureRecognizer
    
    - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinchRecognizer {
        if (pinchRecognizer.state != UIGestureRecognizerStateChanged) {
            return;
        }
    
        MKMapView *aMapView = (MKMapView *)pinchRecognizer.view;
    
        for (id <MKAnnotation>annotation in aMapView.annotations) {
            // if it's the user location, just return nil.
            if ([annotation isKindOfClass:[MKUserLocation class]])
                return;
    
            // handle our custom annotations
            //
            if ([annotation isKindOfClass:[MKPointAnnotation class]])
            {
                // try to retrieve an existing pin view first
                MKAnnotationView *pinView = [aMapView viewForAnnotation:annotation];
                //Format the pin view
                [self formatAnnotationView:pinView forMapView:aMapView];
            }
        }    
    }
    
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        return YES;
    }
    

    所以在这一点上 - 你再次有几个选项可以调整注释的大小。以下两个代码示例都依赖于Troy Brant's code for getting the zoom level of an MKMapView

    1. 使用变换调整注释图像和标注的大小。就个人而言,我认为转换会带来更清晰的调整大小。但在大多数情况下,不需要调整标注大小。
    2. 仅调整注释图像的大小 - 我使用Trevor Harmon's Resize a UIImage the right way但我的意见是,它看起来并不干净。
    3. 以下是一些示例代码:

      - (void)formatAnnotationView:(MKAnnotationView *)pinView forMapView:(MKMapView *)aMapView {
          if (pinView)
          {
              double zoomLevel = [aMapView zoomLevel];
              double scale = -1 * sqrt((double)(1 - pow((zoomLevel/20.0), 2.0))) + 1.1; // This is a circular scale function where at zoom level 0 scale is 0.1 and at zoom level 20 scale is 1.1
      
              // Option #1
              pinView.transform = CGAffineTransformMakeScale(scale, scale);
      
              // Option #2
              UIImage *pinImage = [UIImage imageNamed:@"YOUR_IMAGE_NAME_HERE"];
              pinView.image = [pinImage resizedImage:CGSizeMake(pinImage.size.width * scale, pinImage.size.height * scale) interpolationQuality:kCGInterpolationHigh];
          }
      }
      

      如果有效,请不要忘记将其标记为答案。

答案 1 :(得分:1)

抱歉我的英语不好......但我只想帮助别人。

非常感谢你,Funktional。你的答案很棒......它完全适用于iOS5!但这在iOS6上无效,现在似乎没有解决方案来解决这个问题。

但最后,我以愚蠢/静态的方式解决了它,它在iOS上都运行良好。我不会解释太多。这就是我在项目中所做的。

  1. mkannotation的图像名为pin.png(大小为20x20)

  2. 我为不同的缩放级别创建了五个不同大小的图像(18x18,16x16,14x14,12x12,10x10),它们被命名为pin-5.png,pin-4.png,pin-3.png ,pin-2.png,pin-1.png。

  3. 我删除了有关在formatAnnotationView中计算比例的所有代码,并添加了这一行

    NSString* imageName = 
        [NSString stringWithFormat:@"%@%@.png", 
        [imageName substringToIndex:[imageName length]-4 ], 
        [self getImageLevel]];
    
  4. 此外,请从

    更改此设置

    UIImage * pinImage = [UIImage imageNamed:@“YOUR_IMAGE_NAME_HERE”];

    UIImage * pinImage = [[UIImage alloc] initWithContentsOfFile:imageName];

  5. 添加此功能

    -(NSString *)getImageLevel{
    
    NSString* output;
    
    double zoomLevel = [self getZoomLevel:_mapview];
    
    
    if(zoomLevel >= 19.0)
        output = @"";
    else if(zoomLevel < 19.0 && zoomLevel >= 18.0)
        output = @"-5";
    else if(zoomLevel < 18.0 && zoomLevel >= 17.0)
        output = @"-4";
    else if(zoomLevel < 17.0 && zoomLevel >= 16.0)
        output = @"-3";
    else if(zoomLevel < 16.0 && zoomLevel >= 15.0)
        output = @"-2";
    else 
        output = @"-1";
    
    return output;}
    
  6. 对于糟糕的编码和英语再次抱歉。

答案 2 :(得分:1)

另一种方法是重新调整注释视图图像属性的大小。一个例子是shown in this post

答案 3 :(得分:1)

在Swift 3中,这对我有用。我的图像在19级上是100%,所以1/19给了我0.5263158,这是我的线性刻度:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {    
  if annotation is MKUserLocation {
    return nil
  }

  let mkView = MKAnnotationView(annotation: annotation, reuseIdentifier: "mkView")
  mkView.image = UIImage(named: "Foo")
  formatAnnotation(pinView: mkView, forMapView: mapView)
  return mkView;
}

func formatAnnotation(pinView: MKAnnotationView, forMapView: MKMapView) {
  let zoomLevel = forMapView.getZoomLevel()
  let scale = 0.05263158 * zoomLevel //Modify to whatever scale you need.
  pinView.transform = CGAffineTransform(scaleX: CGFloat(scale), y: CGFloat(scale))
}

答案 4 :(得分:1)

@Funktional在Swift 3中的回答:

class MapViewController: UIViewController: UIGestureRecognizerDelegate {

    @IBOutlet weak var mapView: MKMapView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // You can also add this gesture recognizer and set the delegate via storyboard
        let pinchGR = UIPinchGestureRecognizer(target: self, action: #selector(handlePinchGesture))
        pinchGR.delegate = self
        self.mapView.addGestureRecognizer(pinchGR)
    }

    // link as @IBAction when added via storyboard
    func handlePinchGesture(_ sender: UIPinchGestureRecognizer) {
        if sender.state == .ended {
            for annotation in mapView.annotations {
                if annotation is MKUserLocation {
                    continue
                }
                guard let annotationView = self.mapView.view(for: annotation) else { continue }
                let scale = -1 * sqrt(1 - pow(mapView.zoomLevel / 20, 2.0)) + 1.4
                annotationView.transform = CGAffineTransform(scaleX: CGFloat(scale), y: CGFloat(scale))
            }
        }
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

extension MKMapView {
    var zoomLevel: Double {
        return log2(360 * ((Double(self.frame.size.width) / 256) / self.region.span.longitudeDelta)) - 1
    }
}