Hoe kan ik een aangepaste "pin-drop" animatie met behulp van MKAnnotationView?

stemmen
23

Ik heb een exemplaar van MKMapViewen wilt gepersonaliseerde annotatie iconen in plaats van de standaard pin pictogrammen door MKPinAnnotationView geleverd te gebruiken. Dus, ik heb opstelling een subklasse van MKAnnotationView genaamd CustomMapAnnotation en ben dwingende -(void)drawRect:een CGImage trekken. Dit werkt.

Het probleem komt wanneer ik probeer om het repliceren .animatesDropvan MKPinAnnotationView geleverde functionaliteit; Ik zou graag voor mijn pictogrammen om geleidelijk verschijnen, daalde van boven en van links naar rechts orde, wanneer de annotaties worden toegevoegd aan de MKMapViewinstantie.

Hier is - (void) drawRect: voor CustomMapAnnotation, die werkt als je de UIImage (dat is wat de 2e lijn doet) gewoon te trekken:

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

Het probleem komt wanneer u de toe te voegen animateDropmethode:

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

Het werkt gewoon niet werken, en er zou een heleboel redenen waarom zijn. Ik zal nu niet te krijgen in elk van hen. Het belangrijkste wat ik wil weten is of de aanpak is het geluid helemaal niet, of als ik iets heel anders moeten proberen.

Ik heb ook geprobeerd te verpakken van de hele zaak in een animatie transactie, zodat de parameter beginTime eigenlijk zou kunnen werken; dit leek helemaal niets dat niet doen. Ik weet niet of dit is omdat ik mis een aantal belangrijke punt, of dat het is omdat MapKit een of andere manier vernielen mijn animaties.

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

Als iemand ervaring met het geanimeerde MKMapAnnotations als dit, zou ik graag enkele tips, anders als je CAAnimation advies over de aanpak kan bieden, dat zou te groot zijn.

De vraag is gesteld op 07/12/2009 om 01:38
bron van user
In andere talen...                            


5 antwoorden

stemmen
58

Een probleem met de code van Paul Shapiro is dat het niet te gaan met wanneer je annotaties toe te voegen onder de plaats waar de gebruiker op zoek is op dit moment. Die aantekeningen zal drijven in de lucht voordat laten vallen, omdat ze worden verplaatst naar de gebruiker zichtbaar kaart rect.

Een andere reden is dat valt ook de locatie van de gebruiker blauwe stip. Met deze onderstaande code, je om met zowel de locatie van de gebruiker en grote hoeveelheden kaartnotities off-screen. Ik heb ook nog een mooie bounce;)

- (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;
                    }];
                }];
            }
        }];
    }
}
antwoordde op 12/08/2011 om 21:24
bron van user

stemmen
52

Eerst moet je om uw view controller te implementeren MKMapViewDelegate als het niet al.

Vervolgens uitvoering van deze methode:

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

   }
}

Voeg uw annotaties bij de MapView en wanneer ze worden toegevoegd, zal deze afgevaardigde methode genoemd worden en zullen de pennen van boven animeren naar beneden als ze worden toegevoegd.

De waarden voor timing en positionering kan worden veranderd een beetje, maar ik heb het getweaked zodat het lijkt best / het dichtst bij de traditionele druppel (voor zover ik heb getest). Ik hoop dat dit helpt!

antwoordde op 18/01/2010 om 16:52
bron van user

stemmen
12

Als alternatief, als je het maken van een MKAnnotationView subklasse, kunt u gebruik maken didMoveToSuperviewom de animatie te activeren. Het volgende doet een druppel die eindigt in een lichte 'squish' effect

  #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];
  }
antwoordde op 26/06/2010 om 19:56
bron van user

stemmen
5

Voor reactie Michael Tyson's (ik kan niet overal nog commentaar), stel ik voor een insertie van de volgende code in didMoveToSuperview voor een goede hergebruik van MKAnnotationView zodat de animatie opnieuw doet en vervolgens imiteren de sequencial toevoeging van annotaties

Speel met de verdelers en multipliers voor verschillende visuele resultaten ...

- (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...
}
antwoordde op 02/11/2010 om 11:08
bron van user

stemmen
0

Ik denk dat de betere optie is om 'animatesDrop' ingesteld op YES. Het is een eigenschap van MKPinAnnotationView.

antwoordde op 10/11/2014 om 00:09
bron van user

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