UIView अनंत 360 डिग्री रोटेशन एनीमेशन?


251

मैं UIImageView360 डिग्री घूमने की कोशिश कर रहा हूं , और ऑनलाइन कई ट्यूटोरियल देख चुका हूं । मैं उनमें से कोई भी काम नहीं कर सकता था UIView, या तो बिना रुके, या एक नई स्थिति में कूदने के लिए।

  • इसे कैसे प्राप्त किया जा सकता है?

नवीनतम चीज़ जो मैंने कोशिश की है वह है:

[UIView animateWithDuration:1.0
                      delay:0.0
                    options:0
                 animations:^{
                     imageToMove.transform = CGAffineTransformMakeRotation(M_PI);
                 } 
                 completion:^(BOOL finished){
                     NSLog(@"Done!");
                 }];

लेकिन अगर मैं 2 * pi का उपयोग करता हूं, तो यह बिल्कुल नहीं चलता (क्योंकि यह एक ही स्थिति है)। अगर मैं सिर्फ पीआई (180 डिग्री) करने की कोशिश करता हूं, तो यह काम करता है, लेकिन अगर मैं फिर से विधि कहता हूं, तो यह पीछे की ओर घूमता है।

संपादित करें :

[UIView animateWithDuration:1.0
                      delay:0.0
                    options:0
                 animations:^{
                     [UIView setAnimationRepeatCount:HUGE_VALF];
                     [UIView setAnimationBeginsFromCurrentState:YES];
                     imageToMove.transform = CGAffineTransformMakeRotation(M_PI);
                 } 
                 completion:^(BOOL finished){
                     NSLog(@"Done!");
                 }];

या तो काम नहीं करता है। यह 180डिग्री में जाता है, एक विभाजन दूसरे के लिए रुकता है, फिर 0दोबारा शुरू होने से पहले डिग्री पर वापस रहता है ।

जवाबों:


334

एक विधि मिली (मैंने इसे थोड़ा संशोधित किया) जो मेरे लिए पूरी तरह से काम करती थी: iPhone UIImageView रोटेशन

#import <QuartzCore/QuartzCore.h>

- (void) runSpinAnimationOnView:(UIView*)view duration:(CGFloat)duration rotations:(CGFloat)rotations repeat:(float)repeat {
    CABasicAnimation* rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];
    rotationAnimation.duration = duration;
    rotationAnimation.cumulative = YES;
    rotationAnimation.repeatCount = repeat ? HUGE_VALF : 0;

    [view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

25
#import <QuartzCore / QuartzCore.h>
AlBeebe

3
Add QuartzCore.framework Project-> बिल्ड चरणों
gjpc

9
यह iOS 3.0 और उससे नीचे के लेकिन नए प्रोग्रामर और नए प्रोजेक्ट्स के लिए सही कोड है, Apple अब उपयोगकर्ताओं को डॉक्स में इन तरीकों से दूर करने की चेतावनी देता है और @Nate कोड ब्लॉक आधारित एनिमेशन का उपयोग करता है जिसे Apple अब पसंद करता है
PaulWoodIII

1
dc से @cvsguimaraes: "यह निर्धारित करता है कि क्या संपत्ति का मूल्य पिछले दोहराने चक्र के अंत में मूल्य है, और वर्तमान दोहराने चक्र का मूल्य है।"
स्मादन

12
इससे कुछ लोगों को मदद मिल सकती है, [view.layer removeAllAnimations]; जरूरत पड़ने पर एनीमेशन बंद करना।
arunit21

112

विचार के लिए रिचर्ड जे। रॉस III को कुडोस, लेकिन मैंने पाया कि उनका कोड काफी वह नहीं था जिसकी मुझे आवश्यकता थी। optionsमुझे विश्वास है कि डिफ़ॉल्ट , आपको देना है UIViewAnimationOptionCurveEaseInOut, जो एक निरंतर एनीमेशन में सही नहीं दिखता है। इसके अलावा, मैंने एक चेक जोड़ा ताकि मैं अपनी एनीमेशन को एक चौथाई मोड़ पर रोक सकूं अगर मुझे ज़रूरत हो ( अनंत नहीं , बल्कि अनिश्चित अवधि की), और पहले 90 डिग्री के दौरान त्वरण रैंप बना दिया, और पिछले 90 डिग्री के दौरान मंदी हो गई (एक स्टॉप के बाद अनुरोध किया गया है):

// an ivar for your class:
BOOL animating;

- (void)spinWithOptions:(UIViewAnimationOptions)options {
   // this spin completes 360 degrees every 2 seconds
   [UIView animateWithDuration:0.5
                         delay:0
                       options:options
                    animations:^{
                       self.imageToMove.transform = CGAffineTransformRotate(imageToMove.transform, M_PI / 2);
                    }
                    completion:^(BOOL finished) {
                       if (finished) {
                          if (animating) {
                             // if flag still set, keep spinning with constant speed
                             [self spinWithOptions: UIViewAnimationOptionCurveLinear];
                          } else if (options != UIViewAnimationOptionCurveEaseOut) {
                             // one last spin, with deceleration
                             [self spinWithOptions: UIViewAnimationOptionCurveEaseOut];
                          }
                       }
                    }];
}

- (void)startSpin {
   if (!animating) {
      animating = YES;
      [self spinWithOptions: UIViewAnimationOptionCurveEaseIn];
   }
}

- (void)stopSpin {
    // set the flag to stop spinning after one last 90 degree increment
    animating = NO;
}

अपडेट करें

मैंने फिर से कताई शुरू करने के अनुरोधों को संभालने की क्षमता को जोड़ा ( startSpin), जबकि पिछली स्पिन नीचे (पूरा) घुमावदार है। गितुब पर यहाँ नमूना परियोजना ।


2
इसका उपयोग करते हुए, मैं प्रत्येक PI / 2 कोण (90 डिग्री) पर एनीमेशन में एक संक्षिप्त ठहराव और CABasicAnimation का उपयोग करके चुने गए उत्तर पर CPU उपयोग में मामूली वृद्धि को नोटिस करता हूं। CABasicAnimation विधि एक निर्दोष चिकनी एनीमेशन पैदा करती है।
अर्जुन मेहता

1
@ डिलिप, के M_PI / 2साथ बदलें - (M_PI / 2)। (प्रत्येक पंक्ति के अंत को देखने के लिए दाईं ओर स्क्रॉल कोड)
Nate

1
@Dipip, मुझे नहीं पता कि आप अपने कोड में किस अवधि का उपयोग कर रहे हैं। एक ही 0.590 डिग्री प्रति सेकंड, के रूप में मैं कर रहा हूँ? यदि हां, तो मेरा कोड आपको 90 डिग्री के रोटेशन के एक अंश पर नहीं रुकने देता । यह आपको पूरे 90 डिग्री के अंतराल पर रुकने की अनुमति देता है, लेकिन एक अतिरिक्त 90 डिग्री रोटेशन को जोड़ता है, "बाहर ढील दी गई"। इसलिए, ऊपर दिए गए कोड में, यदि आप stopSpin0.35 सेकंड के बाद कॉल करते हैं, तो यह एक और 0.65 सेकंड के लिए स्पिन करेगा, और 180 डिग्री कुल रोटेशन पर रोक देगा। यदि आपके पास अधिक विस्तृत प्रश्न हैं, तो आपको संभवतः एक नया प्रश्न खोलना चाहिए। इस उत्तर से लिंक करने के लिए स्वतंत्र महसूस करें।
नैट

1
क्या हो रहा है, @MohitJethwa देख रहे हो? मेरे पास एक ऐप है जो इसका उपयोग करता है, और यह अभी भी मेरे लिए iOS 8.1 पर काम करता है।
नैट

1
@ हेमांग, यकीन है, लेकिन यह सवाल नहीं था। यदि आप ऐसा करने की कोशिश कर रहे हैं तो मैं एक नया प्रश्न पोस्ट करूँगा।
नट

85

स्विफ्ट में, आप अनंत रोटेशन के लिए निम्न कोड का उपयोग कर सकते हैं:

स्विफ्ट 4

extension UIView {
    private static let kRotationAnimationKey = "rotationanimationkey"

    func rotate(duration: Double = 1) {
        if layer.animation(forKey: UIView.kRotationAnimationKey) == nil {
            let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")

            rotationAnimation.fromValue = 0.0
            rotationAnimation.toValue = Float.pi * 2.0
            rotationAnimation.duration = duration
            rotationAnimation.repeatCount = Float.infinity

            layer.add(rotationAnimation, forKey: UIView.kRotationAnimationKey)
        }
    }

    func stopRotating() {
        if layer.animation(forKey: UIView.kRotationAnimationKey) != nil {
            layer.removeAnimation(forKey: UIView.kRotationAnimationKey)
        }
    }
}

स्विफ्ट 3

let kRotationAnimationKey = "com.myapplication.rotationanimationkey" // Any key

func rotateView(view: UIView, duration: Double = 1) {
    if view.layer.animationForKey(kRotationAnimationKey) == nil {
        let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")

        rotationAnimation.fromValue = 0.0
        rotationAnimation.toValue = Float(M_PI * 2.0)
        rotationAnimation.duration = duration
        rotationAnimation.repeatCount = Float.infinity

        view.layer.addAnimation(rotationAnimation, forKey: kRotationAnimationKey)
    }
}

स्टॉपिंग की तरह है:

func stopRotatingView(view: UIView) {
    if view.layer.animationForKey(kRotationAnimationKey) != nil {
        view.layer.removeAnimationForKey(kRotationAnimationKey)
    }
}

KRotationAnimationKey क्या है?
लूडा

यह एक निरंतर स्ट्रिंग कुंजी है, जो आपको एनीमेशन को पहचानने और खोजने में मदद करता है। यह आप चाहते हैं किसी भी स्ट्रिंग हो सकता है। निष्कासन प्रक्रिया में, आप देख सकते हैं कि इस कुंजी द्वारा एनीमेशन को खोजा और हटा दिया गया है।
काडी

क्या यह कोई स्ट्रिंग या कुछ विशिष्ट है?
लुडा

देर से जवाब के लिए क्षमा करें, लेकिन हाँ, यह किसी भी स्ट्रिंग हो सकता है।
काडी

1
// उत्तर में किसी भी कुंजी के रूप में
ज़ेंडर जांग

67

नैट का उत्तर स्टॉप और स्टार्ट एनिमेशन के लिए आदर्श है और बेहतर नियंत्रण देता है। मुझे पता था कि तुम्हारा काम क्यों नहीं किया गया और वह क्या करता है। मैं अपने निष्कर्ष यहाँ और कोड का एक सरल संस्करण साझा करना चाहता था जो बिना रुके लगातार एक UIView को चेतन करेगा।

यह वह कोड है जिसका मैंने उपयोग किया है,

- (void)rotateImageView
{
    [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        [self.imageView setTransform:CGAffineTransformRotate(self.imageView.transform, M_PI_2)];
    }completion:^(BOOL finished){
        if (finished) {
            [self rotateImageView];
        }
    }];
}

मैंने ine CGAffineTransformMakeRotation ’के बजाय ate CGAffineTransformRotate’ का उपयोग किया था क्योंकि पूर्व में वह परिणाम मिलता है जो एनीमेशन आय के रूप में सहेजा जाता है। यह एनीमेशन के दौरान दृश्य को कूदने या रीसेट करने से रोक देगा।

एक और बात 'UIViewAnimationOptionRepeat' का उपयोग नहीं करना है क्योंकि दोहराए जाने से पहले एनीमेशन के अंत में, यह परिवर्तन को रीसेट करता है जिससे दृश्य अपनी मूल स्थिति पर वापस आ जाता है। एक दोहराने के बजाय, आप पुनरावृत्ति करते हैं ताकि रूपांतरण कभी भी मूल मूल्य पर रीसेट न हो क्योंकि एनीमेशन ब्लॉक वास्तव में कभी समाप्त नहीं होता है।

और अंतिम बात यह है कि, आपको 360 या 180 डिग्री (2 * M_PI या M_PI) के बजाय 90 डिग्री (M_PI / 2) के चरणों में दृश्य को बदलना होगा। क्योंकि रूपांतरण साइन और कोसाइन मूल्यों के मैट्रिक्स गुणन के रूप में होता है।

t' =  [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ] * t

इस प्रकार, यदि आप 180 डिग्री के परिवर्तन का उपयोग करते हैं, तो कहिए कि 180 पैदावार का कोसाइन -1 हर बार विपरीत दिशा में दृश्य परिवर्तन कर रहा है (नोट-नैट के उत्तर में यह समस्या भी होगी यदि आप परिवर्तन का मूल मान M_PI में बदल देते हैं)। एक 360-डिग्री परिवर्तन बस देखने के लिए कह रहा है कि वह कहां था, इसलिए आपको कोई भी रोटेशन नहीं दिखता है।


मेरे उत्तर का पूरा बिंदु (और रिचर्ड का उत्तर जो इसे प्राप्त करता है) स्विचिंग दिशाओं से बचने के लिए, 90 डिग्री चरणों का उपयोग करना है। 90 डिग्री भी अपेक्षाकृत अच्छी तरह से काम करती है यदि आप कभी रोटेशन को रोकना चाहते हैं , क्योंकि कई छवियों में 180 डिग्री या 90 डिग्री समरूपता है।
नैट

हां, मुझे लगा कि मैं समझाऊंगा कि इसका इस्तेमाल क्यों किया जा रहा है :)
ram

2
@ मिनी लेकिन वहां ब्रेकपॉइंट सेट करने के बाद मैं देख रहा हूं कि स्टैक ओवरफ्लो नहीं होगा क्योंकि सिस्टम द्वारा पूर्ण ब्लॉक कहा जाता है, rotateImageViewतब तक पहले ही समाप्त हो चुका होता है। तो यह वास्तव में उस अर्थ में पुनरावर्ती नहीं है।
ह्यूगी

1
वांछित कार्यक्षमता वाले छोटे संस्करण के लिए अच्छा उत्तर +1।
प्रदीप मित्तल

1
मैं वास्तव में UIViewAnimationOptionRepeat का उपयोग नहीं करने के स्पष्टीकरण की सराहना करता हूं।
जोनाथन ज़न

21

यदि आप चाहते हैं कि सभी छवि को अंतहीन रूप से घुमाएं, तो यह काफी अच्छा काम करता है, और बहुत सरल है:

NSTimeInterval duration = 10.0f;
CGFloat angle = M_PI / 2.0f;
CGAffineTransform rotateTransform = CGAffineTransformRotate(imageView.transform, angle);

[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionRepeat| UIViewAnimationOptionCurveLinear animations:^{
    imageView.transform = rotateTransform;
} completion:nil];

मेरे अनुभव में, यह त्रुटिपूर्ण रूप से काम करता है, लेकिन सुनिश्चित करें कि आपकी छवि बिना किसी ऑफ़सेट के अपने केंद्र के चारों ओर घूमने में सक्षम है, या पीआई के चारों ओर इसे बनाते ही छवि एनीमेशन "कूद" जाएगा।

स्पिन की दिशा बदलने के लिए, angle( angle *= -1) का चिन्ह बदलें ।

अद्यतन @AlexPretzlav द्वारा टिप्पणियां बनाया मुझे इस पर फिर से, और मैंने महसूस किया कि जब मैं इस छवि को मैं घूर्णन था दोनों ऊर्ध्वाधर और क्षैतिज अक्ष के साथ नजर आता था लिखा था, जिसका अर्थ है छवि वास्तव में केवल 90 डिग्री घूर्णन गया था और तब रीसेट करने, हालांकि यह देखा की तरह चारों तरफ चक्कर लगाना जारी था।

इसलिए, यदि आपकी छवि मेरी जैसी है, तो यह बहुत अच्छा होगा, हालाँकि, यदि छवि सममित नहीं है, तो आप 90 डिग्री के बाद "स्नैप" को मूल अभिविन्यास पर वापस देखेंगे।

एक गैर-सममित छवि को घुमाने के लिए, आप स्वीकृत उत्तर के साथ बेहतर हैं।

इन कम सुरुचिपूर्ण समाधानों में से एक, नीचे देखा गया, वास्तव में छवि को घुमाएगा, लेकिन एनीमेशन को पुनरारंभ करने पर ध्यान देने योग्य हकलाना हो सकता है:

- (void)spin
{
    NSTimeInterval duration = 0.5f;
    CGFloat angle = M_PI_2;
    CGAffineTransform rotateTransform = CGAffineTransformRotate(self.imageView.transform, angle);

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        self.imageView.transform = rotateTransform;
    } completion:^(BOOL finished) {
        [self spin];
    }];
}

आप इसे केवल ब्लॉक के साथ भी कर सकते हैं, जैसा कि @ richard-j-ross-iii बताता है, लेकिन ब्लॉक बनाए रखने के बाद से आपको लूप की चेतावनी मिलेगी:

__block void(^spin)() = ^{
    NSTimeInterval duration = 0.5f;
    CGFloat angle = M_PI_2;
    CGAffineTransform rotateTransform = CGAffineTransformRotate(self.imageView.transform, angle);

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        self.imageView.transform = rotateTransform;
    } completion:^(BOOL finished) {
        spin();
    }];
};
spin();

1
यह केवल मेरे लिए एक रोटेशन का 1/4 घुमाया।
एलेक्स प्रेट्ज़लाव

@AlexPretzlav सुनिश्चित करें कि आपने UIViewAnimationOptionRepeatअपने एनीमेशन में सेट किया है options
लेविग्रोकर

1
मैंने किया था, यह 45 ° घूमता है, और फिर 0 ° तक वापस कूदकर 45 ° फिर से घूमता है
एलेक्स प्रेट्ज़लाव

इस "काम" के बारे में नई जानकारी के साथ मेरे उत्तर को अपडेट किया गया
लेविग्रोकर

21

चेक किए गए समाधान से एक स्विफ्ट एक्सटेंशन के साथ मेरा योगदान:

स्विफ्ट 4.0

extension UIView{
    func rotate() {
        let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotation.toValue = NSNumber(value: Double.pi * 2)
        rotation.duration = 1
        rotation.isCumulative = true
        rotation.repeatCount = Float.greatestFiniteMagnitude
        self.layer.add(rotation, forKey: "rotationAnimation")
    }
}

पदावनत:

extension UIView{
    func rotate() {
        let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotation.toValue = NSNumber(double: M_PI * 2)
        rotation.duration = 1
        rotation.cumulative = true
        rotation.repeatCount = FLT_MAX
        self.layer.addAnimation(rotation, forKey: "rotationAnimation")
    }
}

दोहराने की गिनती के लिए, एक का उपयोग कर सकते हैं .infinity
मिस्टर रोजर्स

15

स्विफ्ट 4 में अपडेट किया गया डेविड रैनसेक का जबरदस्त जवाब :

import UIKit

extension UIView {

        func startRotating(duration: CFTimeInterval = 3, repeatCount: Float = Float.infinity, clockwise: Bool = true) {

            if self.layer.animation(forKey: "transform.rotation.z") != nil {
                return
            }

            let animation = CABasicAnimation(keyPath: "transform.rotation.z")
            let direction = clockwise ? 1.0 : -1.0
            animation.toValue = NSNumber(value: .pi * 2 * direction)
            animation.duration = duration
            animation.isCumulative = true
            animation.repeatCount = repeatCount
            self.layer.add(animation, forKey:"transform.rotation.z")
        }

        func stopRotating() {

            self.layer.removeAnimation(forKey: "transform.rotation.z")

        }   

    }
}

मेरे लिए (एक UIButton पर) बहुत अच्छा काम किया। धन्यवाद!
अग्रिप्पा

मुझे आपकी सादगी पसंद आई
निकोलस मंज़िनी

10

क्वार्टर टर्न का उपयोग करें, और टर्न को बढ़ाएँ।

void (^block)() = ^{
    imageToMove.transform = CGAffineTransformRotate(imageToMove.transform, M_PI / 2);
}

void (^completion)(BOOL) = ^(BOOL finished){
    [UIView animateWithDuration:1.0
                          delay:0.0
                        options:0
                     animations:block
                     completion:completion];
}

completion(YES);

मैं ब्लॉक करने के लिए बहुत नया हूं, लेकिन यह विधि गलत है "असंगत ब्लॉक पॉइंटर प्रकारों को 'शून्य (^ const__strong ()' प्रकार के पैरामीटर को 'शून्य (^) (BOOL)' भेजने के लिए फेंकता है। मैंने कोड में अपनी रोटेशन विधि को बदलने की कोशिश की। मेरे सवाल के imageToMove.transform = CGAffineTransformRotate (imageToMove.transform, M_PI / 2) में, आपने उपयोग किया है, और एनीमेशन में अभी भी थोड़ी देरी है, और अगले मोड़ से पहले फिर से शुरू करें।
Derek

10

यह मेरे लिए काम कर रहा था:

[UIView animateWithDuration:1.0
                animations:^
{
    self.imageView.transform = CGAffineTransformMakeRotation(M_PI);
    self.imageView.transform = CGAffineTransformMakeRotation(0);
}];

यह अनंत समय के लिए नहीं हो रहा है!
बायजीवन

9

मुझे इस भंडार में अच्छा कोड मिला है ,

यहाँ यह कोड से मैं गति के लिए मेरी जरूरत के अनुसार छोटे बदलाव किया है :)

UIImageView + Rotate.h

#import <Foundation/Foundation.h>

@interface UIImageView (Rotate)
- (void)rotate360WithDuration:(CGFloat)duration repeatCount:(float)repeatCount;
- (void)pauseAnimations;
- (void)resumeAnimations;
- (void)stopAllAnimations;
@end

UIImageView + Rotate.m

#import <QuartzCore/QuartzCore.h>
#import "UIImageView+Rotate.h"

@implementation UIImageView (Rotate)

- (void)rotate360WithDuration:(CGFloat)duration repeatCount:(float)repeatCount
{

    CABasicAnimation *fullRotation;
    fullRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    fullRotation.fromValue = [NSNumber numberWithFloat:0];
    //fullRotation.toValue = [NSNumber numberWithFloat:(2*M_PI)];
    fullRotation.toValue = [NSNumber numberWithFloat:-(2*M_PI)]; // added this minus sign as i want to rotate it to anticlockwise
    fullRotation.duration = duration;
    fullRotation.speed = 2.0f;              // Changed rotation speed
    if (repeatCount == 0)
        fullRotation.repeatCount = MAXFLOAT;
    else
        fullRotation.repeatCount = repeatCount;

    [self.layer addAnimation:fullRotation forKey:@"360"];
}

//Not using this methods :)

- (void)stopAllAnimations
{

    [self.layer removeAllAnimations];
};

- (void)pauseAnimations
{

    [self pauseLayer:self.layer];
}

- (void)resumeAnimations
{

    [self resumeLayer:self.layer];
}

- (void)pauseLayer:(CALayer *)layer
{

    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed = 0.0;
    layer.timeOffset = pausedTime;
}

- (void)resumeLayer:(CALayer *)layer
{

    CFTimeInterval pausedTime = [layer timeOffset];
    layer.speed = 1.0;
    layer.timeOffset = 0.0;
    layer.beginTime = 0.0;
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    layer.beginTime = timeSincePause;
}

@end

@BreadicalMD, मैथ प्रोग्रामिंग की तरह है, आप एक ही काम कई तरह से कर सकते हैं। इसका मतलब यह नहीं है कि केवल 1 तरीका सही है और अन्य नहीं हैं। हाँ हर तरीके के लिए कुछ पेशेवरों और विपक्ष हो सकते हैं, लेकिन इसका मतलब यह नहीं है कि आप किसी पर प्रोग्रामिंग विधि पर सवाल उठा सकते हैं, आप इस पद्धति के लिए विपक्ष का सुझाव दे सकते हैं और अपनी विधि के लिए पेशेवरों का उपयोग कर सकते हैं। यह टिप्पणी वास्तव में आपत्तिजनक है, और आपको इस तरह की टिप्पणी नहीं करनी चाहिए।
दिलीप

1
मुझे खेद है कि आपने दिलीप को नाराज कर दिया, लेकिन 2 * M_PI लिखना उद्देश्यपूर्ण रूप से (360 * M_PI) / 180) से अधिक स्पष्ट है, और उत्तरार्द्ध को लिखना हाथ में विषय की समझ की कमी दर्शाता है।
ब्रेडिकलएमडी

1
@BreadicalMD को कोई चिंता नहीं है, लेकिन इसका अच्छा सुझाव है, मैंने अपना कोड अपडेट कर दिया है। Thanx।
दिलीप

9

यहाँ एक UIView एक्सटेंशन के रूप में मेरा स्विफ्ट समाधान है। इसे किसी भी UIImageView पर UIActivityIndicator व्यवहार का अनुकरण माना जा सकता है।

import UIKit

extension UIView
{

    /**
    Starts rotating the view around Z axis.

    @param duration Duration of one full 360 degrees rotation. One second is default.
    @param repeatCount How many times the spin should be done. If not provided, the view will spin forever.
    @param clockwise Direction of the rotation. Default is clockwise (true).
     */
    func startZRotation(duration duration: CFTimeInterval = 1, repeatCount: Float = Float.infinity, clockwise: Bool = true)
    {
        if self.layer.animationForKey("transform.rotation.z") != nil {
            return
        }
        let animation = CABasicAnimation(keyPath: "transform.rotation.z")
        let direction = clockwise ? 1.0 : -1.0
        animation.toValue = NSNumber(double: M_PI * 2 * direction)
        animation.duration = duration
        animation.cumulative = true
        animation.repeatCount = repeatCount
        self.layer.addAnimation(animation, forKey:"transform.rotation.z")
    }


    /// Stop rotating the view around Z axis.
    func stopZRotation()
    {
        self.layer.removeAnimationForKey("transform.rotation.z")
    }

}

9

एक स्विफ्ट 3 संस्करण:

extension UIView {

    func startRotate() {
        let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotation.fromValue = 0
        rotation.toValue = NSNumber(value: M_PI * 2)
        rotation.duration = 2
        rotation.isCumulative = true
        rotation.repeatCount = FLT_MAX
        self.layer.add(rotation, forKey: "rotationAnimation")
    }

    func stopRotate() {
        self.layer.removeAnimation(forKey: "rotationAnimation")
    }
}

और याद रखें कि startRotateअंदर viewWillAppearन जाएं viewDidLoad


3

आप UIView और ब्लॉकों का उपयोग करके एक ही प्रकार का एनीमेशन भी कर सकते हैं। यहां एक क्लास एक्सटेंशन विधि है जो किसी भी कोण से दृश्य को घुमा सकती है।

- (void)rotationWithDuration:(NSTimeInterval)duration angle:(CGFloat)angle options:(UIViewAnimationOptions)options
{
    // Repeat a quarter rotation as many times as needed to complete the full rotation
    CGFloat sign = angle > 0 ? 1 : -1;
    __block NSUInteger numberRepeats = floorf(fabsf(angle) / M_PI_2);
    CGFloat quarterDuration = duration * M_PI_2 / fabs(angle);

    CGFloat lastRotation = angle - sign * numberRepeats * M_PI_2;
    CGFloat lastDuration = duration - quarterDuration * numberRepeats;

    __block UIViewAnimationOptions startOptions = UIViewAnimationOptionBeginFromCurrentState;
    UIViewAnimationOptions endOptions = UIViewAnimationOptionBeginFromCurrentState;

    if (options & UIViewAnimationOptionCurveEaseIn || options == UIViewAnimationOptionCurveEaseInOut) {
        startOptions |= UIViewAnimationOptionCurveEaseIn;
    } else {
        startOptions |= UIViewAnimationOptionCurveLinear;
    }

    if (options & UIViewAnimationOptionCurveEaseOut || options == UIViewAnimationOptionCurveEaseInOut) {
        endOptions |= UIViewAnimationOptionCurveEaseOut;
    } else {
        endOptions |= UIViewAnimationOptionCurveLinear;
    }

    void (^lastRotationBlock)(void) = ^ {
        [UIView animateWithDuration:lastDuration 
                              delay:0 
                            options:endOptions 
                         animations:^{
                             self.transform = CGAffineTransformRotate(self.transform, lastRotation);
                         } 
                         completion:^(BOOL finished) {
                             NSLog(@"Animation completed");   
                         }
         ];
    };

    if (numberRepeats) {
        __block void (^quarterSpinningBlock)(void) = ^{ 
            [UIView animateWithDuration:quarterDuration 
                                  delay:0 
                                options:startOptions 
                             animations:^{
                                 self.transform = CGAffineTransformRotate(self.transform, M_PI_2);
                                 numberRepeats--; 
                             } 
                             completion:^(BOOL finished) {
                                 if (numberRepeats > 0) {
                                     startOptions = UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveLinear;
                                     quarterSpinningBlock();
                                 } else {
                                     lastRotationBlock();
                                 }NSLog(@"Animation completed");   
                             }
             ];

        };

        quarterSpinningBlock();
    } else {
        lastRotationBlock();
    }
}

क्या यह विधि (पूर्ण होने पर पुनरावर्ती कॉल) एक तेजी से बदलते एनीमेशन के साथ अच्छी तरह से काम करेगी? उदाहरण के लिए, अवधि लगभग होगी। 1 / 30s ताकि मैं वास्तविक समय में ऑब्जेक्ट की रोटेशन की गति को संशोधित कर सकूं, उदाहरण के लिए स्पर्श पर प्रतिक्रिया?
alecail

3

अगर किसी को नैट का समाधान चाहिए था, लेकिन स्विफ्ट में, तो यहाँ एक मोटा तेज़ अनुवाद है:

class SomeClass: UIViewController {

    var animating : Bool = false
    @IBOutlet weak var activityIndicatorImage: UIImageView!

    func startSpinning() {
        if(!animating) {
            animating = true;
            spinWithOptions(UIViewAnimationOptions.CurveEaseIn);
        }
    }

    func stopSpinning() {
        animating = false
    }

    func spinWithOptions(options: UIViewAnimationOptions) {
        UIView.animateWithDuration(0.5, delay: 0.0, options: options, animations: { () -> Void in
            let val : CGFloat = CGFloat((M_PI / Double(2.0)));
            self.activityIndicatorImage.transform = CGAffineTransformRotate(self.activityIndicatorImage.transform,val)
        }) { (finished: Bool) -> Void in

            if(finished) {
                if(self.animating){
                    self.spinWithOptions(UIViewAnimationOptions.CurveLinear)
                } else if (options != UIViewAnimationOptions.CurveEaseOut) {
                    self.spinWithOptions(UIViewAnimationOptions.CurveEaseOut)
                }
            }

        }
    }

    override func viewDidLoad() {
        startSpinning()
    }
}

3

xamarin ios के लिए:

public static void RotateAnimation (this UIView view, float duration=1, float rotations=1, float repeat=int.MaxValue)
{
    var rotationAnimation = CABasicAnimation.FromKeyPath ("transform.rotation.z");
    rotationAnimation.To = new NSNumber (Math.PI * 2.0 /* full rotation*/ * 1 * 1);
    rotationAnimation.Duration = 1;
    rotationAnimation.Cumulative = true;
    rotationAnimation.RepeatCount = int.MaxValue;
    rotationAnimation.RemovedOnCompletion = false;
    view.Layer.AddAnimation (rotationAnimation, "rotationAnimation");
}

2

यह है कि मैं सही दिशा में 360 को घुमाता हूं।

[UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionRepeat|UIViewAnimationOptionCurveLinear
                     animations:^{
                         [imageIndView setTransform:CGAffineTransformRotate([imageIndView transform], M_PI-0.00001f)];
                     } completion:nil];

2

एनीमेशन बनाएं

- (CABasicAnimation *)spinAnimationWithDuration:(CGFloat)duration clockwise:(BOOL)clockwise repeat:(BOOL)repeats
{
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    anim.toValue = clockwise ? @(M_PI * 2.0) : @(M_PI * -2.0);
    anim.duration = duration;
    anim.cumulative = YES;
    anim.repeatCount = repeats ? CGFLOAT_MAX : 0;
    return anim;
}

इसे इस तरह एक दृश्य में जोड़ें

CABasicAnimation *animation = [self spinAnimationWithDuration:1.0 clockwise:YES repeat:YES];
[self.spinningView.layer addAnimation:animation forKey:@"rotationAnimation"];

यह उत्तर अलग कैसे है? यदि आपके अधिकांश कार्य केवल कुछ वस्तुओं को यहाँ और वहाँ हेरफेर करने के बजाय ऑब्जेक्ट लौटाते हैं तो आपके पास क्लीनर कोड होगा।


2

UIView के साथ 360 डिग्री एनीमेशन करने के लिए विभिन्न तरीके निम्नलिखित हैं।

CABasicAnimation का उपयोग करना

var rotationAnimation = CABasicAnimation()
rotationAnimation = CABasicAnimation.init(keyPath: "transform.rotation.z")
rotationAnimation.toValue = NSNumber(value: (Double.pi))
rotationAnimation.duration = 1.0
rotationAnimation.isCumulative = true
rotationAnimation.repeatCount = 100.0
view.layer.add(rotationAnimation, forKey: "rotationAnimation")


यहाँ UIView के लिए एक विस्तार कार्य है जो रोटेशन संचालन शुरू और बंद करता है:

extension UIView {

    // Start rotation
    func startRotation() {
        let rotation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotation.fromValue = 0
        rotation.toValue = NSNumber(value: Double.pi)
        rotation.duration = 1.0
        rotation.isCumulative = true
        rotation.repeatCount = FLT_MAX
        self.layer.add(rotation, forKey: "rotationAnimation")
    }

    // Stop rotation
    func stopRotation() {
        self.layer.removeAnimation(forKey: "rotationAnimation")
    }
}


अब का उपयोग कर, UIView.animation बंद:

UIView.animate(withDuration: 0.5, animations: { 
      view.transform = CGAffineTransform(rotationAngle: (CGFloat(Double.pi)) 
}) { (isAnimationComplete) in
    // Animation completed 
}

2

@ राम का जवाब वाकई मददगार था। यहाँ उत्तर का एक स्विफ्ट संस्करण है।

स्विफ्ट 2

private func rotateImageView() {

    UIView.animateWithDuration(1, delay: 0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in
        self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, CGFloat(M_PI_2))
        }) { (finished) -> Void in
            if finished {
                self.rotateImageView()
            }
    }
}

स्विफ्ट 3,4,5

private func rotateImageView() {

    UIView.animate(withDuration: 1, delay: 0, options: UIView.AnimationOptions.curveLinear, animations: { () -> Void in
        self.imageView.transform = self.imageView.transform.rotated(by: .pi / 2)
    }) { (finished) -> Void in
        if finished {
            self.rotateImageView()
        }
    }
}

मैं रोटेशन को कैसे रोक सकता हूं?
user2526811

1
आपने झंडा कैसे लगाया? तो, शायद आपके पास एनीमेशन को रोकने के लिए एक var stop = false private func stopRotation() { stop = true }if finished {...}if finished { if stop { return} self.rotateImageView() }
कवक है

धन्यवाद, मैंने ठीक वैसा ही किया। आपके प्रतिक्रिया के लिए धन्येवाद।
user2526811

1

मैंने एक चमकदार एनीमेशन फ्रेमवर्क विकसित किया है जो आपको समय की बचत कर सकता है! इसका उपयोग करके इस एनीमेशन को बहुत आसानी से बनाया जा सकता है:

private var endlessRotater: EndlessAnimator!
override func viewDidAppear(animated: Bool) 
{
    super.viewDidAppear(animated)
    let rotationAnimation = AdditiveRotateAnimator(M_PI).to(targetView).duration(2.0).baseAnimation(.CurveLinear)
    endlessRotater = EndlessAnimator(rotationAnimation)
    endlessRotater.animate()
}

बस इस एनीमेशन को रोकने के nilलिए endlessRotater

यदि आप रुचि रखते हैं, तो कृपया देखें: https://github.com/hip4yes/Animatics



1

स्विफ्ट 4.0

func rotateImageView()
{
    UIView.animate(withDuration: 0.3, delay: 0, options: .curveLinear, animations: {() -> Void in
        self.imageView.transform = self.imageView.transform.rotated(by: .pi / 2)
    }, completion: {(_ finished: Bool) -> Void in
        if finished {
            rotateImageView()
        }
    })
}

1

Keyframe एनिमेशन का उपयोग कर 5 UIView एक्सटेंशन स्विफ्ट

यह दृष्टिकोण हमें सीधे UIView.AnimationOptions.repeat का उपयोग करने की अनुमति देता है

public extension UIView {

    func animateRotation(duration: TimeInterval, repeat: Bool, completion: ((Bool) -> ())?) {

        var options = UIView.KeyframeAnimationOptions(rawValue: UIView.AnimationOptions.curveLinear.rawValue)

        if `repeat` {
            options.insert(.repeat)
        }

        UIView.animateKeyframes(withDuration: duration, delay: 0, options: options, animations: {

            UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.25, animations: {
                self.transform = CGAffineTransform(rotationAngle: CGFloat.pi/2)
            })

            UIView.addKeyframe(withRelativeStartTime: 0.25, relativeDuration: 0.25, animations: {
                self.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
            })

            UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.25, animations: {
                self.transform = CGAffineTransform(rotationAngle: 3*CGFloat.pi/2)
            })

            UIView.addKeyframe(withRelativeStartTime: 0.75, relativeDuration: 0.25, animations: {
                self.transform = CGAffineTransform(rotationAngle: 2*CGFloat.pi)
            })

        }, completion: completion)

    }

}

2
मुझे आपका साथ पसंद है, बहुत साफ-सुथरा
निकोलस मंज़िनी

0

स्विफ्ट:

func runSpinAnimationOnView(view:UIView , duration:Float, rotations:Double, repeatt:Float ) ->()
    {
        let rotationAnimation=CABasicAnimation();

        rotationAnimation.keyPath="transform.rotation.z"

        let toValue = M_PI * 2.0 * rotations ;


        // passing it a float
        let someInterval = CFTimeInterval(duration)

        rotationAnimation.toValue=toValue;
        rotationAnimation.duration=someInterval;
        rotationAnimation.cumulative=true;
        rotationAnimation.repeatCount=repeatt;
        view.layer.addAnimation(rotationAnimation, forKey: "rotationAnimation")


    }

0

स्विफ्ट 3:

 var rotationAnimation = CABasicAnimation()
     rotationAnimation = CABasicAnimation.init(keyPath: "transform.rotation.z")
     rotationAnimation.toValue = NSNumber(value: (M_PI * 2.0))
     rotationAnimation.duration = 2.0
     rotationAnimation.isCumulative = true
     rotationAnimation.repeatCount = 10.0
     view.layer.add(rotationAnimation, forKey: "rotationAnimation")


-1

मुझे लगता है कि आपको बेहतर तरीके से UIVIewश्रेणी जोड़ना चाहिए :

#import <QuartzCore/QuartzCore.h>
#import "UIView+Rotate.h"

कार्यान्वयन उविवि (घुमाएँ)

  • (void)remrotate360WithDuration:(CGFloat)duration repeatCount: (float)repeatCount
    {
        CABasicAnimation *fullRotation;
        fullRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
        fullRotation.fromValue = [NSNumber numberWithFloat:0];
        fullRotation.toValue = [NSNumber numberWithFloat:(2*M_PI)];
        // fullRotation.toValue = [NSNumber numberWithFloat:-(2*M_PI)]; // added this minus sign as i want to rotate it to anticlockwise
        fullRotation.duration = duration;
        fullRotation.speed = 2.0f; // Changed rotation speed
        if (repeatCount == 0)
            fullRotation.repeatCount = MAXFLOAT;
        else
            fullRotation.repeatCount = repeatCount;
    
        [self.layer addAnimation:fullRotation forKey:@"360"];
    }

इस तरीके का उपयोग नहीं :)

  • (void)remstopAllAnimations
    {
        [self.layer removeAllAnimations];
    };
  • (void)rempauseAnimations
    {
        [self rempauseLayer:self.layer];
    }
  • (void)remresumeAnimations
    {
        [self remresumeLayer:self.layer];
    }
  • (void)rempauseLayer:(CALayer *)layer
    {
        CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
        layer.speed = 0.0;
        layer.timeOffset = pausedTime;
    }
  • (void)remresumeLayer:(CALayer *)layer
    {
        CFTimeInterval pausedTime = [layer timeOffset];
        layer.speed = 1.0;
        layer.timeOffset = 0.0;
        layer.beginTime = 0.0;
        CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
        layer.beginTime = timeSincePause;
    }

बहुत बढ़िया। मैं सिर्फ UIImageView श्रेणी पर टिप्पणी करना चाहता हूं। आप सब का धन्यवाद।
Zgpeace
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.