Jak mohu vytvořit vlastní „pin-drop“ animaci pomocí MKAnnotationView?

hlasů
23

Mám instance MKMapViewa chtěli pomocí ikon na zakázku anotace namísto standardních čepů ikony dodávané MKPinAnnotationView. Takže jsem nastavení podtřídy MKAnnotationView volal CustomMapAnnotation a jsem přepsání -(void)drawRect:k tomu CGImage. To funguje.

Problém nastává, když se snažím napodobit .animatesDropfunkčnost dodávaného MKPinAnnotationView; Byl bych rád za mé ikony objevují postupně klesl shora a zleva doprava pořadí, jsou-li anotace přidány k MKMapViewinstanci.

Zde je - (void) drawRect: pro CustomMapAnnotation, která funguje, když stačí nakreslit UIImage (což je to, co dělá druhá linie):

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

Problém nastává, když přidáte animateDropmetodu:

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

Je to prostě nefunguje, a tam by mohlo být mnoho důvodů, proč. Nebudu se dostat do všech z nich teď. Hlavní věc, kterou jsem chtěl vědět, je-li tento přístup je zvuk vůbec, nebo jestli bych měl zkusit něco úplně jiného.

Zkoušel jsem i balíček se celou věc do animačního transakce tak, že parametr beginTime by ve skutečnosti mohly fungovat; to vypadalo, že nebude dělat vůbec nic. Já nevím, jestli je to proto, že jsem chybí nějaký klíčový bod, nebo zda je to proto, MapKit je trashing mé animace nějak.

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

Pokud má někdo nějaké zkušenosti s animovanými MKMapAnnotations jako je tento, rád bych nějaké rady, jinak, pokud můžete nabídnout CAAnimation rady ohledně přístupu, který by bylo příliš velké.

Položena 07/12/2009 v 01:38
zdroj uživatelem
V jiných jazycích...                            


5 odpovědí

hlasů
58

Jeden problém s kódem Paul Shapiro je to, že se nezabývá při přidání poznámky pod místem, kde se uživatel dívá na chvíli. Tyto poznámky se vznášet ve vzduchu před svržením, neboť jsou přesunuty do satelitní viditelného obdélníku uživatele.

Dalším důvodem je, že také poklesne o umístění uživatelské modrou tečku. S tímto kódem níže můžete zvládnout i uživatelské polohu a velké množství mapových anotací off-screen. Také jsem přidal pěkný odraz)

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
    MKAnnotationView *aV; 

    for (aV in views) {

        // Don't pin drop if annotation is user location
        if ([aV.annotation isKindOfClass:[MKUserLocation class]]) {
            continue;
        }

        // Check if current annotation is inside visible map rect, else go to next one
        MKMapPoint point =  MKMapPointForCoordinate(aV.annotation.coordinate);
        if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) {
            continue;
        }

        CGRect endFrame = aV.frame;

        // Move annotation out of view
        aV.frame = CGRectMake(aV.frame.origin.x, aV.frame.origin.y - self.view.frame.size.height, aV.frame.size.width, aV.frame.size.height);

        // Animate drop
        [UIView animateWithDuration:0.5 delay:0.04*[views indexOfObject:aV] options:UIViewAnimationCurveLinear animations:^{

            aV.frame = endFrame;

        // Animate squash
        }completion:^(BOOL finished){
            if (finished) {
                [UIView animateWithDuration:0.05 animations:^{
                    aV.transform = CGAffineTransformMakeScale(1.0, 0.8);

                }completion:^(BOOL finished){
                    [UIView animateWithDuration:0.1 animations:^{
                        aV.transform = CGAffineTransformIdentity;
                    }];
                }];
            }
        }];
    }
}
Odpovězeno 12/08/2011 v 21:24
zdroj uživatelem

hlasů
52

Za prvé, je třeba, aby váš názor řadič realizovat MKMapViewDelegate pokud tomu tak již není.

Potom implementovat tuto metodu:

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

   }
}

Přidat poznámky k MapView a když jsou přidány, bude nazývat tuto metodu delegáta a oživí kolíky od shora dolů tak, jak jsou přidány.

Hodnoty pro načasování a umístění lze změnit trochu, ale jsem vylepšil ho tak, aby vypadal co nejlépe / nejblíže k tradičním poklesem (pokud jsem testováno). Snad to pomůže!

Odpovězeno 18/01/2010 v 16:52
zdroj uživatelem

hlasů
12

Případně, pokud děláte MKAnnotationView podtřídy, můžete použít didMoveToSuperviewke spuštění animace. Doplňuje se dělá kapku, která končí v mírném ‚stlačitelný‘ efektu

  #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];
  }
Odpovězeno 26/06/2010 v 19:56
zdroj uživatelem

hlasů
5

Pro Michael Tyson je odpověď (nemohu komentovat všude zatím), navrhuji vložení následujícího kódu v didMoveToSuperview pro řádné opětovné využití MKAnnotationView tak to dělá animaci znovu a pak napodobit sequencial přidávání poznámek

Hrát s přepážkami a veřejného mínění pro různé vizuální výsledky ...

- (void)didMoveToSuperview {
    //necessary so it doesn't add another animation when moved to superview = nil
    //and to remove the previous animations if they were not finished!
    if (!self.superview) {
        [self.layer removeAllAnimations];
        return;
    }


    float xOriginDivider = 20.;
    float pos = 0;

    UIView *mySuperview = self.superview;
    while (mySuperview && ![mySuperview isKindOfClass:[MKMapView class]])
        mySuperview = mySuperview.superview;
    if ([mySuperview isKindOfClass:[MKMapView class]]) 
        //given the position in the array
        // pos = [((MKMapView *) mySuperview).annotations indexOfObject:self.annotation];   
        // left to right sequence;
        pos = [((MKMapView *) mySuperview) convertCoordinate:self.annotation.coordinate toPointToView:mySuperview].x / xOriginDivider;

    float yOffsetMultiplier = 20.;
    float timeOffsetMultiplier = 0.05;


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

    // rest of animation group...
}
Odpovězeno 02/11/2010 v 11:08
zdroj uživatelem

hlasů
0

Myslím, že lepší volbou je nastavení ‚animatesDrop‘ Ano. Je to vlastnost MKPinAnnotationView.

Odpovězeno 10/11/2014 v 00:09
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more