UIView शेक एनीमेशन


82

जब एक बटन दबाया जाता है तो मैं एक UIView शेक बनाने की कोशिश कर रहा हूं।

मैं http://www.cimgf.com/2008/02/27/core-animation-tutorial-window-shake-effect/ पर पाए गए कोड को अपना रहा हूं ।

हालाँकि, UIView को हिला देने के लिए निम्न कोड को अनुकूलित करने की कोशिश करने से यह काम नहीं करता है:

- (void)animate {
    const int numberOfShakes = 8;
    const float durationOfShake = 0.5f;
    const float vigourOfShake = 0.1f;

    CAKeyframeAnimation *shakeAnimation = [CAKeyframeAnimation animation];

    CGRect frame = lockView.frame;

    CGMutablePathRef shakePath = CGPathCreateMutable();
    CGPathMoveToPoint(shakePath, NULL, CGRectGetMinX(frame), CGRectGetMinY(frame));

    for (int index = 0; index < numberOfShakes; ++index) {
        CGPathAddLineToPoint(shakePath, NULL, CGRectGetMinX(frame) - frame.size.width * vigourOfShake, CGRectGetMinY(frame));

        CGPathAddLineToPoint(shakePath, NULL, CGRectGetMinX(frame) + frame.size.width * vigourOfShake, CGRectGetMinY(frame));
    }

    CGPathCloseSubpath(shakePath);

    shakeAnimation.path = shakePath;
    shakeAnimation.duration = durationOfShake;


    [lockView.layer addAnimation:shakeAnimation forKey:@"frameOrigin"];

}

जवाबों:


204

मैंने वो पोस्ट लिखी। यह एक UIView के लिए ओवरकिल है, इसके अलावा पैरामीटर एक OSX ऐप की ओर तैयार हैं। इसके बजाय ऐसा करें।

CABasicAnimation *animation = 
                         [CABasicAnimation animationWithKeyPath:@"position"];
[animation setDuration:0.05];
[animation setRepeatCount:8];
[animation setAutoreverses:YES];
[animation setFromValue:[NSValue valueWithCGPoint:
               CGPointMake([lockView center].x - 20.0f, [lockView center].y)]];
[animation setToValue:[NSValue valueWithCGPoint:
               CGPointMake([lockView center].x + 20.0f, [lockView center].y)]];
[[lockView layer] addAnimation:animation forKey:@"position"];

आपको अवधि और दोहराने के मापदंडों के साथ-साथ केंद्र से एक्स की दूरी और मूल्यों में खेलना होगा, लेकिन यह आपको वह देना चाहिए जो आपको चाहिए। मुझे आशा है कि वह मदद करेंगे। अगर आपका कोई प्रश्न हैं, तो मुझे से पूछें।

---


स्विफ्ट 3.0

let midX = lockView.center.x
let midY = lockView.center.y

let animation = CABasicAnimation(keyPath: "position")
animation.duration = 0.06
animation.repeatCount = 4
animation.autoreverses = true
animation.fromValue = CGPoint(x: midX - 10, y: midY)
animation.toValue = CGPoint(x: midX + 10, y: midY)
layer.add(animation, forKey: "position")

धन्यवाद, मैं इसे Xamarin IOS में बनाने के लिए आपके उत्तर का उपयोग करता हूं। यदि कोई भी इसका उपयोग करना चाहेगा, तो वह यहां है: gist.github.com/jorwan/1ed57459c7b01b5b5b5b113521926219cf
जॉर्ज वांडर सैंटाना

@ मैट अगर मैं बेतरतीब ढंग से हिलाना चाहता हूं, तो यूआईईवीई प्रत्येक हिला पर यादृच्छिक दिशाओं में चलता है?
एहतेशाम हसन

@ एहतेशामहसन वास्तव में यादृच्छिक नहीं हो सकता है। पदों / बिंदुओं को एक सीमा के भीतर होना होगा और आप यह नहीं चाहेंगे कि यह उस सीमा के चरम सीमा (उदाहरण के लिए कोने से कोने) के बीच हिल जाए (हालांकि यह आपके ऊपर है)। सरल उत्तर को एक सरणी में संभावित स्थिति (सीजी पॉइंट) में रखा जाता है और एक यादृच्छिक संख्या जनरेटर को बीज देता है जो आपके सरणी में बिंदुओं की संख्या से कम एक सूचकांक प्रदान करता है और फिर मेरे जवाब में वर्णित उसी तकनीक का उपयोग करके उस बिंदु पर स्थिति को स्थानांतरित करता है।
मैट लॉन्ग

78

मैं इस समाधान को पसंद करता हूं जिसमें एक अच्छा वसंत व्यवहार होता है, एक गलत-पासवर्ड शेक एनीमेशन के लिए आदर्श है।

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

स्विफ्ट 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)
    }
}

आप इसे कैसे दोहराते हैं? यह केवल एक बार ही होता है।
क्रैशलॉट

1
अगर मैं ओपी को सही ढंग से समझता हूं, तो वह एक शॉर्ट शेक एनीमेशन चाहता था। चूंकि वास्तविक जीवन में एक हिला आंदोलन में घर्षण होता है और समय के साथ धीमा हो जाता है, मुझे मेरा समाधान सबसे उपयुक्त लगता है। यदि आप इसे लंबे समय तक हिलाना चाहते हैं, तो भिगोना और initialVelocity मापदंडों के साथ प्रयोग करें। यदि आप इसे दोहराना चाहते हैं अनिश्चित काल के लिए अन्य समाधानों में से एक के साथ जाएं।
ऑर्टविन Gentz

यह एनीमेशन सबसे अच्छा था, सहमत था। बस इसे कुछ बार दोहराना चाहते हैं, बस इतना ही।
Crashalot

यदि आप इसे विस्तारित करना चाहते हैं, तो अवधि, भिगोना और आरंभिक मानों के साथ खेलने का प्रयास करें।
ऑर्टविन Gentz

1
पूर्ण हैंडलर का उपयोग करने की संभावना के कारण यह समाधान बहुत बेहतर है।
यूरी ग्रिगोरिएव

34

यहाँ मेरा अच्छा और सरल दिखने वाला संस्करण है यह मैक ओएस एक्स पर मिलने वाले शेक का अनुकरण करता है जब आप एक गलत लॉगिन करते हैं। यदि आप चाहें, तो आप इसे UIView पर एक श्रेणी के रूप में जोड़ सकते हैं।

@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

एनिमेशन मान वर्तमान स्थिति के विचारों से ऑफसेट हैं। सकारात्मक मूल्य दृश्य को दाईं ओर और नकारात्मक मूल्यों को बाईं ओर स्थानांतरित कर रहे हैं। क्रमिक रूप से उन्हें कम करके, आपको एक झटका मिलता है जो स्वाभाविक रूप से गति खो देता है। आप चाहें तो इन नंबरों को ट्वीक कर सकते हैं।


1
शानदार लग रहा है और ध्वनि विचार यह एक UIView श्रेणी में एम्बेड करने के लिए। UIViews को हिला देना चाहिए, अवधि!
पेड्रो बोर्ग्स

जब धीमी गति (लंबे समय तक) में उपयोग किया जाता है, तो यह एनीमेशन रिपीटाउंट का उपयोग करने वाले दूसरे उत्तर की तुलना में बहुत अधिक चिकना होता है।
थियो

इस कोड का उपयोग करने के बाद कुछ विचार। टाइमिंग फंक्शन - रैखिक के लिए चूक इसलिए इसे सेट करने के लिए आवश्यक नहीं है। एनिमेशन वैल्यूज़ - आप एक कदम और आगे बढ़ सकते हैं और अच्छे गणितीय मूल्यों का निर्माण करने के लिए एक फंक्शन को परिभाषित कर सकते हैं ... यह बहुत काम करता है :)
जॉर्डन स्मिथ

17

यदि किसी को इसकी आवश्यकता हो तो विस्तार के रूप में यहां स्विफ्ट संस्करण है

extension UIImageView{
    func vibrate(){
        let animation = CABasicAnimation(keyPath: "position")
        animation.duration = 0.05
        animation.repeatCount = 5
        animation.autoreverses = true
        animation.fromValue = NSValue(CGPoint: CGPointMake(self.center.x - 2.0, self.center.y))
        animation.toValue = NSValue(CGPoint: CGPointMake(self.center.x + 2.0, self.center.y))
        self.layer.addAnimation(animation, forKey: "position")
    }
}

यह एक छोटा UIImageView (15x15 के आसपास) को चेतन करेगा। यदि आपको कुछ बड़ा करने की आवश्यकता है, तो आप आंदोलन के 2.0 कारक को कुछ अधिक से अधिक बदल सकते हैं।


8

@Bandejapaisa उत्तर के आधार पर, स्विफ्ट 3 के लिए UIView विस्तार

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

4

आप इस कोड का टुकड़ा आज़मा सकते हैं:

नीचे दिए गए कोड को कॉल करने के लिए, उपयोग करें: [self earthquake:myObject];

#pragma mark EarthQuake Methods

- (void)earthquake:(UIView*)itemView
{
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); 

    CGFloat t = 2.0;

    CGAffineTransform leftQuake  = CGAffineTransformTranslate(CGAffineTransformIdentity, t, -t);
    CGAffineTransform rightQuake = CGAffineTransformTranslate(CGAffineTransformIdentity, -t, t);

    itemView.transform = leftQuake;  // starting point

    [UIView beginAnimations:@"earthquake" context:itemView];
    [UIView setAnimationRepeatAutoreverses:YES]; // important
    [UIView setAnimationRepeatCount:3];
    [UIView setAnimationDuration:0.05];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(earthquakeEnded:finished:context:)];

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

    [UIView commitAnimations];
}

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

4

आप इस विधि को UIButton क्लिक इवेंट पर कॉल कर सकते हैं

-(void)shakescreen
{
    //Shake screen
    CGFloat t = 5.0;
    CGAffineTransform translateRight = CGAffineTransformTranslate(CGAffineTransformIdentity, t, t);
    CGAffineTransform translateLeft = CGAffineTransformTranslate(CGAffineTransformIdentity, -t, -t);

    self.view.transform = translateLeft;

    [UIView animateWithDuration:0.05 delay:0.0 options:UIViewAnimationOptionAutoreverse|UIViewAnimationOptionRepeat animations:^
    {
         [UIView setAnimationRepeatCount:2.0];
         self.view.transform = translateRight;
    } completion:^(BOOL finished)

      {
          if (finished) 
          {
             [UIView animateWithDuration:0.05 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^
          {
              self.view.transform = CGAffineTransformIdentity;
          } 
          completion:NULL];
      }
  }];
}

आशा है कि यह आपकी मदद करेगा :-)


3

C # Xamarin.iOS iOS में UIView शेक एनीमेशन बनाने का उत्तर का संस्करण नीचे है

        CAKeyFrameAnimation keyframeAnimation = CAKeyFrameAnimation.GetFromKeyPath(new NSString("transform.translation.x"));
        keyframeAnimation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
        keyframeAnimation.Duration = 0.6f;
        keyframeAnimation.Values = new NSObject[]{ new NSNumber(-20f), new NSNumber(20f), new NSNumber(-20f), new NSNumber(20f), new NSNumber(-10f), new NSNumber(10f), new NSNumber(-5f), new NSNumber(5f), new NSNumber(0f) };
        shakyView.Layer.AddAnimation(keyframeAnimation, "shake");

2

यहाँ एक है कि हिला को क्षय करने के लिए एक स्पंज समारोह का उपयोग करता है:

- (void)shake
{
    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    animation.duration = 0.5;
    animation.delegate = self;
    animation.fillMode = kCAFillModeForwards;
    animation.removedOnCompletion = YES;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

    NSMutableArray* values = [[NSMutableArray alloc] init];

    int steps = 100;
    double position = 0;
    float e = 2.71;

    for (int t = 0; t < steps; t++)
    {
        position = 10 * pow(e, -0.022 * t) * sin(0.12 * t);
        NSValue* value = [NSValue valueWithCGPoint:CGPointMake([self center].x - position, [self center].y)];
        DDLogInfo(@"Value: %@", value);
        [values addObject:value];
    }

    animation.values = values;
    [[self layer] addAnimation:animation forKey:@"position"];

}

2

मैंने @Matt लॉन्ग कोड रिफैक्ट किया और एक श्रेणी बनाई UIView। अब यह अधिक पुन: प्रयोज्य और उपयोग में आसान है।

@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

2

@ मिहेल-इसव उत्तर के आधार पर स्विफ्ट 3 कार्यान्वयन

private enum Axis: StringLiteralType {
    case x = "x"
    case y = "y"
}

extension UIView {
    private func shake(on axis: Axis) {
        let animation = CAKeyframeAnimation(keyPath: "transform.translation.\(axis.rawValue)")
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        animation.duration = 0.6
        animation.values = [-20, 20, -20, 20, -10, 10, -5, 5, 0]
        layer.add(animation, forKey: "shake")
    }
    func shakeOnXAxis() {
        self.shake(on: .x)
    }
    func shakeOnYAxis() {
        self.shake(on: .y)
    }
}

2

@ स्विफ्ट 4.2 में इसका उत्तर

extension UIView {
func shake() {
    let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
    animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
    animation.duration = 0.6
    animation.values = [-20, 20, -20, 20, -10, 10, -5, 5, 0]
    self.layer.add(animation, forKey: "shake")
}}

1
अंतिम पंक्ति self.layer.add (एनीमेशन, forKey: "शेक") के साथ तय की जानी चाहिए
ilkayaktas

1

आप निम्न कोड आज़मा सकते हैं:

+ (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"];

}

लिंक से।


1

यहाँ एक संस्करण का उपयोग किया गया है,

+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion

IOS 7 में पेश किया गया।

    const CGFloat xDelta = 16.0f;

    [UIView animateKeyframesWithDuration:0.50f
                                   delay:0.0f
                                 options:UIViewKeyframeAnimationOptionCalculationModeLinear
                              animations:^{

                                  [UIView addKeyframeWithRelativeStartTime:0.0
                                                          relativeDuration:(1.0/6.0)
                                                                animations:^{
                                                                    self.passwordTextField.transform = self.usernameTextField.transform = CGAffineTransformMakeTranslation(xDelta, 0.0);
                                                                }];

                                  [UIView addKeyframeWithRelativeStartTime:(1.0/6.0)
                                                          relativeDuration:(1.0/6.0)
                                                                animations:^{
                                                                    self.passwordTextField.transform = self.usernameTextField.transform = CGAffineTransformMakeTranslation(-xDelta, 0.0);
                                                                }];

                                  [UIView addKeyframeWithRelativeStartTime:(1.0/3.0)
                                                          relativeDuration:(1.0/3.0)
                                                                animations:^{
                                                                    self.passwordTextField.transform = self.usernameTextField.transform = CGAffineTransformMakeTranslation(xDelta/2.0, 0.0);
                                                                }];

                                  [UIView addKeyframeWithRelativeStartTime:(2.0/3.0)
                                                          relativeDuration:(1.0/3.0)
                                                                animations:^{
                                                                    self.passwordTextField.transform = self.usernameTextField.transform = CGAffineTransformIdentity;
                                                                }];

                              }
                              completion:NULL];


1

स्विफ्ट 4.0:

शीर्ष उत्तर के आधार पर लेकिन एनीमेशन पर एक परिशोधन: यह एनीमेशन के शुरू और अंत में कूदता नहीं है।

    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))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.