CGAffineTransform

SteadySlower·2022년 1월 25일
0

iOS Development

목록 보기
2/38
post-custom-banner

두 번째 주제는 아핀 변환입니다. 개인적으로 생소한 용어였고 정의 자체를 이해하는데 상당한 시간이 걸렸는데요. 수학적인 내용은 잘 설명해드릴 수는 없지만 코드로 어떻게 사용하는지 결과가 어떻게 나타나는지 간략하게 정리해봤습니다.

AffineTransform (아핀 변환이란?)

= translation (평행 이동) + scaling (크기 변환) + skew (기울이기) + rotating (회전)

아핀 변환은 점, 직선, 평면을 보존하는 선형 매핑 방법입니다. 아핀 변환 후에도 평행한 두 선은 그대로 평행 상태를 유지한다는 특징이 있습니다. (더 이상은 묻지 마세요😅 )

⭐️ View 자체의 속성이기 때문에 layout constraints와는 관련이 없습니다.

실습 준비

아핀 변환을 적용할 2개의 사각형을 준비하겠습니다.

그리고 아핀 변환의 적용하는 버튼과 해제하는 애니메이션을 실행할 버튼도 하나 준비합니다.

import UIKit

class VC2: UIViewController {
    
    // MARK: Properties
    
    let redSquare: UIView = {
        let view = UIView()
        view.widthAnchor.constraint(equalToConstant: 100).isActive = true
        view.heightAnchor.constraint(equalToConstant: 100).isActive = true
        view.backgroundColor = .red
        return view
    }()
    
    let blueSquare: UIView = {
        let view = UIView()
        view.widthAnchor.constraint(equalToConstant: 100).isActive = true
        view.heightAnchor.constraint(equalToConstant: 100).isActive = true
        view.backgroundColor = .blue
        return view
    }()
    
    let activatingButton: UIButton = {
        let button = UIButton()
        button.setTitle("Apply AffineTransform", for: .normal)
        button.setTitleColor(.black, for: .normal)
        button.addTarget(self, action: #selector(activateAffineTransform), for: .touchUpInside)
        return button
    }()
    
    let deactivatingButton: UIButton = {
        let button = UIButton()
        button.setTitle("Remove AffineTransform", for: .normal)
        button.setTitleColor(.black, for: .normal)
        button.addTarget(self, action: #selector(deactivateAffineTransform), for: .touchUpInside)
        return button
    }()
    

    // MARK: LifeCycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        configureUI()
    }
    
    // MARK: Selector
    
    @objc func activateAffineTransform() {
   //✅ 아핀 변환 적용 애니메이션
    }
    
    @objc func deactivateAffineTransform() {
    //✅ 아핀 변환 적용 애니메이션
    }
    
    // MARK: Helpers
    
    func configureUI() {
        view.addSubview(redSquare)
        redSquare.translatesAutoresizingMaskIntoConstraints = false
        redSquare.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        redSquare.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
        
        view.addSubview(blueSquare)
        blueSquare.translatesAutoresizingMaskIntoConstraints = false
        blueSquare.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        blueSquare.topAnchor.constraint(equalTo: redSquare.bottomAnchor, constant: 100).isActive = true
        
        view.addSubview(activatingButton)
        activatingButton.translatesAutoresizingMaskIntoConstraints = false
        activatingButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        activatingButton.topAnchor.constraint(equalTo: blueSquare.bottomAnchor, constant: 100).isActive = true
        
        view.addSubview(deactivatingButton)
        deactivatingButton.translatesAutoresizingMaskIntoConstraints = false
        deactivatingButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        deactivatingButton.topAnchor.constraint(equalTo: activatingButton.bottomAnchor, constant: 20).isActive = true
    }
}

아핀 변환

적용하기

아핀 변환은 UIView 객체의 transform 속성에 적용하면 됩니다. 할당하는 동시에 바로 해당 아핀 변환이 적용이 됩니다.

아래 아핀 변환은 평행 이동, 확대, 회전 3가지를 적용해보았습니다. 추가적인 API는 공식 문서를 참고해주세요.

@objc func activateAffineTransform() {
    UIView.animate(withDuration: 2) {
        self.redSquare.transform = CGAffineTransform(translationX: 0, y: 50)
            .scaledBy(x: 2, y: 2)
            .rotated(by: 90)
						//👉 y축 방향으로 50만큼 평행이동, 가로세로 2배 확대, 90도 회전
        self.blueSquare.transform = CGAffineTransform(translationX: 0, y: -50)
            .scaledBy(x: 0.5, y: 0.5)
            .rotated(by: 180)
						//👉 y축 방향으로 -50만큼 평행이동, 가로세로 0.5배 확대, 180도 회전
    }
}

해제하기

UIView 객체의 transform 속성에 CGAffineTransform.identity를 적용하면 됩니다. CGAffineTransform.identity은 항등변환을 의미합니다.

@objc func deactivateAffineTransform() {
    UIView.animate(withDuration: 2) {
        self.redSquare.transform = CGAffineTransform.identity
        self.blueSquare.transform = CGAffineTransform.identity
    }
}

결과

평행이동, 확대(축소), 회전이 동시에 일어나는 것을 볼 수 있습니다.

마치며

3차원 아핀 변환도 있습니다. 나중에 공부 해보고 포스팅에서 다뤄보도록 하겠습니다!

profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.
post-custom-banner

0개의 댓글