How do you create a wiggle animation similar to ip

2019-07-26 03:08发布

We are currently developing an application that contains a series of icons. We want the icons to wiggle like the app deletion animations when pressed. What would be the best way to code this animation sequence?

8条回答
小情绪 Triste *
2楼-- · 2019-07-26 03:40

SWIFT :-

let transformAnim  = CAKeyframeAnimation(keyPath:"transform")
transformAnim.values  = [NSValue(CATransform3D: CATransform3DMakeRotation(0.04, 0.0, 0.0, 1.0)),NSValue(CATransform3D: CATransform3DMakeRotation(-0.04 , 0, 0, 1))]
transformAnim.autoreverses = true
transformAnim.duration  = (Double(indexPath.row)%2) == 0 ?   0.115 : 0.105
transformAnim.repeatCount = Float.infinity
self.layer.addAnimation(transformAnim, forKey: "transform")

Objective C :-

-(CAKeyframeAnimation *)wiggleView
{
    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];

    CGFloat wobbleAngle = 0.04f;

    NSValue* valLeft = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(wobbleAngle, 0.0f, 0.0f, 1.0f)];
    NSValue* valRight = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-wobbleAngle, 0.0f, 0.0f, 1.0f)];
    animation.values = [NSArray arrayWithObjects:valLeft, valRight, nil];

    animation.autoreverses = YES;
    animation.duration = 0.125;
    animation.repeatCount = HUGE_VALF;

    return animation;
}
查看更多
倾城 Initia
3楼-- · 2019-07-26 03:43

Edited paiego's code to fit my needs: visual error animation feedback upon user's action (tap). It happens once - it's not a constant wiggling like SpringBoard app edit wiggle animation.

- (CAAnimation *)shakeAnimation {
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];

    CGFloat wobbleAngle = 0.06f;

    NSValue *valLeft;
    NSValue *valRight;
    NSMutableArray *values = [NSMutableArray new];

    for (int i = 0; i < 5; i++) {
        valLeft = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(wobbleAngle, 0.0f, 0.0f, 1.0f)];
        valRight = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-wobbleAngle, 0.0f, 0.0f, 1.0f)];
        [values addObjectsFromArray:@[valLeft, valRight]];
        wobbleAngle*=0.66;
    }
    animation.values = [values copy];
    animation.duration = 0.7;
    return animation;
}

Usage:

[your_view.layer addAnimation:[self shakeAnimation] forKey:@""]; //do the shake animation
your_view.transform = CGAffineTransformIdentity; //return the view back to original

Hope this helps someone else.

查看更多
Lonely孤独者°
4楼-- · 2019-07-26 03:45

Rewrote Sebastien's answer in Swift 3.

let wiggleBounceY = 4.0
let wiggleBounceDuration = 0.12
let wiggleBounceDurationVariance = 0.025

let wiggleRotateAngle = 0.06
let wiggleRotateDuration = 0.10
let wiggleRotateDurationVariance = 0.025

func randomize(interval: TimeInterval, withVariance variance: Double) -> Double{
    let random = (Double(arc4random_uniform(1000)) - 500.0) / 500.0
    return interval + variance * random
}

func startWiggle(for view: UIView){

    //Create rotation animation
    let rotationAnim = CAKeyframeAnimation(keyPath: "transform.rotation.z")
    rotationAnim.values = [-wiggleRotateAngle, wiggleRotateAngle]
    rotationAnim.autoreverses = true
    rotationAnim.duration = randomize(interval: wiggleRotateDuration, withVariance: wiggleRotateDurationVariance)
    rotationAnim.repeatCount = HUGE

    //Create bounce animation
    let bounceAnimation = CAKeyframeAnimation(keyPath: "transform.translation.y")
    bounceAnimation.values = [wiggleBounceY, 0]
    bounceAnimation.autoreverses = true
    bounceAnimation.duration = randomize(interval: wiggleBounceDuration, withVariance: wiggleBounceDurationVariance)
    bounceAnimation.repeatCount = HUGE

    //Apply animations to view
    UIView.animate(withDuration: 0) {
        view.layer.add(rotationAnim, forKey: "rotation")
        view.layer.add(bounceAnimation, forKey: "bounce")
        view.transform = .identity
    }
}

func stopWiggle(for view: UIView){
    view.layer.removeAllAnimations()
}
查看更多
做个烂人
5楼-- · 2019-07-26 03:49

The answer by Vinzius is very cool. However the wobble only rotates from 0 Radians to 0.08. Thus the wobble can look a little unbalanced. If you get this same issue then you may want to add both a negative and a positive rotation by using a CAKeyframeAnimation rather than a CABasicRotation:

- (CAAnimation*)getShakeAnimation 
{
    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];

    CGFloat wobbleAngle = 0.06f;

    NSValue* valLeft = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(wobbleAngle, 0.0f, 0.0f, 1.0f)];
    NSValue* valRight = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-wobbleAngle, 0.0f, 0.0f, 1.0f)];
    animation.values = [NSArray arrayWithObjects:valLeft, valRight, nil];

    animation.autoreverses = YES;  
    animation.duration = 0.125;
    animation.repeatCount = HUGE_VALF;  

    return animation;    
}

You can use this animation method for your view or button like this.

[self.yourbutton.layer addAnimation:[self getShakeAnimation] forKey:@""];
查看更多
Evening l夕情丶
6楼-- · 2019-07-26 03:49

Answered in another thread a Swift 4 version of what is apparently Apple's own algorithm reverse engineered: https://stackoverflow.com/a/47730519/5018607

查看更多
倾城 Initia
7楼-- · 2019-07-26 03:50

I tried to do something like that for an iPad app.

I tried to do some rotations (with CAAnimation) to the view. Here is a sample code I wrote :

- (CAAnimation*)getShakeAnimation {

    CABasicAnimation *animation;
    CATransform3D transform;

    // Create the rotation matrix
    transform = CATransform3DMakeRotation(0.08, 0, 0, 1.0);

    // Create a basic animation to animate the layer's transform
    animation = [CABasicAnimation animationWithKeyPath:@"transform"];

    // Assign the transform as the animation's value
    animation.toValue = [NSValue valueWithCATransform3D:transform];

    animation.autoreverses = YES;  
    animation.duration = 0.1;  
    animation.repeatCount = HUGE_VALF;  

    return animation;

}

And you should try to apply this one to your layer (with function : addAnimation). Here, autoreverses property is to alternate left and right orientation. Try setting others values to the angle and duration.

But in my case I had to add others angles to the CATransform3DMakeRotation method, depending on the initial layer orientation ^^

Good Luck ! Vincent

查看更多
登录 后发表回答