What's the correct way to rotate a UIImage 270

2019-04-17 12:18发布

UIView.animate(withDuration:2.0, animations: {

         self.imageView.transform = CGAffineTransform(rotationAngle: (270 * CGFloat(2 * Double.pi)) / 360.0)
    })

This is animating anti clockwise i want the animation clockwise.

标签: ios swift swift3
3条回答
虎瘦雄心在
2楼-- · 2019-04-17 12:53

Explanation

The problem with rotation is that it finds the shortest path to finish. So when your view is rotated by 0 degrees at the beginning, the shortest path to 270 degrees is rotate the view by -90 degrees.

You have to combine TWO animations to do this.

First: Rotate view by 180 + 1 degrees (Plus 1 tells the animation that you want to rotate clockwise - shorter path)

Second: Rotate view by 90 degrees

In code:

Let's say you have an UIView called rotateView.

@objc func rotate() {
        if rotateView.transform == .identity {
            UIView.animate(withDuration: 0.5) {
                self.rotateView.transform = CGAffineTransform(rotationAngle: (CGFloat.pi) + 1)
            }

            UIView.animate(withDuration: 0.5, delay: 0.25, options:[], animations: {
                self.rotateView.transform = CGAffineTransform(rotationAngle: (CGFloat.pi / 2))
            }, completion: nil)

        } else {
            UIView.animate(withDuration: 0.5, animations: {
                self.rotateView.transform = .identity
            })
        }
    }

The .identity checks if your rotateView is at its 'start position'.

查看更多
放我归山
3楼-- · 2019-04-17 12:55

To rotate by 270 degrees clockwise...

UIView.animate(withDuration:2.0, animations: {
            self.sampleView.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
            self.sampleView.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi * 3 / 2))
        })

Core Animation will always take the shortest route to make the rotation work. So, if your object is straight and you rotate to 90 degrees (radians: pi/2), it will rotate clockwise. If your object is straight and you rotate to 270 degrees (radians: pi + pi/2 = 3pi/2) it will rotate counter-clockwise because it's the smallest possible animation.

So we first need to rotate by pi radians (from 0 -> pi, 0 -> 180) then rotate by another pi/2 radians (pi -> 3pi/2, 180 -> 270) to perform the full rotation.

Notes :

  • To rotate by an angle greater than 180 degrees you need to perform 2 transforms, one for the first 180 degrees and then another for the rest.
  • To rotate by an angle greater than 360 degrees (like one and a half turns) you will need to perform three transforms.
  • To rotate by an odd angle, lets say 195 degrees, first rotate by 180 degrees then another 15 degrees.
  • While performing rotations you need to convert degrees to radians.
查看更多
祖国的老花朵
4楼-- · 2019-04-17 12:59

In iOS, coordinate system is flipped. So you go clockwise as your degree gains. It means that passing 270° will give you an angle, equivalent to 90° in standard coordinate system. Keep that in mind and provide needed angle accordingly.

Consider the following approach.

1) Handy extension for angle

postfix operator °

protocol IntegerInitializable: ExpressibleByIntegerLiteral {
    init (_: Int)
}

extension Int: IntegerInitializable {
    postfix public static func °(lhs: Int) -> CGFloat {
        return CGFloat(lhs) * .pi / 180
    }
}

extension CGFloat: IntegerInitializable {
    postfix public static func °(lhs: CGFloat) -> CGFloat {
        return lhs * .pi / 180
    }
}

2) Rotate to any angle with CABasicAnimation:

extension UIView {
    func rotateWithAnimation(angle: CGFloat, duration: CGFloat? = nil) {
        let pathAnimation = CABasicAnimation(keyPath: "transform.rotation")
        pathAnimation.duration = CFTimeInterval(duration ?? 2.0)
        pathAnimation.fromValue = 0
        pathAnimation.toValue = angle
        pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        self.transform = transform.rotated(by: angle)
        self.layer.add(pathAnimation, forKey: "transform.rotation")
    }
}

Usage:

override func viewDidAppear(_ animated: Bool) {
    // clockwise
    myView.rotateWithAnimation(angle: 90°)

    // counter-clockwise
    myView.rotateWithAnimation(angle: -270°) 

}

Passing negative value will rotate counter-clockwise.

查看更多
登录 后发表回答