UIView shake animation

后端 未结 16 1236
梦毁少年i
梦毁少年i 2020-11-28 18:07

i\'m trying to make a UIView shake when a button is pressed.

I am adapting the code I found on http://www.cimgf.com/2008/02/27/core-animation-tutorial-window-shake-e

相关标签:
16条回答
  • 2020-11-28 18:47

    Based on @bandejapaisa answer, UIView extension for Swift 3

    extension UIView {
        func shake() {
            let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
            animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
            animation.duration = 0.6
            animation.values = [-20, 20, -20, 20, -10, 10, -5, 5, 0]
            layer.addAnimation(animation, forKey: "shake")
        }
    }
    
    0 讨论(0)
  • 2020-11-28 18:49

    Here's my nice and simple looking version This simulates the shake you get on Mac OS X when you do an incorrect login. You could add this as a category on UIView if you like.

    @implementation UIView (DUExtensions)
    
    - (void) shake {
        CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        animation.duration = 0.6;
        animation.values = @[ @(-20), @(20), @(-20), @(20), @(-10), @(10), @(-5), @(5), @(0) ];
        [self.layer addAnimation:animation forKey:@"shake"];  
    }
    
    @end
    

    The animation values are the x offset from the views current position. Positive values shifting the view to the right, and negative values to the left. By successively lowering them, you get a shake that naturally loses momentum. You can tweak these numbers if you like.

    0 讨论(0)
  • 2020-11-28 18:52

    You can try the following code:

    + (void)vibrateView:(UIView*)view
    {
        CABasicAnimation *shiverAnimationR;
        shiverAnimationR = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        shiverAnimationR.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(1)];
        //shiverAnimationR.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(-10)];
        shiverAnimationR.duration = 0.1;
        shiverAnimationR.repeatCount = 1000000.0; // Use A high Value
        shiverAnimationR.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
    
        [view.layer addAnimation: shiverAnimationR forKey:@"shiverAnimationR"];
    
        CABasicAnimation * shiverAnimationL;
        shiverAnimationL = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        //shiverAnimationL 2.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(10)];
        shiverAnimationL.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(-1)];
        shiverAnimationL.duration = 0.1;
        shiverAnimationL.repeatCount = 1000000.0;
        shiverAnimationL.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
    
        [view.layer addAnimation: shiverAnimationL forKey:@"shiverAnimationL"];
    
    }
    

    From the link.

    0 讨论(0)
  • 2020-11-28 18:53

    I prefer this solution that has a nice springy behavior, ideal for a wrong-password shake animation.

    view.transform = CGAffineTransformMakeTranslation(20, 0);
    [UIView animateWithDuration:0.4 delay:0.0 usingSpringWithDamping:0.2 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        view.transform = CGAffineTransformIdentity;
    } completion:nil];
    

    Swift 3

    extension UIView {
        func shake() {
            self.transform = CGAffineTransform(translationX: 20, y: 0)
            UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 1, options: .curveEaseInOut, animations: {
                self.transform = CGAffineTransform.identity
            }, completion: nil)
        }
    }
    
    0 讨论(0)
  • 2020-11-28 18:53

    Swift 4.0:

    Based on the top answer but a refinement over the animation: This does not have the jumps at the start and end of animation.

        let midX = center.x
        let midY = center.y
    
        let rightAnim = CABasicAnimation(keyPath: #keyPath(CALayer.position))
        rightAnim.duration      = 0.07
        rightAnim.autoreverses  = true
        rightAnim.fromValue     = CGPoint(x: midX, y: midY)
        rightAnim.toValue       = CGPoint(x: midX + 9, y: midY)
    
        let leftAnim = CABasicAnimation(keyPath: #keyPath(CALayer.position))
        leftAnim.duration       = 0.07
        leftAnim.autoreverses   = true
        leftAnim.fromValue      = CGPoint(x: midX, y: midY)
        leftAnim.toValue        = CGPoint(x: midX - 9, y: midY)
    
        let group = CAAnimationGroup()
        group.duration      = leftAnim.duration + rightAnim.duration
        group.animations    = [rightAnim, leftAnim]
        group.repeatCount   = 3
    
        layer.add(group, forKey: #keyPath(CALayer.position))
    
    0 讨论(0)
  • 2020-11-28 18:54

    I refactored @Matt Long code and made a category to UIView. Now it's much more reusable and easy to use.

    @implementation UIView (Animation)
    
    - (void)shakeViewWithOffest:(CGFloat)offset {
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.x"];
        [animation setDuration:0.05];
        [animation setRepeatCount:6];
        [animation setAutoreverses:YES];
        [animation setFromValue:@([self center].x-offset)];
        [animation setToValue:@([self center].x+offset)];
    
        [self.layer addAnimation:animation forKey:@"position.x"];
    }
    
    - (void)shake {
        [self shakeViewWithOffest:7.0f];
    }
    @end
    
    0 讨论(0)
提交回复
热议问题