skip to Main Content

I’m trying to get my UIView to rotate about the z-axis in Swift. But for some reason, the rotation axis is not as expected:

enter image description here

    rotatedView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    rotatedView.contentMode = .scaleToFill
    rotatedView.layer.transform = CATransform3DMakeRotation(rotatedObjectWrapper.object.rotation, 0, 0, 1)

How do I get the UIView to rotate about the z-axis? Thanks.

UPDATE:
I investigated and realised that the rotation is around the z-axis when I use a Stepper element to control the rotation. For context, the delegate function delegate?.didRotateObject update rotatedObjectWrapper.object.rotation value.

Slider:

@IBAction func didChangeRotation(_ sender: UISlider) {
    delegate?.didRotateObject(to: Double(angleSlider.value))
}

Stepper (which updates by 0.1 radians):

 @IBAction func didChangeStepper(_ sender: Any) {
    delegate?.didRotateObject(to: Double(stepper.value))
}

I tried using some animation to change the rotation value, and it sort of rotates around the z-axis, while still having the weird rotation behaviour:

    UIView.animate(withDuration: 0.5, animations: {
      rotatedView.layer.transform = CATransform3DMakeRotation(rotatedObjectWrapper.object.rotation, 0, 0, 1)
    })

Outcome:

enter image description here

UPDATE 2:
I’m trying this out:

        testView = CustomObjectView(image: UIImage(named: "black"))    
        guard let testView = testView else { return }
        testView.frame = CGRect(x: rotatedObject.position.x, y: rotatedObject.position.y, width: rotatedObject.width, height: rotatedObject.height)
        testView.layer.transform = CATransform3DMakeRotation(rotatedObjectWrapper.object.rotation, 0, 0, 1)
        rotatedView.layer.transform = CATransform3DMakeRotation(rotatedObjectWrapper.object.rotation, 0, 0, 1)
        print(testView.layer.frame)
        print(rotatedView.layer.frame)
        rotatedView.layer.frame = testView.layer.frame
        print(rotatedView.layer.frame)
        print(")))))))")

testView is still rotating correctly, whereas rotatedView is still rotating weirdly. The only difference between the two is that rotatedView is obtained from a dictionary as such:

guard let rotatedView = objectsToViews[rotatedObjectWrapper] else { return }

I’m trying a hackish way to set the rotatedView.layer.frame to be equal to testView.layer.frame but it’s not working.

2

Answers


  1. import UIKit
    
    class ViewController: UIViewController {
        let rotatedView = UIView(frame: CGRect(x: 50, y: 50, width: 50, height: 50))
        
        var angle = 0.0
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            rotatedView.backgroundColor = .red
            view.addSubview(rotatedView)
            rotatedView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
               rotatedView.contentMode = .scaleToFill
    
            _ = Timer.scheduledTimer(timeInterval: 1/60, target: self, selector: #selector(updateFrame), userInfo: nil, repeats: true)
            
           
        }
    
    
        @objc func updateFrame(_ timer: Timer)
        {
            angle += 0.1
               rotatedView.layer.transform = CATransform3DMakeRotation(angle, 1, 0, 0)
        }
    }
    
    Login or Signup to reply.
  2. This code rotates a view about the z-axis based on the value of a slider, you can run it in a playground:

    import UIKit
    import PlaygroundSupport
    
    class MyViewController : UIViewController {
        
        var viewToRotate: UIView!
        override func loadView() {
            let view = UIView()
            view.backgroundColor = .white
    
            let label = UILabel()
            label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
            label.text = "Hello World!"
            label.sizeToFit()
            label.textColor = .black
            viewToRotate = label
            
            let slider = UISlider(frame: CGRect(x: 50, y: 300, width: 300, height: 40))
            slider.minimumValue = 0
            slider.maximumValue = .pi * 2
            slider.addTarget(self, action: #selector(updateRotation(_:)), for: .valueChanged)
            
            view.addSubview(label)
            view.addSubview(slider)
            self.view = view
        }
        
        @objc private func updateRotation(_ sender: UISlider) {
            viewToRotate?.layer.transform = CATransform3DMakeRotation(CGFloat(sender.value), 0, 0, 1)
        }
        
        
    }
    // Present the view controller in the Live View window
    PlaygroundPage.current.liveView = MyViewController()
    

    enter image description here

    It’s not clear why your code isn’t working, since the transform is being set the same way, but it must be in some code that isn’t in your question. What are the values you are passing in for rotation? Are there any sublayer transforms?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search