관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] Animation 테크닉 - 오토레이아웃, 단일 애니메이션, 연속 애니메이션, 스프링, 뒤집기 (autolayout, CAKeyframeAnimation, animateKeyFrames) 본문

iOS 응용 (swift)

[iOS - swift] Animation 테크닉 - 오토레이아웃, 단일 애니메이션, 연속 애니메이션, 스프링, 뒤집기 (autolayout, CAKeyframeAnimation, animateKeyFrames)

jake-kim 2022. 3. 14. 23:13

* 예제에서 UI 레이아웃을 코드로 편리하게 작성하기 위해 SnapKit 프레임워크 사용

(SnapKit 필수로 알아야 하는 것 포스팅 글 참고)

애니메이션에 사용될 뷰 준비

  • animationTargetView 선언
// ViewController.swift

import UIKit
import SnapKit

private lazy var animationTargetView: UIView = {
  let view = UIView()
  view.backgroundColor = .systemBlue
  self.view.addSubview(view)
  return view
}()

self.animationTargetView.snp.makeConstraints {
  $0.top.equalTo(self.view.safeAreaLayoutGuide).inset(16)
  $0.centerX.equalToSuperview()
  $0.size.equalTo(120)
}

Autolayout 애니메이션

아래로 이동 + 사이즈 확장

  • autolayout 애니메이션
    • autolayout을 사용하고, 이후에 UIView.animate에서 self.view.layoutIfNeeded를 사용하여 frame이 변하는 것들을 애니메이션 되게끔 설정
self.animationTargetView.snp.remakeConstraints {
  $0.bottom.equalTo(self.view.safeAreaLayoutGuide).inset(-16)
  $0.centerX.equalToSuperview()
  $0.size.equalTo(240)
}

UIView.animate(
  withDuration: 0.5,
  animations: self.view.layoutIfNeeded
)
  • 되돌릴때도 역시 remakeConstraints하여 다시 autolayout 업데이트
// autolayout 애니메이션 원상 복구
self.animationTargetView.snp.remakeConstraints {
  $0.top.equalTo(self.view.safeAreaLayoutGuide).inset(16)
  $0.centerX.equalToSuperview()
  $0.size.equalTo(120)
}

UIView.animate(
  withDuration: 0.5,
  animations: self.view.layoutIfNeeded
)

단일 애니메이션 (CAKeyframeAnimation)

반짝이는 애니메이션
shaking 애니메이션

  • CAKeyframeAnimation: position.x, position.y, opacity 등등의 단일 애니메이션에 대해서 쉽게 설정이 가능한 것
  • 반짝이는 애니메이션
let opacityKeyframe = CAKeyframeAnimation(keyPath: "opacity")
opacityKeyframe.values = [0.2, 0.5, 0.2] // opacity값이 0.2 -> 0.5 -> 0.2로 바뀜 (선명해졌다가 다시 흐려지는 애니메이션)
opacityKeyframe.keyTimes = [0, 0.5, 1]
opacityKeyframe.duration = 1
opacityKeyframe.repeatCount = .infinity
self.animationTargetView.layer.add(opacityKeyframe, forKey: "myAnimation")

// cf) 애니메이션 삭제 방법
self.animationTargetView.layer.removeAnimation(forKey: "myAnimation")
  • 쉐이킹 애니메이션
let shakingKeyframe = CAKeyframeAnimation(keyPath: "position.x")
shakingKeyframe.values = [0, 5, -5, 5, 2, 2, -2, 0]
shakingKeyframe.keyTimes = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1]
shakingKeyframe.duration = 0.4
shakingKeyframe.isAdditive = true // true이면 values가 현재 위치 기준, false이면 values가 Screen좌표 기준
self.animationTargetView.layer.add(shakingKeyframe, forKey: "shaking")

// 애니메이션 삭제 방법
self.animationTargetView.layer.removeAnimation(forKey: "shaking")

연속 애니메이션 (animateKeyframes)

크기가 변하고, alpha값까지 변하는 애니메이션

UIView.animateKeyframes(
  withDuration: 3,
  delay: 0,
  animations: {
    UIView.addKeyframe(
      withRelativeStartTime: 0 / 4,
      relativeDuration: 1 / 4,
      animations: { self.animationTargetView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5) }
    )
    
    UIView.addKeyframe(
      withRelativeStartTime: 1 / 4,
      relativeDuration: 1 / 4,
      animations: { self.animationTargetView.transform = .identity }
    )
    
    UIView.addKeyframe(
      withRelativeStartTime: 2 / 4,
      relativeDuration: 1 / 4,
      animations: { self.animationTargetView.alpha = 0 }
    )
    
    UIView.addKeyframe(
      withRelativeStartTime: 3 / 4,
      relativeDuration: 1 / 4,
      animations: { self.animationTargetView.alpha = 1 }
    )
  },
  completion: nil
)

스프링 애니메이션 (autolayout + UIView.animate)

  • autolayout으로 뷰의 위치를 변경할 때, 추가적으로 스프링 애니메이션 옵션 추가
    • UIView.animate안의 usingSpringWithDamping과 initaialSpringVelocity 인수에 값 입력하면 구현
self.animationTargetView.snp.remakeConstraints {
  $0.top.equalTo(self.view.safeAreaLayoutGuide).inset(300)
  $0.centerX.equalToSuperview()
  $0.size.equalTo(120)
}

UIView.animate(
  withDuration: 2,
  delay: 0,
  usingSpringWithDamping: 0.2,
  initialSpringVelocity: 2,
  animations: self.view.layoutIfNeeded
)

뒤집기 애니메이션 (autolayout + transition)

  • autolayout으로 위치 이동 시, 추가적으로 flip되는 애니메이션 넣는 방법
    • autolayout 설정 후, UIView.transition에서 options에 .transitionFlipFromLeft 사용
self.animationTargetView.snp.remakeConstraints {
  $0.top.equalTo(self.view.safeAreaLayoutGuide).inset(300)
  $0.centerX.equalToSuperview()
  $0.size.equalTo(120)
}

UIView.transition(
  with: self.animationTargetView,
  duration: 1,
  options: .transitionFlipFromLeft,
  animations: self.view.layoutIfNeeded,
  completion: nil
)

* 전체 코드: https://github.com/JK0369/ExAnimations

Comments