14

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.

Chris Barry
  • 4,564
  • 7
  • 54
  • 89
  • I think this is pretty much exactly my problem, but I'm too tired to get it to work now. I am constantly moving and rotating these views - https://stackoverflow.com/questions/5973562/uiview-rotation-movement – Chris Barry Aug 21 '17 at 23:37
  • This seems to perfectly hint at the problem, but none of the answers help. I'm not using interface builder at all, this is a 100% programatic project - https://stackoverflow.com/questions/22173350/why-does-a-view-changes-position-when-rotating-it-using-cgaffinetransformmakerot – Chris Barry Sep 06 '17 at 23:03

3 Answers3

4

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.

KavyaKavita
  • 1,581
  • 9
  • 16
  • The thing is, I want to change the position and rotation at the same time. This changed this rotation, but now it is doing a huge loop around the top left of the parent view. – Chris Barry Sep 07 '17 at 13:13
  • I understand that chaging the ordering of the rotate or the translate makes a different result, but neither gets me to what I want. If I just rotate, it works perfectly. But if I translate it moves as described. If i move the UIView by chaging it's frames origin or center, it seems to move very badly (skews etc..) – Chris Barry Sep 07 '17 at 14:01
4

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.

Chris Barry
  • 4,564
  • 7
  • 54
  • 89
  • @Krunal ah, sorry :( but your answer didn't help me get to the solution. There is so much going on in my codebase, it was more of an architectual problem with my code flow, than anything anyone could have helped with (and ended up being quite a simple thing) – Chris Barry Sep 12 '17 at 07:37
  • The problem was I was doing this whole process twice, there isn't really any working code to show? – Chris Barry Sep 12 '17 at 08:13
3

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

Krunal
  • 77,632
  • 48
  • 245
  • 261
  • I don't want to use the inbuilt animation system. Also, I want to to translate and rotate (i can include scale as well, but it's not essential) – Chris Barry Sep 07 '17 at 13:16