Как я могу создать пользовательское использование анимации “отбрасывания контакта” MKAnnotationView?

У меня есть экземпляр MKMapView и хотел бы использовать пользовательские значки аннотации вместо стандартных значков контакта, предоставленных MKPinAnnotationView. Так, я имею, устанавливают подкласс MKAnnotationView по имени CustomMapAnnotation, и является переопределяющим -(void)drawRect: потянуть CGImage. Это работает.

Проблема прибывает, когда я пытаюсь копировать .animatesDrop функциональность предоставляется MKPinAnnotationView; я хотел бы в свои значки казаться постепенно, отброшенным сверху и в слева направо порядке, когда аннотации добавляются к MKMapView экземпляр.

Вот - (пустой) drawRect: для CustomMapAnnotation, который работает, когда Вы просто тянете UIImage (который является тем, что 2-я строка делает):

- (void)drawRect:(CGRect)rect {
 [super drawRect:rect];
 [((Incident *)self.annotation).smallIcon drawInRect:rect];
 if (newAnnotation) {
  [self animateDrop];
  newAnnotation = NO;
 }
} 

Проблема прибывает, когда Вы добавляете animateDrop метод:

-(void)animateDrop {
 CGContextRef myContext = UIGraphicsGetCurrentContext();

 CGPoint finalPos = self.center;
 CGPoint startPos = CGPointMake(self.center.x, self.center.y-480.0);
 self.layer.position = startPos;

 CABasicAnimation *theAnimation;
 theAnimation=[CABasicAnimation animationWithKeyPath:@"position"];
 theAnimation.fromValue=[NSValue valueWithCGPoint:startPos];
 theAnimation.toValue=[NSValue valueWithCGPoint:finalPos];
 theAnimation.removedOnCompletion = NO;
 theAnimation.fillMode = kCAFillModeForwards;
 theAnimation.delegate = self;
 theAnimation.beginTime = 5.0 * (self.center.x/320.0);
 theAnimation.duration = 1.0;
 [self.layer addAnimation:theAnimation forKey:@""];
}

Это просто не работает, и могло быть много причин почему. Я не войду во всех них теперь. Главное, которое я желаю знать, состоит в том, если подход является звуковым вообще, или если я должен попробовать что-то совершенно различное.

Я попробовал также к пакету все это в транзакцию анимации так, чтобы beginTime параметр мог бы на самом деле работать; это, казалось, не сделало что-либо вообще. Я не знаю, является ли это вызвано тем, что я упускаю некоторую ключевую суть или является ли это, потому что MapKit повреждает мои анимации так или иначе.

  // Does nothing
  [CATransaction begin];
  [map addAnnotations:list];
  [CATransaction commit];

Если у кого-либо есть опыт с анимированным MKMapAnnotations как это, я любил бы некоторые подсказки, иначе если бы можно дать совет CAAnimation относительно подхода, это было бы большим также.

24
задан Matthias Bauch 9 March 2015 в 22:03
поделиться

2 ответа

Сначала необходимо заставить контроллер просмотра реализовать MKMapViewDelegate, если он еще этого не сделал.

Затем, реализуйте этот метод:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views { 
   MKAnnotationView *aV; 
   for (aV in views) {
     CGRect endFrame = aV.frame;

     aV.frame = CGRectMake(aV.frame.origin.x, aV.frame.origin.y - 230.0, aV.frame.size.width, aV.frame.size.height);

     [UIView beginAnimations:nil context:NULL];
     [UIView setAnimationDuration:0.45];
     [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
         [aV setFrame:endFrame];
     [UIView commitAnimations];

   }
}

Добавьте свои аннотации в MapView, и когда они будут добавлены, этот метод делегирования будет вызываться и будет анимировать контакты сверху вниз по мере их добавления.

Значения для синхронизации и позиционирования могут быть немного изменены, но я настроил его так, чтобы он выглядел лучше/ближе к традиционному падению (насколько я тестировал). Надеюсь, это поможет!

52
ответ дан 28 November 2019 в 22:07
поделиться

В качестве альтернативы, если вы создаете подкласс MKAnnotationView, вы можете использовать didMoveToSuperview для запуска анимации. Ниже приведено падение, которое заканчивается легким эффектом «сплющивания»

  #define kDropCompressAmount 0.1

  @implementation MyAnnotationViewSubclass

  ...

  - (void)didMoveToSuperview {
      CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
      animation.duration = 0.4;
      animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
      animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, -400, 0)];
      animation.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];

      CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"transform"];
      animation2.duration = 0.10;
      animation2.beginTime = animation.duration;
      animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
      animation2.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DMakeTranslation(0, self.layer.frame.size.height*kDropCompressAmount, 0), 1.0, 1.0-kDropCompressAmount, 1.0)];
      animation2.fillMode = kCAFillModeForwards;

      CABasicAnimation *animation3 = [CABasicAnimation animationWithKeyPath:@"transform"];
      animation3.duration = 0.15;
      animation3.beginTime = animation.duration+animation2.duration;
      animation3.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
      animation3.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
      animation3.fillMode = kCAFillModeForwards;

      CAAnimationGroup *group = [CAAnimationGroup animation];
      group.animations = [NSArray arrayWithObjects:animation, animation2, animation3, nil];
      group.duration = animation.duration+animation2.duration+animation3.duration;
      group.fillMode = kCAFillModeForwards;

      [self.layer addAnimation:group forKey:nil];
  }
12
ответ дан 28 November 2019 в 22:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: