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)
}
}
'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 |