Размер MKAnnotationView изображения, когда карта приближается и выходит?
что у меня есть
У меня около 150 MKAnnotationViews на карте. Каждый MKAnnotationView имеет изображение, которое заменяет pin-код по умолчанию.
что происходит
когда карта приближается, MKAnnotationViews становятся меньше и наоборот, когда она приближается.
что я хочу, чтобы произошло
Ну, я хочу, чтобы все было наоборот. С тех пор, как карта маленькая, я хочу, чтобы MKAnnotationViews будет меньше, чтобы пользователь мог видеть их все, и когда он увеличит масштаб, я хочу, чтобы они были больше.
какой код у меня до сих пор
Я знаю, как получить изменение масштаба, и я знаю, что могу получить "pMapView.регион.промежуток.latitudeDelta"в качестве ссылки на величину масштабирования. и я знаю, что могу изменить annotationView.рамка.
-(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];
}
}
может кто-нибудь помочь мне с этим пожалуйста? спасибо Шани!--3-->
5 ответов
фактически на MKMapView по умолчанию-аннотация (например, pin или изображение) и выноска (например, пузырь) остаются того же размера, что и при увеличении или уменьшении масштаба. Они не масштабируются. Но я понимаю вашу точку зрения - по отношению к карте они, кажется, растут по мере увеличения карты и уменьшаются по мере увеличения карты.
Итак, есть два решения вашей проблемы и они работают немного по-другому:
- реализовать
-(void)mapView:(MKMapView *)pMapView regionDidChangeAnimated:(BOOL)animated
из ссылки на протокол MKMapViewDelegate-который ты уже сделал это. - вложение
UIPinchGestureRecognizer
к объекту MKMapView, а затем реализовать действие.
Вариант #1 -mapView:regionDidChangeAnimated:
будет вызываться для прокрутки или события масштабирования-в основном в любое время, когда область карты изменилась, как следует из названия. Это приводит к несколько менее плавному изменению размера значков, поскольку события карты запускаются реже.
мои предпочтения для опции #2-прикрепить UIPinchGestureRecognizer
к объекту MKMapView, а затем реализовать действие. События Pinch gesture запускаются довольно быстро, поэтому вы получаете плавное изменение размера значка. И они срабатывают только для распознанного события щепотки-поэтому они не будут срабатывать во время события прокрутки.
вызываемые методы действия должны соответствовать одной из следующих сигнатур:
- (void)handleGesture;
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer;
вы должны быть осторожны, чтобы не переопределить карты по умолчанию зум. См. это сообщение: "UIMapView: UIPinchGestureRecognizer не называется" для получения дополнительной информации. Короткий ответ заключается в том, что вы должны реализовать shouldRecognizeSimultaneouslyWithGestureRecognizer:
и вернуться да.
все сказанное ниже приведен пример кода:
// 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;
}
на данный момент - у вас снова есть несколько вариантов как изменить размер аннотации. Оба следующих примера кода полагаются на код Троя Бранта для получения уровня масштабирования MKMapView.
- измените размер изображения аннотации и выноски с помощью преобразования. Лично я думаю, что преобразование приводит к более чистому изменению размера. Но в большинстве случаев-изменение размера выноски не требуется.
- изменить размер только изображения аннотации-я использую Тревор Хармон изменить размер UIImage правильный путь но, опять же, мое мнение, что это не так чисто, глядя на размер.
вот еще пример кода:
- (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 (размер 20x20)
Я создал еще пять изображений с разным размером для разных уровней масштабирования (18x18, 16x16, 14x14, 12x12, 10x10), и они называются pin-5.ПНГ, пин-код-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"];
to
UIImage * pinImage = [[UIImage alloc] initWithContentsOfFile:imageName];
-
добавить эту функцию
-(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 это сработало для меня. Мое изображение было 100% на уровне 19, поэтому 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
}
}