본문 바로가기

ComputerScience/ios App(Storyboard)

ios - 18 Animation with ViewProperties

728x90

1 Animation with ViewProperties

- 앞서 layout의 constraint를 활용해서 animation을 간접적으로 구현했다면 이번에는 뷰의 속성을 이용해서 구현해보자.

- 애니메이션이 적용 가능한 뷰의 속성은 크게 세가지 카테고리로 나뉜다.

*Position & Size

- bounds, frame, center

- auto layout과 상당히 겹치는 부분이 있다.

- view property를 활용해서 위치나 크기를 잡는 경우 animation이 view의 auto layout을 벗어나면 다시 layout을 잡아줄 수 있도록 해야 한다.

*Transformation

- rotation, scale, translation

 

*Appearance

- backgroundColor, alpha(투명도)

 

2 적용해보기

- 이전장에서 constraint로 구현한 animation을 view property를 활용해서 더 화려하게 대체 해보자.

    @IBOutlet weak var nameLabelCenterX: NSLayoutConstraint!
    @IBOutlet weak var bountyLabelCenterX: NSLayoutConstraint!

- 레이블의 constraint를 outlet으로 연결해주고

override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
        prepareAnimation()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        showAnimation()
    }

- load되었을 때 애니메이션을 준비, appear되었을 때 애니메이션을 보여주는 함수를 실행할 것이다.

    private func prepareAnimation() {
        nameLabel.transform = CGAffineTransform(translationX: view.bounds.width, y: 0).scaledBy(x: 3, y: 3).rotated(by: 180)
        bountyLabel.transform = CGAffineTransform(translationX: view.bounds.width, y: 0).scaledBy(x: 3, y: 3).rotated(by: 180)
        
        nameLabel.alpha = 0
        bountyLabel.alpha = 0
    }

- 이전 장에서 처럼 constant값을 변경시키는 것이 아니라 레이블의 transform 프로퍼티를 사용해 움직임을 나타낼 것이다.

- affine transform: 수치해석학에서 배우는데 도형을 변환하는 방법이라고 생각하자.

- translationX: x축 좌표를 화면 밖에서 시작하도록 한다.

- scaledBy: 도형의 크기를 변환하는 방법이다. 3배 확대된 상태로 애니메이션이 시작한다.

- rotated: 180도 회전하며 등장하도록 하자

- alpha값은 투명도를 나타낸다 0이면 화면에 보이지 않는, 완전 투명한 상태이다. 이 상태로 애니메이션이 시작될 것이다.

private func showAnimation() {
        UIView.animate(
                   withDuration: 1,
                   delay: 0,
                   usingSpringWithDamping: 0.6,
                   initialSpringVelocity: 2,
                   options: .allowUserInteraction,
                   animations: {
                       self.nameLabel.transform = CGAffineTransform.identity
                       self.nameLabel.alpha = 1
               },
                   completion: nil)

- 이제부터는 화면에 뷰가 나타나고 애니메이션이 보여지는 동작을 정의할 것이다.

- animate라는 api를 사용할 것인데 필요에 맞춰서 여러 파라미터로 값을 전달한다.

- animations에서 nameLabel의 최종 모습을 정의해 줘야한다.

- CGAffineTransform.identity는 변환하기 전 원래 nameLabel의 모습을 가리킨다.

- nameLabel의 투명도도 1로 화면에 보이도록 다시 바꾸어주자.

 UIView.animate(
            withDuration: 1,
            delay: 0.2,
            usingSpringWithDamping: 0.6,
            initialSpringVelocity: 2,
            options: .allowUserInteraction,
            animations: {
                self.bountyLabel.transform = CGAffineTransform.identity
                self.bountyLabel.alpha = 1
        },
            completion: nil)

- bountyLabel도 같은 방법으로 애니메이션을 적용해보자.

- name label과는 다르게 딜레이를 주었다.

UIView.transition(with: imgView,
                          duration: 0.3,
                          options: .transitionFlipFromLeft,
                          animations: nil, completion: nil)

- 이번에는 이미지 뷰에도 애니메이션을 적용해보자.

- 중심축을 기준으로 오른쪽에서 왼쪽으로 이미지 뷰가 0.3초 동안 회전하도록 했다.

3 전체코드

- 아래 코드를 실행시켜 더 화려해진 모션을 확인해보자.

import UIKit

class DetailViewController: UIViewController {
    
    @IBOutlet weak var imgView: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var bountyLabel: UILabel!
    @IBOutlet weak var nameLabelCenterX: NSLayoutConstraint!
    @IBOutlet weak var bountyLabelCenterX: NSLayoutConstraint!
    
    let viewModel = DetailViewModel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
        prepareAnimation()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        showAnimation()
    }
    
    private func prepareAnimation() {
        nameLabel.transform = CGAffineTransform(translationX: view.bounds.width, y: 0).scaledBy(x: 3, y: 3).rotated(by: 180)
        bountyLabel.transform = CGAffineTransform(translationX: view.bounds.width, y: 0).scaledBy(x: 3, y: 3).rotated(by: 180)
        
        nameLabel.alpha = 0
        bountyLabel.alpha = 0
    }
    
    private func showAnimation() {
        UIView.animate(
                   withDuration: 1,
                   delay: 0,
                   usingSpringWithDamping: 0.6,
                   initialSpringVelocity: 2,
                   options: .allowUserInteraction,
                   animations: {
                       self.nameLabel.transform = CGAffineTransform.identity
                       self.nameLabel.alpha = 1
               },
                   completion: nil)
               
        
        UIView.animate(
            withDuration: 1,
            delay: 0.2,
            usingSpringWithDamping: 0.6,
            initialSpringVelocity: 2,
            options: .allowUserInteraction,
            animations: {
                self.bountyLabel.transform = CGAffineTransform.identity
                self.bountyLabel.alpha = 1
        },
            completion: nil)

        
        UIView.transition(with: imgView,
                          duration: 0.3,
                          options: .transitionFlipFromLeft,
                          animations: nil, completion: nil)
        
    }
    
    func updateUI() {
        if let bountyInfo = viewModel.bountyInfo {
            imgView.image = bountyInfo.image
            nameLabel.text = bountyInfo.name
            bountyLabel.text = "\(bountyInfo.bounty)"
        }
    }
    
    @IBAction func close(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }
}
728x90
반응형

'ComputerScience > ios App(Storyboard)' 카테고리의 다른 글

ios - 17 Animation with contraints  (0) 2021.08.03
ios - 16 CollectionView  (0) 2021.08.03
ios - 15 Design Pattern  (0) 2021.08.02
ios - 14 Segue  (0) 2021.07.28
ios - 13 Custom Cell  (0) 2021.07.28