如何制作类似于 iphone 删除动画的摆动动画

Posted

技术标签:

【中文标题】如何制作类似于 iphone 删除动画的摆动动画【英文标题】:How do you create a wiggle animation similar to iphone deletion animation 【发布时间】:2010-09-13 19:59:08 【问题描述】:

我们目前正在开发一个包含一系列图标的应用程序。我们希望图标在按下时像应用删除动画一样摆动。编写此动画序列的最佳方法是什么?

【问题讨论】:

how to create iphone's wobbling icon effect?的可能重复 看看这个:Wobble Effect 【参考方案1】:

Vinzius 的回答非常酷。然而,摆动仅从 0 弧度旋转到 0.08。因此,摆动看起来有点不平衡。如果您遇到同样的问题,那么您可能希望通过使用 CAKeyframeAnimation 而不是 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;    

您可以像这样将这种动画方法用于您的视图或按钮。

[self.yourbutton.layer addAnimation:[self getShakeAnimation] forKey:@""];

【讨论】:

很棒的动画,谢谢。尝试两个答案,两者都很好,这对我来说更好。 如何将它添加到我的视图或按钮..?【参考方案2】:

斯威夫特:-

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")

目标 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;

【讨论】:

【参考方案3】:

仔细观察 ios 的实现,有两点让他们的实现比这里提到的代码更真实一些:

图标似乎有反弹和旋转 每个图标都有自己的时间 - 它们并非全部同步

我根据此处的答案(并在此 answer 的帮助下)为每个动画的持续时间添加旋转、反弹和一点随机性。

#define kWiggleBounceY 4.0f
#define kWiggleBounceDuration 0.12
#define kWiggleBounceDurationVariance 0.025

#define kWiggleRotateAngle 0.06f
#define kWiggleRotateDuration 0.1
#define kWiggleRotateDurationVariance 0.025

-(void)startWiggling 
    [UIView animateWithDuration:0
                     animations:^
                         [self.layer addAnimation:[self rotationAnimation] forKey:@"rotation"];
                         [self.layer addAnimation:[self bounceAnimation] forKey:@"bounce"];
                         self.transform = CGAffineTransformIdentity;
                     ];


-(CAAnimation*)rotationAnimation 
    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
    animation.values = @[@(-kWiggleRotateAngle), @(kWiggleRotateAngle)];

    animation.autoreverses = YES;
    animation.duration = [self randomizeInterval:kWiggleRotateDuration
                                    withVariance:kWiggleRotateDurationVariance];
    animation.repeatCount = HUGE_VALF;

    return animation;


-(CAAnimation*)bounceAnimation 
    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.y"];
    animation.values = @[@(kWiggleBounceY), @(0.0)];

    animation.autoreverses = YES;
    animation.duration = [self randomizeInterval:kWiggleBounceDuration
                                    withVariance:kWiggleBounceDurationVariance];
    animation.repeatCount = HUGE_VALF;

    return animation;


-(NSTimeInterval)randomizeInterval:(NSTimeInterval)interval withVariance:(double)variance 
    double random = (arc4random_uniform(1000) - 500.0) / 500.0;
    return interval + variance * random;

我在 UICollectionView 上实现了这段代码,它有 30 个项目弹跳,并且在 iPad 2 上表现完美。

【讨论】:

这非常接近 Apple Wobble。我只是将常量调整到这些,它似乎更接近:#define kWiggleBounceY 3.0f #define kWiggleBounceDuration 0.14 #define kWiggleBounceDurationVariance 0.025 #define kWiggleRotateAngle 0.03f #define kWiggleRotateDuration 0.12 #define kWiggleRotateDurationVariance 0.025【参考方案4】:

我尝试为 iPad 应用程序做类似的事情。

我尝试对视图进行一些旋转(使用 CAAnimation)。这是我编写的示例代码:

- (CAAnimation*)getShakeAnimation 

    CABasicAnimation *动画;
    CATransform3D变换;

    // 创建旋转矩阵
    变换 = CATransform3DMakeRotation(0.08, 0, 0, 1.0);

    // 创建一个基本动画来动画层的变换
    动画 = [CABasicAnimation animationWithKeyPath:@"transform"];

    // 将变换指定为动画的值
    animation.toValue = [NSValue valueWithCATransform3D:transform];

    动画.autoreverses = YES;
    动画.持续时间 = 0.1;
    动画.repeatCount = HUGE_VALF;

    返回动画;

您应该尝试将这个应用到您的图层(使用函数:addAnimation)。 在这里, autoreverses 属性是交替左右方向。 尝试将其他值设置为角度和持续时间。

但在我的情况下,我必须向 CATransform3DMakeRotation 方法添加其他角度,具体取决于初始层方向^^

祝你好运! 文森特

【讨论】:

【参考方案5】:

在 Swift 3 中重写了 Sebastien 的答案。

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()

【讨论】:

【参考方案6】:
    func startWiggling() 
        deleteButton.isHidden = false
        guard contentView.layer.animation(forKey: "wiggle") == nil else  return 
        guard contentView.layer.animation(forKey: "bounce") == nil else  return 

        let angle = 0.04

        let wiggle = CAKeyframeAnimation(keyPath: "transform.rotation.z")
        wiggle.values = [-angle, angle]
        wiggle.autoreverses = true
        wiggle.duration = randomInterval(0.1, variance: 0.025)
        wiggle.repeatCount = Float.infinity
        contentView.layer.add(wiggle, forKey: "wiggle")

        let bounce = CAKeyframeAnimation(keyPath: "transform.translation.y")
        bounce.values = [4.0, 0.0]
        bounce.autoreverses = true
        bounce.duration = randomInterval(0.12, variance: 0.025)
        bounce.repeatCount = Float.infinity
        contentView.layer.add(bounce, forKey: "bounce")
    

    func stopWiggling() 
        deleteButton.isHidden = true
        contentView.layer.removeAllAnimations()
        

    func randomInterval(_ interval: TimeInterval, variance: Double) -> TimeInterval 
        return interval + variance * Double((Double(arc4random_uniform(1000)) - 500.0) / 500.0)
    

看看这个 iOS SpingBoard example

【讨论】:

【参考方案7】:

在另一个线程中回答了一个显然是苹果自己的算法逆向工程的 Swift 4 版本: https://***.com/a/47730519/5018607

【讨论】:

【参考方案8】:

编辑了 paiego 的代码以满足我的需求:用户操作(点击)时的视觉错误动画反馈。它发生一次 - 它不像 SpringBoard 应用程序编辑摆动动画那样持续摆动。

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

用法:

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

希望这对其他人有所帮助。

【讨论】:

以上是关于如何制作类似于 iphone 删除动画的摆动动画的主要内容,如果未能解决你的问题,请参考以下文章

scss 简单的摆动动画错误或类似的东西。

iphone - 创建像用户位置蓝色大理石水滴这样的动画

如何在 UIView Like Swipeable TableView Cell 中制作类似于“滑动解锁”的动画

Safari CSS Bug:动画旋转方向不正确?

渐变动画 - 减速和加速

Jquery:如何同时制作连续和同时的动画