nSack
nSack

Reputation: 65

How to rotate a Button around a point or the center of a UIView in Xcode?

I don't want the button to rotate, I want it to revolve around a point, just like Earth rotates around the sun. To be noted that I barely have a great knowledge in xcode or swift. So I would suggest a simplest form of code, maybe in the form of function so that I can use it to rotate any number of buttons, around a particular point!

Upvotes: 0

Views: 1084

Answers (2)

Andreas Oetjen
Andreas Oetjen

Reputation: 10199

If you look at earth and sun, there is no rotation involved: The letter "E" (the earth) will never rotate, e.g. the "north pole" will always point to the same direction. Anti-clockwise rotation looks like this:

                 E            
         =>      |     => 
S-E              S          E-S

(letter "E" is not rotated).

To do this, your animation will have to follow a circle around the sun. Create a view controller with two buttons (sunButton and earthButton), and upon touching the sun, the rotation will start or stop:

// some helper extension
extension CGPoint {
    static func distanceBetween(point p1: CGPoint,
                                andPoint p2: CGPoint) -> CGFloat {
        return sqrt(pow((p2.x - p1.x), 2) + pow((p2.y - p1.y), 2))
    }

    static func angle(from fromPoint: CGPoint, to toPoint: CGPoint) -> CGFloat {
        let dx: CGFloat = fromPoint.x - toPoint.x
        let dy: CGFloat = fromPoint.y - toPoint.y
        let radians: CGFloat = atan2(dy, dx)
        return radians
    }

}

class ViewController: UIViewController {

    @IBOutlet weak var sunButton: UIButton!
    @IBOutlet weak var earthButton: UIButton!

    var isRevolving = false

    @IBAction func sunPressed(_ sender: Any) {
        if (!isRevolving) {
            startRevolving()
        } else {
            stopRevolving()
        }
    }

    func startRevolving() {
        isRevolving = true
        let sunCenter = sunButton.center
        let earthCenter = earthButton.center

        let distance = CGPoint.distanceBetween(point: sunCenter, andPoint: earthCenter)
        var angle = CGPoint.angle(from: sunCenter, to: earthCenter)
        angle = .pi + angle

        let circlePath = UIBezierPath(arcCenter: sunCenter, radius: distance, startAngle: angle + .pi*2, endAngle: angle, clockwise: false)
        // for clockwise rotation, use:
        //let circlePath = UIBezierPath(arcCenter: sunCenter, radius: distance, startAngle: angle, endAngle: angle + .pi*2, clockwise: true)

        let animation = CAKeyframeAnimation(keyPath: #keyPath(CALayer.position))
        animation.duration = 5
        animation.repeatCount = MAXFLOAT
        animation.path = circlePath.cgPath

        earthButton.layer.add(animation, forKey: nil)
    }

    func stopRevolving() {
        isRevolving = false
        if let currentPosition = earthButton.layer.presentation()?.position {
            earthButton.center = currentPosition
        }
        earthButton.layer.removeAllAnimations()
    }

}

Upvotes: 0

Agile Infoways
Agile Infoways

Reputation: 41

You can make an extension of a button as below to rotate any instance of button.

extension UIButton {

    func rotate(angle: CGFloat) {
        let radians = angle / 180.0 * CGFloat(Double.pi)
        self.transform = self.transform.rotated(by: radians);
    }
}

// Call to rotate button as below from wherever you require in your code
let myButton = UIButton()
myButton.rotate(angle: 180)

Hope this helps!

Upvotes: 1

Related Questions