调整MKAnnotationView图像大小当地图放大和缩小?
我拥有的
我在地图上有大约150个MKAnnotationView。 每个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
实际上,在默认的MKMapView中,注释(例如pin或图像)和标注(例如气泡)保持与放大或缩小相同的大小。 他们不规模。 但是,我相信你的观点 – 与地图相关,随着地图的放大,地图缩小,缩小。
所以你的问题有两个解决scheme,它们的工作方式稍有不同:
- 实现
-(void)mapView:(MKMapView *)pMapView regionDidChangeAnimated:(BOOL)animated
从MKMapViewDelegate协议参考-(void)mapView:(MKMapView *)pMapView regionDidChangeAnimated:(BOOL)animated
– 你已经做了。 - 将一个
UIPinchGestureRecognizer
附加到MKMapView对象,然后执行该操作。
选项#1 – mapView:regionDidChangeAnimated:
将被调用的滚动或缩放事件 – 基本上任何时候地图区域更改顾名思义。 这会导致图标的平滑调整稍微不平滑,因为地图事件的触发频率较低。
我的首选项是选项#2 – 将一个UIPinchGestureRecognizer
附加到MKMapView对象,然后执行操作。 捏手势事件被激发相当快,所以你得到一个平滑的图标大小。 而且他们只会触发一个公认的捏事件,所以他们不会在滚动事件中触发。
所调用的操作方法必须符合以下签名之一:
- (void)handleGesture;
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer;
您必须小心不要覆盖地图的默认缩放行为。 看到这个post:“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; }
所以在这一点上,你再次有几个select如何调整注释的大小。 下面的两个代码示例都依赖于Troy Brant的代码来获取MKMapView的缩放级别 。
- 使用变换调整注释图像和标注的大小。 就我个人而言,我认为这个转换导致了一个更清晰的外观调整。 但是在大多数情况下,不需要调整标注的大小。
- 调整注释图像的大小 – 我使用Trevor Harmon的Resize UIImage正确的方式,但我的意见是,它不是一样干净的resize。
这里是一些更多的示例代码:
- (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]; } }
如果这样做,不要忘记标记为答案。
对不起,我的英语不好,但我只是想帮助别人。
非常感谢你,Funktional。 你的答案很好,它完美的工作在iOS5上! 但是这在iOS6上是失效的,现在看来目前还没有解决这个问题的办法。
但最后,我用一种愚蠢/静态的方式解决了这个问题,它在iOS上都能正常工作。 我不会解释太多。 这是我在我的项目中所做的。
-
mkannotation的图像名为pin.png(大小为20×20)
-
我为不同的缩放级别(18×18,16×16,14×14,12×12,10×10)创build了五个不同大小的图像,它们被命名为pin-5.png,pin-4.png,pin-3.png,pin-2.png ,pin-1.png。
-
我删除了formatAnnotationView中有关计算比例的所有代码,并添加了这一行
NSString* imageName = [NSString stringWithFormat:@"%@%@.png", [imageName substringToIndex:[imageName length]-4 ], [self getImageLevel]];
-
另外,从这个改变
UIImage * pinImage = [UIImage imageNamed:@“YOUR_IMAGE_NAME_HERE”];
至
UIImage * pinImage = [[UIImage alloc] initWithContentsOfFile:imageName];
-
添加这个function
-(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;}
对不起的代码和英语再次抱歉。
另一种方法是重新调整注解视图图像属性的大小。 在这篇文章中显示了一个例子
在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)) }
@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 } }