2011-11-27 45 views
5

Những gì tôi cóThay đổi kích thước MKAnnotationView Image Khi bản đồ phóng to và thu nhỏ?

Tôi có khoảng 150 MKAnnotationXem trên bản đồ. Mỗi MKAnnotationView đều có một hình ảnh thay thế mã pin mặc định.

gì đang xảy ra tại

Khi bản đồ phóng to, các MKAnnotationViews đang nhận được nhỏ hơn và ngược lại khi nó phóng ra.

gì tôi muốn xảy ra

Vâng tôi muốn nó là cách khác xung quanh. Vì khi bản đồ nhỏ, tôi muốn rằng các MKAnnotationViews sẽ nhỏ hơn để người dùng có thể nhìn thấy tất cả chúng, và khi anh ấy phóng to tôi ước chúng sẽ lớn hơn.

đang Những gì tôi có cho đến nay

tôi biết làm thế nào để có được sự thay đổi zoom, và tôi biết tôi có thể nhận được "pMapView.region.span.latitudeDelta" như một tài liệu tham khảo cho số tiền zoom. và tôi biết tôi có thể thay đổi 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]; 
    } 
} 

Ai đó có thể giúp tôi với điều đó không? Cảm ơn Shani

Trả lời

22

Trên thực tế trên mặc định MKMapView- chú thích (ví dụ pin hoặc hình ảnh) và callout (ví dụ bong bóng) vẫn là kích thước tương tự như bạn phóng to hoặc thu. Họ không quy mô. Nhưng tôi nhận được point- của bạn liên quan đến bản đồ chúng xuất hiện để được phát triển như bản đồ thu nhỏ và co lại như bản đồ phóng to

Vì vậy, có hai giải pháp cho vấn đề của bạn và họ làm việc hơi khác nhau:.

  1. Triển khai -(void)mapView:(MKMapView *)pMapView regionDidChangeAnimated:(BOOL)animated từ Tham chiếu giao thức MKMapViewDelegate - mà bạn đã thực hiện.
  2. Đính kèm một UIPinchGestureRecognizer vào đối tượng MKMapView và sau đó triển khai tác vụ.

Tùy chọn # 1 - mapView:regionDidChangeAnimated: sẽ được gọi là cuộn hoặc sự kiện thu phóng - về cơ bản bất cứ khi nào khu vực bản đồ thay đổi theo tên ngụ ý. Điều này dẫn đến việc thay đổi kích thước nhỏ hơn một chút các biểu tượng, bởi vì các sự kiện trên bản đồ được kích hoạt ít thường xuyên hơn.

Tùy chọn của tôi là cho Tùy chọn # 2 - Đính kèm một UIPinchGestureRecognizer vào đối tượng MKMapView và sau đó triển khai tác vụ. Các sự kiện cử chỉ chụm được kích hoạt khá nhanh, do đó bạn có thể thay đổi kích thước của biểu tượng. Và họ chỉ bắn cho một sự kiện pinch được công nhận - vì vậy họ sẽ không cháy trong một sự kiện di chuyển.

Các phương pháp hành động gọi phải phù hợp với một trong những dấu hiệu sau đây:

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

Bạn phải cẩn thận để không ghi đè lên các hành vi zoom bản đồ mặc định. Xem bài đăng này: "UIMapView: UIPinchGestureRecognizer không được gọi là" để biết thêm thông tin. Câu trả lời ngắn gọn là bạn phải thực hiện shouldRecognizeSimultaneouslyWithGestureRecognizer: và trả lại CÓ.

Tất cả đã nói đây là một số mẫu mã:

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

Vì vậy, tại này point- bạn lại có nhiều lựa chọn cho làm thế nào để thay đổi kích thước chú thích. Cả hai mẫu mã sau dựa trên Troy Brant's code for getting the zoom level of an MKMapView.

  1. Thay đổi kích thước Cả hình ảnh chú thích và chú dẫn sử dụng biến đổi. Cá nhân tôi nghĩ rằng các kết quả biến đổi trong một thay đổi kích thước tìm kiếm sạch hơn. Nhưng trong hầu hết các trường hợp, thay đổi kích thước chú thích không được gọi.
  2. Thay đổi kích thước hình ảnh chú thích - Tôi sử dụng Trevor Harmon's Resize a UIImage the right way nhưng một lần nữa ý kiến ​​của tôi là nó không phải là sạch sẽ tìm kiếm một thay đổi kích cỡ.

Dưới đây là một số mẫu mã hơn:

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

Nếu công trình này, đừng quên để đánh dấu nó như là câu trả lời.

+0

Hey. Tôi sẽ cố gắng này, cảm ơn cho một câu trả lời tuyệt vời. Và không phải lo lắng về việc chấp thuận :) – shannoga

+1

điều này không hợp lệ trên iOS6 – user501836

+5

Đúng vậy, không còn hoạt động trên iOS6 nữa. Bất cứ ai đã đưa ra một giải pháp cho điều đó? – Bach

1

Xin lỗi về tiếng anh xấu của tôi ... nhưng tôi chỉ muốn giúp đỡ ai đó.

Cảm ơn bạn rất nhiều, Funktional. Câu trả lời của bạn rất tuyệt ... nó hoạt động hoàn hảo trên iOS5! Nhưng điều này không hợp lệ trên iOS6, và có vẻ như không có giải pháp để giải quyết vấn đề này ngay bây giờ.

Nhưng cuối cùng, tôi đã giải quyết nó theo cách ngu ngốc/tĩnh và hoạt động tốt trên cả iOS. Tôi sẽ không giải thích quá nhiều. Đây là những gì tôi đã làm trong dự án của tôi.

  1. Hình ảnh cho mkannotation được đặt tên pin.png (kích thước 20x20)

  2. Tôi tạo ra thêm năm hình ảnh với kích thước khác nhau cho mức độ zoom khác nhau (18x18, 16x16, 14x14, 12x12, 10x10) và chúng được đặt tên là pin-5.png, pin-4.png, pin-3.png, pin-2.png, pin-1.png.

  3. Tôi đã gỡ bỏ tất cả các mã về tính quy mô trong formatAnnotationView và thêm dòng này

    NSString* imageName = 
        [NSString stringWithFormat:@"%@%@.png", 
        [imageName substringToIndex:[imageName length]-4 ], 
        [self getImageLevel]]; 
    
  4. Ngoài ra, thay đổi này từ

    UIImage * pinImage = [UIImage imageNamed: @ "YOUR_IMAGE_NAME_HERE"];

    để

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

  5. add chức năng này

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

xin lỗi về mã hóa xấu và tiếng anh một lần nữa.

1

Một phương pháp thay thế sẽ là kích thước lại thuộc tính hình ảnh chế độ xem chú thích. Ví dụ: shown in this post

1

Trong Swift 3, tính năng này phù hợp với tôi. Hình ảnh của tôi là 100% trên mức 19, vì vậy 1/19 mang lại cho tôi 0,5263158 đó là quy mô tuyến tính của tôi:

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

Chỉ hoạt động với chú thích được tạo mới khi thu nhỏ, chú thích đã tạo có kích thước khác nhau khi thu nhỏ, bạn có giải pháp nào không –

1

@ câu trả lời Funktional trong 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 
    } 
} 
Các vấn đề liên quan