ios 在 Swift 中无限地旋转 360 度视图?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27755504/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:13:29  来源:igfitidea点击:

Rotate a view for 360 degrees indefinitely in Swift?

iosswift

提问by Cesare

I want to rotate an image view for 360 degrees indefinitely.

我想无限地旋转图像视图 360 度。

UIView.animate(withDuration: 2, delay: 0, options: [.repeat], animations: {
    self.view.transform = CGAffineTransform(rotationAngle: 6.28318530717959)
}, completion: nil)

How can I do it?

我该怎么做?

回答by Crashalot

Swift 2.x way to rotate UIView indefinitely, compiled from earlier answers:

Swift 2.x 无限期旋转 UIView 的方法,从早期的答案编译:

// Rotate <targetView> indefinitely
private func rotateView(targetView: UIView, duration: Double = 1.0) {
    UIView.animateWithDuration(duration, delay: 0.0, options: .CurveLinear, animations: {
        targetView.transform = CGAffineTransformRotate(targetView.transform, CGFloat(M_PI))
    }) { finished in
        self.rotateView(targetView, duration: duration)
    }
}

UPDATE Swift 3.x

更新 Swift 3.x

// Rotate <targetView> indefinitely
private func rotateView(targetView: UIView, duration: Double = 1.0) {
    UIView.animate(withDuration: duration, delay: 0.0, options: .curveLinear, animations: {
        targetView.transform = targetView.transform.rotated(by: CGFloat(M_PI))
    }) { finished in
        self.rotateView(targetView: targetView, duration: duration)
    }
}

回答by Hardik Thakkar

Swift 3.0

斯威夫特 3.0

let imgViewRing = UIImageView(image: UIImage(named: "apple"))
imgViewRing.frame = CGRect(x: 0, y: 0, width: UIImage(named: "apple")!.size.width, height: UIImage(named: "apple")!.size.height)
imgViewRing.center = CGPoint(x: self.view.frame.size.width/2.0, y: self.view.frame.size.height/2.0)
rotateAnimation(imageView: imgViewRing)
self.view.addSubview(imgViewRing)

This is the animation logic

这是动画逻辑

func rotateAnimation(imageView:UIImageView,duration: CFTimeInterval = 2.0) {
        let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
        rotateAnimation.fromValue = 0.0
        rotateAnimation.toValue = CGFloat(.pi * 2.0)
        rotateAnimation.duration = duration
        rotateAnimation.repeatCount = .greatestFiniteMagnitude

        imageView.layer.add(rotateAnimation, forKey: nil)
    }

You can check output in this link

您可以在此链接中检查输出

回答by Saqib Omer

Use this extension to rotate UIImageView 360 degrees.

使用这个扩展来旋转 UIImageView 360 度。

extension UIView {
func rotate360Degrees(duration: CFTimeInterval = 1.0, completionDelegate: AnyObject? = nil) {
    let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
    rotateAnimation.fromValue = 0.0
    rotateAnimation.toValue = CGFloat(M_PI)
    rotateAnimation.duration = duration

    if let delegate: CAAnimationDelegate = completionDelegate as! CAAnimationDelegate? {
        rotateAnimation.delegate = delegate
    }
    self.layer.addAnimation(rotateAnimation, forKey: nil)
}
}

Than to rotate UIImageView simply use this method

比旋转 UIImageView 只需使用此方法

self.YOUR_SUBVIEW.rotate360Degrees()

回答by saroj raut

This one work for me in Swift 2.2:

这个在 Swift 2.2 中对我有用:

let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotationAnimation.fromValue = 0.0
rotationAnimation.toValue = 360 * CGFloat(M_PI/180)
let innerAnimationDuration : CGFloat = 1.0
rotationAnimation.duration = Double(innerAnimationDuration)
rotationAnimation.repeatCount = HUGE
self.imageView.addAnimation(rotationAnimation, forKey: "rotateInner")

回答by nanothread59

I would stick it in a function like rotateImage()and in the completion code just call rotateImage()again. I think you should use M_PI (or the swift equivalent) for the rotation amount, though.

我会把它放在一个类似的函数中,rotateImage()并且在完成代码中rotateImage()再次调用。不过,我认为您应该使用 M_PI(或 swift 等效项)作为旋转量。

回答by Randoramma

Updated for Swift 3: I made an extension to UIView and included the following function within:

针对 Swift 3 进行了更新:我对 UIView 进行了扩展,并在其中包含了以下函数:

func rotate(fromValue: CGFloat, toValue: CGFloat, duration: CFTimeInterval = 1.0, completionDelegate: Any? = nil) {

let rotateAnimation = CABasicAnimation(keyPath: >"transform.rotation")
rotateAnimation.fromValue = fromValue
rotateAnimation.toValue = toValue
rotateAnimation.duration = duration

if let delegate: Any = completionDelegate {
rotateAnimation.delegate = delegate as? CAAnimationDelegate
}
self.layer.add(rotateAnimation, forKey: nil)

}

You can then call the function via (on a UIView I made into a button for example) :

然后,您可以通过(例如,在我制作成按钮的 UIView 上)调用该函数:

monitorButton.rotate(fromValue: 0.0, toValue: CGFloat(M_PI * 2), completionDelegate: self)

Hope this helps!

希望这可以帮助!

回答by Patel Jigar

Try this one it works for me, i am rotating image for once

试试这个对我有用,我正在旋转图像一次

 UIView.animateWithDuration(0.5, delay: 0.0, options: .CurveLinear, animations: {

       self.imgViewReload.transform = CGAffineTransformRotate(self.imgViewReload.transform, CGFloat(M_PI))

 }, completion: {
    (value: Bool) in

          UIView.animateWithDuration(0.5, delay: 0.0, options: .CurveLinear, animations: {
          self.imgViewReload.transform = CGAffineTransformIdentity

         }, completion: nil)
 })

回答by Garret Kaye

I think what you really want here is to use a CADisplayLink. Reason being that this would be indefinitely smooth versus using completion blocks which may cause slight hiccups and are not as easily cancelable. See the following solution:

我认为您在这里真正想要的是使用CADisplayLink。原因是与使用完成块相比,这将无限期地平滑,这可能会导致轻微的问题并且不容易取消。请参阅以下解决方案:

var displayLink : CADisplayLink?
var targetView = UIView()

func beginRotation () {

    // Setup display link
    self.displayLink = CADisplayLink(target: self, selector: #selector(onFrameInterval(displayLink:)))
    self.displayLink?.preferredFramesPerSecond = 60
    self.displayLink?.add(to: .current, forMode: RunLoop.Mode.default)
}

func stopRotation () {

    // Invalidate display link
    self.displayLink?.invalidate()
    self.displayLink = nil
}

// Called everytime the display is refreshed
@objc func onFrameInterval (displayLink: CADisplayLink) {

    // Get frames per second
    let framesPerSecond = Double(displayLink.preferredFramesPerSecond)

    // Based on fps, calculate how much target view should spin each interval
    let rotationsPerSecond = Double(3)
    let anglePerSecond = rotationsPerSecond * (2 * Double.pi)
    let anglePerInterval = CGFloat(anglePerSecond / framesPerSecond)

    // Rotate target view to match the current angle of the interval
    self.targetView.layer.transform = CATransform3DRotate(self.targetView.layer.transform, anglePerInterval, 0, 0, 1)

}

回答by SomaMan

Avoiding the completion closure with recursive calls!

避免使用递归调用完成闭包!

Bit late to this party, but using UIView keyFrame animation & varying stages of rotation for each keyFrame, plus setting the animation curve works nicely. Here's an UIView class function -

这个聚会有点晚了,但是使用 UIView 关键帧动画和每个关键帧的不同旋转阶段,加上设置动画曲线效果很好。这是一个 UIView 类函数 -

class func rotate360(_ view: UIView, duration: TimeInterval, repeating: Bool = true) {

    let transform1 = CGAffineTransform(rotationAngle: .pi * 0.75)
    let transform2 = CGAffineTransform(rotationAngle: .pi * 1.5)

    let animationOptions: UInt
    if repeating {
        animationOptions = UIView.AnimationOptions.curveLinear.rawValue | UIView.AnimationOptions.repeat.rawValue
    } else {
        animationOptions = UIView.AnimationOptions.curveLinear.rawValue
    }

    let keyFrameAnimationOptions = UIView.KeyframeAnimationOptions(rawValue: animationOptions)

    UIView.animateKeyframes(withDuration: duration, delay: 0, options: [keyFrameAnimationOptions, .calculationModeLinear], animations: {
        UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.375) {
            view.transform = transform1
        }
        UIView.addKeyframe(withRelativeStartTime: 0.375, relativeDuration: 0.375) {
            view.transform = transform2
        }
        UIView.addKeyframe(withRelativeStartTime: 0.75, relativeDuration: 0.25) {
            view.transform = .identity
        }
    }, completion: nil)
}

Looks pretty gnarly, with the weird rotation angles, but as the op & others have found, you can't just tell it to rotate 360

看起来很粗糙,有奇怪的旋转角度,但正如 op 和其他人发现的那样,你不能只告诉它旋转 360

回答by LuAndre

On your tabBarController, make sure to set your delegate and do the following didSelectmethod below:

在您的 tabBarController 上,确保设置您的委托并执行以下didSelect方法:

func tabBarController(_ tabBarController: UITabBarController,
                          didSelect viewController: UIViewController) {
        if let selectedItem:UITabBarItem = tabBarController.tabBar.selectedItem {
            animated(tabBar: tabBarController.tabBar, selectedItem: selectedItem)
        }
    }




fileprivate func animated(tabBar: UITabBar, selectedItem:UITabBarItem){
        if let view:UIView = selectedItem.value(forKey: "view") as? UIView {
            if let currentImageView = view.subviews.first as? UIImageView {
                rotate(imageView: currentImageView, completion: { (completed) in
                    self.restore(imageView: currentImageView, completion: nil)
                })
            }
        }
    }

    fileprivate func rotate(imageView:UIImageView, completion:((Bool) ->Void)?){
        UIView.animate(withDuration: animationSpeed, delay: 0.0, options: .curveLinear, animations: {
            imageView.transform = CGAffineTransform.init(rotationAngle: CGFloat.pi)
        }, completion: {
            (value: Bool) in
            completion?(value)
        })
    }

    fileprivate func restore(imageView:UIImageView, completion:((Bool) ->Void)?){
        UIView.animate(withDuration: animationSpeed, delay: 0.0, options: .curveLinear, animations: {
            imageView.transform = CGAffineTransform.identity
        }, completion: {
            (value: Bool) in
            completion?(value)
        })
    }