2011-11-27 130 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 
    } 
} 
相關問題