본문 바로가기

iOS

[iOS] 화면전환 애니메이션 커스텀하기 - CGAffineTransform, animateTransition [1]

오늘은 CGAffineTransform을 이용한 애니메이션과, 트랜지션 애니메이션을 공부해보겠습니다!

 

1. CGAffineTransform

CGAffineTransform은 아핀 행렬을 이용한 아핀 변환이라고 합니다. 무슨 말인가..?

Affine은 2D 객체를 이동시키는 벡터인데요,

2D, 3D 구조에서의 아핀행렬 혹은 축의 구조에 대해서 알고 계시다면 도움이 되지만,

몰라도 괜찮았습니다! 사용할 때는, 구조체의 함수를 이용해서

뷰를 이동하게 하는 형태라고 생각하시면 좋겠습니다.

구조체에는 세가지 이동 메소드가 존재합니다.

 

1. 이동(Translate)

2. 조절(Scale)

3. 회전(Rotate) 

 

또한, 위 세가지를 혼합해서 사용할수도 있습니다.

간단히 사용해 보겠습니다.

 

func makeView() {
        let view = UIView(frame: CGRect(x: 137.5, y: 200, width: 100, height: 100))
        view.backgroundColor = UIColor.lightGray
        view.layer.cornerRadius = view.frame.height / 2

        self.view.addSubview(view)
    }

뷰를 만들어주고, 

 

이제 이 뷰에 애니메이션을 맥여보겠습니다!

*delay는 녹화하느라 좀 줬는데, 사실 필요 없으실거에요! 

UIView.Animate(withDuration: 0.3) { }

매개변수를 필요한대로 써 주세요!

 

Scale

func animation(_ view: UIView) {
        UIView.animate(withDuration: 0.3, delay: 1, options: [], animations: {
            
            view.transform = CGAffineTransform(scaleX: 2.0, y: 2.0)
        }, completion: nil)
    }

 

Rotate

func animation(_ view: UIView) {
        UIView.animate(withDuration: 0.3, delay: 1, options: [], animations: {
            
            view.transform = CGAffineTransform(rotationAngle: .pi)
        }, completion: nil)
    }

 

앗 얘는 잘 녹화가 안되었네요ㅠㅠ 그런데 .pi 즉 반바퀴만큼 예쁘게 회전합니다!

이번에는 여러 애니메이션을 합쳐보겠습니다. 합치는 방법은 .concatenating을 활용하는 것입니다.

 

func animation(_ view: UIView) {

        let scaleAnimation = CGAffineTransform(scaleX: 2.0, y: 2.0)
        let rotateAnimation = CGAffineTransform(rotationAngle: .pi)
        let moveAnimation = CGAffineTransform(translationX: 0, y: -200)
        
        let concat = scaleAnimation.concatenating(rotateAnimation).concatenating(moveAnimation)
        
        UIView.animate(withDuration: 1, delay: 1, options: [], animations: {
            
            view.transform = concat
        }, completion: nil)
    }

 

꽤 예쁘게 해냈습니다.

        let moveAnimation = CGAffineTransform(translationX: 0, y: -200)

 

에서, translationX는 현재 객체의 위치를 기준으로 움직이는 것을 기억하셨으면 좋겠습니다!

따라서, 저는 원래의 위치였던 ( 137.5 , 200 ) 에서 y방향으로 - 200만큼 움직였습니다.

 

또한, 원래대로 돌아올 수도 있습니다. 바로, indentity 속성을 이용하는것인데요,

Animate의 Completion Handler에

  func animation(_ view: UIView) {
        
        let scaleAnimation = CGAffineTransform(scaleX: 2.0, y: 2.0)
        let rotateAnimation = CGAffineTransform(rotationAngle: .pi)
        let moveAnimation = CGAffineTransform(translationX: 0, y: -200)
        
        let concat = scaleAnimation.concatenating(rotateAnimation).concatenating(moveAnimation)
        
        UIView.animate(withDuration: 1, delay: 1, options: [], animations: {
            view.transform = concat
            
        }, completion: { (_) in
            UIView.animate(withDuration: 1, animations: {
                view.transform = CGAffineTransform.identity
            })
        })
    }

identity 속성을 추가해주었습니다. 

 

 

원래의 위치와 모양으로 돌아오는것을 확인할 수 있습니다!

간단하게 UIView.Animate()CGAffineTransform 을 이용하여 애니메이션을 해 보았는데,

어렵지도 않고, 예쁜 형태를 만들어 낼 수 있는것 같습니다!

 

다음 편은 오늘 배운 CGAffineTransform을 이용해서 Push, dismiss Animation을 바꾸어 보겠습니다!

틀린점 지적은 감사하게 받겠습니다. 감사합니다!

 

 

참고자료) 

https://hyerios.tistory.com/14

https://medium.com/@joncardasis/better-ios-animations-with-catransaction-72a7425673a6

https://developer.apple.com/documentation/coregraphics/cgaffinetransform

https://www.youtube.com/watch?v=fF4rbxq8VqU

https://lifetimecoding.wordpress.com/2015/12/16/%e1%84%8b%e1%85%a9%e1%84%90%e1%85%a9%e1%84%85%e1%85%a6%e1%84%8b%e1%85%b5%e1%84%8b%e1%85%a1%e1%84%8b%e1%85%ae%e1%86%ba-%e1%84%8b%e1%85%a2%e1%84%82%e1%85%b5%e1%84%86%e1%85%a6%e1%84%8b%e1%85%b5-2/