Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rotate a UIView around it's proper center without distortion / skew

I've built my own animation engine, and I want to set the rotation of a UI view on each frame that I render (60fps)

I've made a video now showing what the problem is currently.

It's fairly close, but it's still rotating in a strange way:

https://www.youtube.com/watch?v=1ZKK4r0-6i4

I've implemented a custom CustomUIView class, that inherits from UI view. This has translation, scaling and rotation properties, so when I transform the matrix, all 3 happen in the same action.

var t = CGAffineTransform( translationX: self.translation.x, y: 
self.translation.y );
// Apply scaling
t = t.scaledBy( x: self.scaling.x, y: self.scaling.y );
// Apply rotation
t = t.rotated(by:self.rotation)
self.transform = t

and the size and the width are set like this:

view.frame.size.width = parseSize(value, axis: "width")
view.layer.bounds.size.width = parseSize(value, axis: "width")    

I'm trying to set both of these properties, but I'm not sure if this is correct.

I've set the anchor point a lot, and also tried the overall center point of the view as well.

like image 715
Chris Barry Avatar asked Aug 20 '17 16:08

Chris Barry


3 Answers

Instead of using

var t = CGAffineTransform( translationX: self.translation.x, y: 
self.translation.y );

use

var t = CGAffineTransform(rotationAngle: CGFloat(Double.pi*self.rotation/180.0))

this will rotate your view from a center without changing their position.

like image 194
KavyaKavita Avatar answered Oct 16 '22 14:10

KavyaKavita


This should help you to make it work according to your requirement:

@IBOutlet var scaleRotateImage: UIImageView!
func scaleNTransform() -> Void {

    scaleRotateImage.layer.cornerRadius = scaleRotateImage.frame.size.height/2.0
    scaleRotateImage.clipsToBounds = true

    let scaleTransform = CGAffineTransform(scaleX: 3.0, y: 3.0)  // Scale
    let rotateTransform = CGAffineTransform(rotationAngle: CGFloat.pi) // Rotation
    let hybridTransform = scaleTransform.concatenating(rotateTransform) // Both Scale + Rotation

    // Outer block of animation
    UIView.animate(withDuration: 5.0, animations: {
        self.scaleRotateImage.transform = scaleTransform
        self.view.layoutIfNeeded()
    }) { (isCompleted) in

        // Nested block of animation
        UIView.animate(withDuration: 5.0, animations: {
            self.scaleRotateImage.transform = hybridTransform
            self.view.layoutIfNeeded()
        })

    }


}


Result

enter image description here

like image 20
Krunal Avatar answered Oct 16 '22 12:10

Krunal


The problem was that I was setting the transform more than once per animation frame. This was causing a compound effect with different values. You need to organise your variables so that you only set the transform once during the property modifications.

like image 4
Chris Barry Avatar answered Oct 16 '22 14:10

Chris Barry