53 Stimmen

Wie erzeugt man den wackelnden Icon-Effekt für das iPhone?

Ich möchte ein Bild in meiner Anwendung hin und her wackeln lassen, ähnlich wie die iPhone-Symbole wackeln, wenn man sie nach unten drückt. Wie kann ich das am besten machen?

Dies ist mein erster Ausflug in die Welt der Animationen, bei dem ich keine animierten GIFs verwende. Ich glaube, die Idee ist, das Bild leicht hin und her zu drehen, um den Wackeleffekt zu erzeugen. Ich habe die Verwendung von CABasicAnimation und CAKeyframeAnimation in Betracht gezogen. CABasicAnimation erzeugt bei jeder Wiederholung einen Jitter, weil es zur Ausgangsposition springt und nicht zurück interpoliert. CAKeyframeAnimation scheint wie die Lösung, außer dass ich es nicht zum Laufen bringen kann. Ich muss etwas übersehen. Hier ist mein Code mit der CAKeyframeAnimation (die nicht funktioniert):

    NSString *keypath = @"wobbleImage";
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:keypath];
animation.duration = 1.0f;
animation.delegate = self;
animation.repeatCount = 5;

CGFloat wobbleAngle = 0.0872664626f;
NSValue *initial = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(0.0f, 0.0f, 0.0f, 1.0f)];
NSValue *middle = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(wobbleAngle, 0.0f, 0.0f, 1.0f)];
NSValue *final = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-wobbleAngle, 0.0f, 0.0f, 1.0f)];
animation.values = [NSArray arrayWithObjects:initial, middle, final, nil];

[imageView.layer addAnimation:animation forKey:keypath];

Vielleicht gibt es aber auch eine ganz einfache Lösung, die ich gerade übersehe. Ich bin für jeden Hinweis dankbar. Danke!

93voto

Ramin Punkte 13326

Das geht ganz einfach:

#define RADIANS(degrees) (((degrees) * M_PI) / 180.0)

CGAffineTransform leftWobble = CGAffineTransformRotate(CGAffineTransformIdentity, RADIANS(-5.0));
CGAffineTransform rightWobble = CGAffineTransformRotate(CGAffineTransformIdentity, RADIANS(5.0));

itemView.transform = leftWobble;  // starting point

[UIView beginAnimations:@"wobble" context:itemView];
[UIView setAnimationRepeatAutoreverses:YES]; // important
[UIView setAnimationRepeatCount:10];
[UIView setAnimationDuration:0.25];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(wobbleEnded:finished:context:)];

itemView.transform = rightWobble; // end here & auto-reverse

[UIView commitAnimations];

...

- (void) wobbleEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context 
{
     if ([finished boolValue]) {
        UIView* item = (UIView *)context;
        item.transform = CGAffineTransformIdentity;
     }
}

Wahrscheinlich müssen Sie mit dem Timing und den Winkeln spielen, aber das sollte Ihnen den Einstieg erleichtern.

EDIT: Ich habe die Antwort bearbeitet, um einen Code hinzuzufügen, der den Gegenstand wieder in seinen ursprünglichen Zustand versetzt, wenn er fertig ist. Beachten Sie auch, dass Sie die beginAnimations Kontextwert, um etwas an die Start-/Stop-Methoden weiterzugeben. In diesem Fall handelt es sich um das Wobbling-Objekt selbst, so dass Sie nicht auf spezifische Iwars angewiesen sind und die Methode für jedes generische UIView-basierte Objekt (z. B. Textlabels, Bilder usw.) verwendet werden kann.

92voto

Pieter Punkte 16973

Ramin's Antwort war sehr gut, aber seit OS4 kann der gleiche Effekt auch mit animateWithDuration in einer einfachen Funktion erreicht werden.

(angepasst an sein Beispiel für zukünftige Googler)

#define RADIANS(degrees) (((degrees) * M_PI) / 180.0)

- (void)startWobble {
 itemView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, RADIANS(-5));

 [UIView animateWithDuration:0.25 
      delay:0.0 
      options:(UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse)
      animations:^ {
       itemView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, RADIANS(5));
      }
      completion:NULL
 ];
}

- (void)stopWobble {
 [UIView animateWithDuration:0.25
      delay:0.0 
      options:(UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveLinear)
      animations:^ {
       itemView.transform = CGAffineTransformIdentity;
      }
      completion:NULL
  ];
}

14voto

docchang Punkte 1095

Sie sollten Folgendes verwenden CAKeyframeAnimation um eine flüssigere Animation zu erstellen.

+ (void) animationKeyFramed: (CALayer *) layer 
                   delegate: (id) object
              forKey: (NSString *) key {

    CAKeyframeAnimation *animation;
    animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
    animation.duration = 0.4;
    animation.cumulative = YES;
    animation.repeatCount = 2;
    animation.values = [NSArray arrayWithObjects:
            [NSNumber numberWithFloat: 0.0], 
            [NSNumber numberWithFloat: RADIANS(-9.0)], 
            [NSNumber numberWithFloat: 0.0],
            [NSNumber numberWithFloat: RADIANS(9.0)],
            [NSNumber numberWithFloat: 0.0], nil];
    animation.fillMode = kCAFillModeForwards;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animation.removedOnCompletion = NO;
    animation.delegate = object;

    [layer addAnimation:animation forKey:key];
}

9voto

Kristopher Johnson Punkte 78933

Ich habe eine Beispielanwendung geschrieben, die versucht, das Wackeln des Startbildschirms und die Bewegung der Symbole zu replizieren: iPhone-Beispielcode: Kacheln

4voto

Allen Conquest Punkte 116

Für alle, die in jüngerer Zeit auf diesen Beitrag gestoßen sind und dasselbe in Swift tun möchten, hier meine Übersetzung:

func smoothJiggle() {

    let degrees: CGFloat = 5.0
    let animation = CAKeyframeAnimation(keyPath: "transform.rotation.z")
    animation.duration = 0.6
    animation.cumulative = true
    animation.repeatCount = Float.infinity
    animation.values = [0.0,
        degreesToRadians(-degrees) * 0.25,
        0.0,
        degreesToRadians(degrees) * 0.5,
        0.0,
        degreesToRadians(-degrees),
        0.0,
        degreesToRadians(degrees),
        0.0,
        degreesToRadians(-degrees) * 0.5,
        0.0,
        degreesToRadians(degrees) * 0.25,
        0.0]
    animation.fillMode = kCAFillModeForwards;
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    animation.removedOnCompletion = true

    layer.addAnimation(animation, forKey: "wobble")
}

func stopJiggling() {
    jiggling = false
    self.layer.removeAllAnimations()
    self.transform = CGAffineTransformIdentity
    self.layer.anchorPoint = CGPointMake(0.5, 0.5)
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X