2011-11-27 156 views
5

我还有什么调整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

回答

22

实际上在默认MKMapView-注释(例如销或图像)和标注(例如气泡)保持相同的尺寸你在放大或缩小。它们不会缩放。但我明白你的点对多点相对于地图,他们似乎成长为地图缩小和收缩的地图在放大

所以有两种解决方案,您的问题和他们的工作方式略有不同:

  1. 从MKMapViewDelegate协议参考实现-(void)mapView:(MKMapView *)pMapView regionDidChangeAnimated:(BOOL)animated - 你已经完成了。
  2. UIPinchGestureRecognizer附加到MKMapView对象,然后执行操作。

选项#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但我的意见是,它不是一样干净的调整大小。

下面是一些示例代码:

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

如果一切正常,不要忘记将其标记为答案。

+0

嘿。我会尝试这个,谢谢你的一个很好的答案。并且不需要担心:) – shannoga

+1

这在iOS6上无效 – user501836

+5

这是正确的,不再适用于iOS6。任何人都想出了一个解决方案? – Bach

1

对不起,我的英语不好......但我只是想帮助别人。

非常感谢你,Funktional。你的答案很棒......它完美地工作在iOS5上!但是这在iOS6上是无效的,现在看来目前还没有解决方案来解决这个问题。

但最后,我用愚蠢/静态的方式解决了这个问题,它在iOS上都能正常工作。我不会解释太多。这是我在我的项目中所做的。

  1. 用于mkannotation的图像被命名为pin.png(尺寸20×20是)

  2. 我创建了五个更多的图像具有不同的大小不同的缩放等级(18×18,16×16,14×14,12×12,10×10 ),它们被命名为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的页头] 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;} 
    

对坏的编码和英语难过一次。

1

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

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)) 
} 
+0

它仅适用于缩小时新创建的注释,已创建的注释在缩小时具有不同的大小,您是否有任何解决方案 –

1

@ Funktional在斯威夫特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 
    } 
} 
相关问题