it-source

UIView 무한 360도 회전 애니메이션?

criticalcode 2023. 4. 26. 23:24
반응형

UIView 무한 360도 회전 애니메이션?

나는 회전을 시도하고 있습니다.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다시 시작하기 전에 도를 표시합니다.

나에게 완벽하게 맞는 방법을 찾았습니다(조금 수정했습니다): 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"];
}

Richard J. Ross 3세에게 그 아이디어를 칭찬했지만, 저는 그의 코드가 제가 필요로 하는 것이 아니라는 것을 발견했습니다.은 " " 입니다.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), 이전 스핀이 감겨지는 동안(흔들림).여기 Github에 있는 샘플 프로젝트.

Swift에서 무한 회전을 위해 다음 코드를 사용할 수 있습니다.

스위프트 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)
    }
}

위의 네이트의 답변은 애니메이션 중지 및 시작에 이상적이며 더 나은 제어를 제공합니다.나는 왜 당신의 것과 그의 것이 작동하지 않는지 궁금했습니다.저는 여기서 제 연구 결과와 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];
        }
    }];
}

나는 'CGAfineTransformMakeRotation' 대신 'CGAfineTransformRotate'를 사용했는데, 왜냐하면 전자는 애니메이션 진행 시 저장된 결과를 반환하기 때문입니다.이렇게 하면 애니메이션 중에 보기가 점프하거나 재설정되지 않습니다.

또 다른 것은 '를 사용하지 않는 것입니다.'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로 변경하면 Note-Nate의 답변에도 이 문제가 발생합니다).360도 변환은 단순히 뷰를 원래 위치에 유지하도록 요청하는 것입니다. 따라서 회전을 전혀 볼 수 없습니다.

확인된 솔루션의 Swift Extension에 대한 나의 기여:

스위프트 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")
    }
}

이미지를 무한대로 회전하기만 하면 매우 효과적이며 매우 간단합니다.

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

제 경험에 따르면, 이것은 완벽하게 작동하지만, 이미지가 오프셋 없이 중심을 중심으로 회전할 수 있는지 확인하십시오. 그렇지 않으면 이미지 애니메이션이 PI로 이동하면 "점프"할 것입니다.

스핀 방향을 변경하려면 다음 기호를 변경합니다.angle(angle *= -1).

@AlexPretzlav의 "Update Comments by @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-ii가 제안하는 것처럼 블록만으로 이 작업을 수행할 수도 있지만 블록이 자체적으로 캡처되고 있기 때문에 유지 루프 경고가 표시됩니다.

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

David Rysanek의 멋진 답변이 Swift 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")

        }   

    }
}

UIView 확장자로서 신속한 해결책이 있습니다.UIA 활동의 시뮬레이션으로 간주할 수 있습니다.UI 이미지 보기의 표시기 동작입니다.

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

}

이것은 저에게 효과가 있었습니다.

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

쿼터 턴을 사용하고 턴을 점진적으로 증가시킵니다.

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

저장소에서 좋은 코드를 찾았습니다.

여기 제가 속도에 대한 필요에 따라 작은 변경을 한 코드가 있습니다 :)

UIImageView+Rotate.

#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

Swift3 버전:

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

그리고 전화하는 것을 기억하세요.startRotateviewWillAppear에 없는viewDidLoad.

@ram의 대답은 정말 도움이 되었습니다.여기 스위프트 버전의 답이 있습니다.

스위프트 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()
        }
    }
}

또한 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();
    }
}

네이츠의 해결책을 원했지만 신속한 해결책을 원하는 사람이 있다면 대략적인 신속한 번역은 다음과 같습니다.

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

사마리니오스의 경우:

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

이렇게 360도 오른쪽 방향으로 회전합니다.

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

애니메이션 만들기

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

이 대답은 어떻게 다릅니까?만약 당신의 대부분의 기능이 단지 몇몇 객체를 여기저기서 조작하는 것이 아니라 객체를 반환한다면 당신은 훨씬 더 깨끗한 코드를 갖게 될 것입니다.

UIView를 사용하여 360도 애니메이션을 수행하는 방법은 다음과 같습니다.

CABasic 애니메이션 사용

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.애니메이션 클로저를 사용합니다.

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

키프레임 애니메이션을 이용한 Swift 5 UIView 확장

이 접근 방식을 통해 UIView를 직접 사용할 수 있습니다.애니메이션 옵션.반복

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)

    }

}

시간을 절약할 수 있는 빛나는 애니메이션 프레임워크를 개발했습니다!이를 사용하여 이 애니메이션을 매우 쉽게 만들 수 있습니다.

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 을 보세요.

스위프트 4,

func rotateImage(image: UIImageView) {
        UIView.animate(withDuration: 1, animations: {
            image.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
            image.transform = CGAffineTransform.identity
        }) { (completed) in
            self.rotateImage()
        }
    }

참조

스위프트 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()
        }
    })
}

스위프트:

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


    }

스위프트 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")
let val = CGFloat(M_PI_2)

UIView.animate(withDuration: 1, delay: 0, options: [.repeat, .curveLinear], animations: {
        self.viewToRotate.transform = self.viewToRotate.transform.rotated(by: val)
})
import UIKit

class RotatingImageView: UIImageView, CAAnimationDelegate {
    
    private let rotationAnimationKey = "rotationAnimationKey"

    private var shouldStopRotating = false
    
    func startRotating(witFullRotationDuration duration: Double = 0.5, halfRotation: Bool = true) {
        
        shouldStopRotating = false
        if layer.animation(forKey: rotationAnimationKey) == nil {
        
            let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
            rotationAnimation.fromValue = 0.0
            rotationAnimation.toValue = halfRotation ? Float.pi : Float.pi * 2
            rotationAnimation.duration = duration
            rotationAnimation.repeatCount = 1
            rotationAnimation.delegate = self
            layer.add(rotationAnimation, forKey: rotationAnimationKey)
        
        }
        
    }

    func stopRotating(immediately: Bool = false) {
        if immediately {
            if layer.animation(forKey: rotationAnimationKey) != nil {
                layer.removeAnimation(forKey: rotationAnimationKey)
            }
        } else {
            shouldStopRotating = true
        }
    }
    
    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    
        if !shouldStopRotating {
            startRotating(witFullRotationDuration: anim.duration)
        } else {
            if layer.animation(forKey: rotationAnimationKey) != nil {
                layer.removeAnimation(forKey: rotationAnimationKey)
            }
        }
        
    }
    
}

제 생각에 당신은 추가하는 것이 좋을 것 같습니다.UIVIew범주:

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

구현 UI뷰(회전)

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

언급URL : https://stackoverflow.com/questions/9844925/uiview-infinite-360-degree-rotation-animation

반응형