web-dev-qa-db-ja.com

iPhoneの削除アニメーションに似た小刻みに動くアニメーションをどのように作成しますか

現在、一連のアイコンを含むアプリケーションを開発しています。アイコンを押すと、アプリの削除アニメーションのように小刻みに動くようにします。このアニメーションシーケンスをコーディングするための最良の方法は何でしょうか?

36
user446718

ヴィンジウスの答えはとてもクールです。ただし、ウォブルは0ラジアンから0.08までしか回転しません。したがって、ぐらつきは少し不均衡に見える可能性があります。これと同じ問題が発生した場合は、CABasicRotationではなくCAKeyframeAnimationを使用して、負の回転と正の回転の両方を追加することをお勧めします。

- (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:@""];
33
paiego

IOSの実装をもう少し詳しく見てみると、ここで説明したコードよりも少し現実的になる2つのことがあります。

  • アイコンにはバウンスと回転があるように見えます
  • すべてのアイコンには独自のタイミングがあります-すべてが同期されているわけではありません

私はここでの回答に基づいて(そしてこれからの助けを借りて 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に実装しました。UICollectionViewには30個のアイテムがバウンスし、iPad2でのパフォーマンスは完璧でした。

15

スイフト:-

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;
}
14
Mitul Marsoniya

私はiPadアプリのためにそのようなことをしようとしました。

ビューに対して(CAAnimationを使用して)いくつかの回転を実行しようとしました。これが私が書いたサンプルコードです:

-(CAAnimation *)getShakeAnimation {
 
 CABasicAnimation * animation; 
 CATransform3D変換; 
 
 //回転行列を作成
 transform = CATransform3DMakeRotation(0.08、0、0、1.0); 
 
 //レイヤーの変換をアニメーション化する基本的なアニメーションを作成します
 animation = [CABasicAnimationanimationWithKeyPath:@ "transform"] ; 
 
 //変換をアニメーションの値として割り当てます
 animation.toValue = [NSValue valueWithCATransform3D:transform]; 
 
 animation.autoreverses =はい; 
 animation.duration = 0.1; 
 animation.repeatCount = HUGE_VALF; 
 
アニメーションを返す; 
 
}

そして、これをレイヤーに適用してみてください(関数:addAnimationを使用)。ここで、autoreversesプロパティは、左右の向きを交互にすることです。他の値を角度と期間に設定してみてください。

しかし、私の場合、最初のレイヤーの向きに応じて、CATransform3DMakeRotationメソッドに他の角度を追加する必要がありました^^

幸運を !ヴィンセント

11
Vinzius

Sebastienの答えを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()
}
6
Victor96

別のスレッドで回答a Swift Apple独自のアルゴリズムがリバースエンジニアリングされたと思われる4つのバージョン: https://stackoverflow.com/a/47730519/5018607

2
Paul Popiel
    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)
    }

このiOSSpingBoardを見てください

2
Beslan Tularov

私のニーズに合うように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

これが他の誰かに役立つことを願っています。

0
Roger Oba