Slaknation
Slaknation

Reputation: 1926

Animate a rotated label in swift?

I am trying to animate a rotated label like this:

@IBOutlet fileprivate weak var loadingLabel: UILabel!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        loadingLabel.transform = CGAffineTransform(rotationAngle: CGFloat(0.2))  // rotation line

        UIView.animate(withDuration: 2.0, animations: {
            self.loadingLabel.transform = CGAffineTransform(translationX: 0, y: self.view.bounds.size.height)
        })
    }

When I comment out the rotation line of code (and keep the label unrotated), it works fine. But when I rotate it, the label starts off the screen at the beginning of the animation: enter image description here

When I comment out the animation, the label is rotated perfectly fine (but no animation obviously): enter image description here

How do I rotate the image and animate it, without having this weird placement?

Edit: To clarify: I want the label to start off rotated in the center of the screen, and just simply move the label. I do not want to rotate the image during the animation.

Upvotes: 0

Views: 937

Answers (3)

simvi
simvi

Reputation: 1

The first transform is ot of the animation block, it's why it begin out of the screen. You should move it in the animation block, and use a completion handler to animate again.

UIView.animate(withDuration: 2.0, animations: {
    //
}, completion: { (result) in
    //
})
  • Be carefull, the angle is in radians.

Upvotes: 0

Josh Homann
Josh Homann

Reputation: 16327

The correct answer is that you are supposed to concatenate the transformation matrices. If you don't want to do linear algebra then the easy way is that you use the transform to set the rotation and don't animate it, then animate the view's frame/center instead.

import UIKit

class V: UIViewController {
    @IBOutlet var label: UILabel!
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        label.transform = CGAffineTransform(rotationAngle: CGFloat.pi / 6)
        label.center.x += 300
        UIView.animate(withDuration: 2) {
            self.label.center.x -= 300
        }
    }
}

Upvotes: 1

Muhammad Waqas Bhati
Muhammad Waqas Bhati

Reputation: 2805

You can perform the animation with CABasicAnimation as it will give you more control on the animation and it has a completion block on which you can hide your label as well upon your requirement.

    loadingLabel.transform = CGAffineTransform(rotationAngle: CGFloat(0.2))  // rotation line

        let animationKey = "position.y"
        CATransaction.begin()
        let moveYAnimation = CABasicAnimation( keyPath:  animationKey)
        moveYAnimation.fromValue = loadingLabel.frame.origin.y
        moveYAnimation.toValue = self.view.bounds.size.height
        moveYAnimation.duration = 2
        loadingLabel.layer.add( moveYAnimation, forKey: animationKey )

        // Callback function
        CATransaction.setCompletionBlock {
            print("end animation")
            self.loadingLabel.isHidden = true
        }

        // Do the actual animation and commit the transaction
        loadingLabel.layer.add(moveYAnimation, forKey: animationKey)
        CATransaction.commit()

Hope it will help you.

Upvotes: 1

Related Questions