1

I created a small UIView object, First I use translate transform move UIView to new location, after animation stop, I want UIView rotate in new location, so the code is:

    //circle2 is UIView
    UIView.animate(withDuration: 1, delay:0,options:[.curveLinear],animations:{
        self.circle2.transform=CGAffineTransform(translationX: 0, y: 35)
    },completion: {(result) in
        UIView.animate(withDuration: 1, delay:0,options:[.repeat],animations: {
            self.circle2.transform=CGAffineTransform(rotationAngle: CGFloat.pi)
            //self.circle2.transform=CGAffineTransform(rotationAngle: CGFloat.pi).translatedBy(x: 0, y: 35)
            //self.circle2.transform=CGAffineTransform(translationX: 0, y: 35).rotated(by: CGFloat.pi)
            //self.circle2.transform=CGAffineTransform(rotationAngle: CGFloat.pi).concatenating(CGAffineTransform(translationX: 0, y: 35))
        })
    })

But I found that when UIView is rotating, it also move upward to origin position. I try three another combination method, none of then works....

aluzi992
  • 29
  • 3
  • 1
    Does this answer your question? [How to apply multiple transforms in Swift](https://stackoverflow.com/questions/30929986/how-to-apply-multiple-transforms-in-swift) – El Tomato May 27 '21 at 08:44
  • self.circle2.transform=CGAffineTransform(translationX: 0, y: 35) you can use cst instead of it – Ten May 27 '21 at 09:10
  • Because CGAffineTransform Rotate will rotate the actual position of the view .you can replace self.circle2.transform=CGAffineTransform(translationX: 0, y: 35) before self.circle2.transform=self.circle2.transform.rotated(by: CGFloat.pi) to see that – Ten May 27 '21 at 09:15

1 Answers1

0

Two of your examples do work but animation may be different than what you expected. You will need to do it manually. It is painful but please try and examine the following code:

private func startAnimation()
    let startTime: Date = .init()
    let translationDuration: TimeInterval = 1.0
    var rotation: CGFloat = 0.0
    let rotationDuration: TimeInterval = 1.0
    var translation: CGPoint = .zero
    
    func refreshView(_ controller: ViewController) {
        controller.circle2.transform = CGAffineTransform(rotationAngle: rotation).concatenating(CGAffineTransform(translationX: translation.x, y: translation.y))
    }
    
    Timer.scheduledTimer(withTimeInterval: 1.0/60.0, repeats: true) { timer in
        let now: Date = .init()
        let scale: Double = (now.timeIntervalSince(startTime))/translationDuration
        
        guard scale > 0.0 else { return } // Waiting part if delay is applied
        if scale < 1.0 {
            // Animate the view
            translation = CGPoint(x: 0.0, y: 35.0*scale)
            refreshView(self)
        } else {
            // Animation ended
            timer.invalidate()
            translation = CGPoint(x: 0.0, y: 35.0)
            refreshView(self)
            
            var rotationStartTime: Date = .init()
            Timer.scheduledTimer(withTimeInterval: 1.0/60.0, repeats: true) { [weak self] timer in
                guard let self = self else { timer.invalidate(); return }
                let now: Date = .init()
                let scale: Double = (now.timeIntervalSince(rotationStartTime))/rotationDuration
                
                guard scale > 0.0 else { return } // Waiting part if delay is applied
                if scale < 1.0 {
                    // Animate the view
                    rotation = .pi * CGFloat(scale)
                    refreshView(self)
                } else {
                    // Animation ended
                    rotation = 0.0
                    rotationStartTime = .init()
                    refreshView(self)
                }
            }
        }   
    }
}

If you have a need to stop the animation then you will need some references to timers.

Matic Oblak
  • 16,318
  • 3
  • 24
  • 43