관리 메뉴

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

[iOS - swift] CAKeyframeAnimation 애니메이션, 키프레임, 쉐이킹 애니메이션 본문

iOS 응용 (swift)

[iOS - swift] CAKeyframeAnimation 애니메이션, 키프레임, 쉐이킹 애니메이션

jake-kim 2022. 1. 12. 00:23

CAKeyframeAnimation

  • keyPath 프로퍼티를 사용하여 애니메이션 결정
  • key frame 애니메이션은 여러 값을 설정하고 지정한 시간 동안 값 사이에 애니메이션을 제공할 수 있는 기능

https://aroundck.tistory.com/4761

 

CAKeyframeAnimation 사용 방법

  • keyPath에 값 대입 (어떤 애니메이션인지)
  • values 배열 값에 해당 keyPath에서 사용하려는 값 기입
  • keyTimes: 0~1에 해당하는 값을 위 values.count 개수만큼 지정
  • duration: 전체 지속 시간
  • isAdditive: 현재 위치를 기준으로 애니메이션을 사용할 것인지
@objc private func didTapAnimationButton() {
  let animation = CAKeyframeAnimation()
  animation.keyPath = "position.y"
  animation.values = [0, 500, 0]
  animation.keyTimes = [0, 0.5, 1]
  animation.duration = 2 // 10초동안 지속
  animation.isAdditive = true // 현재 위치를 기준으로 할것인지
  
  self.sampleView.layer.add(animation, forKey: "move") // forKey값은 임의의 문자열 값
}

  • 위에서 isAdditive = false로 한 경우 (결과 아래)
    • 현재위치가 아닌, values에 정의된 절대위치에서 시작

  • Shake 애니메이션 구현
@objc private func didTapShakeAnimationButton() {
  let animation = CAKeyframeAnimation()
  animation.keyPath = "position.x"
  animation.values = [0, 10, -10, 10, -5, 5, -5, 0 ]
  animation.keyTimes = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1]
  animation.duration = 0.4
  animation.isAdditive = true
  
  self.sampleView.layer.add(animation, forKey: "shake") // forKey값은 임의의 문자열 값
}

    • 주로 add(_:forKey:) 부분의 forKey는 key값을 문자열로 저장하고 애니메이션을 삭제시킬 때 사용
      • 삭제되지 않는 옵션을 킨 후, animation.isRemovedOnCompletion = false
      • prepareForReuse()와 같은 cell 업데이트할때 "myCell.layer.add(alpha, forKey: "move")" 코드로 삭제
@objc private func didTapAnimationButton() {
    let animation = CAKeyframeAnimation()
    animation.keyPath = "position.y"
    animation.values = [0, 500, 0]
    animation.keyTimes = [0, 0.5, 1]
    animation.duration = 2
    animation.isAdditive = true
    animation.isRemovedOnCompletion = false // 애니메이션이 종료할 때 해당 애니메이션을 삭제시킬지 여부 (default: true)
    
    self.sampleView.layer.add(animation, forKey: "move")
  }
  • 애니메이션의 카운트도 조정 가능: repeatCount 프로퍼티 사용
animation.repeatCount = .infinity // 무한 반복
  • 애니메이션 KeyPath 종류

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/Key-ValueCodingExtensions/Key-ValueCodingExtensions.html#//apple_ref/doc/uid/TP40004514-CH12-SW8

  • 위 key path뿐만이 아니라, opacity도 가능
@objc private func didTapAlphaAnimationButton() {
  let animation = CAKeyframeAnimation()
  animation.keyPath = "opacity"
  animation.values = [0.2, 0.4, 1]
  animation.keyTimes = [0, 0.7, 1]
  animation.duration = 1
  
  self.sampleView.layer.add(animation, forKey: "alpha")
}

* 전체 코드


import UIKit

class ViewController: UIViewController {
  private let sampleView: UIView = {
    let view = UIView()
    view.backgroundColor = .systemBlue
    return view
  }()
  
  private let animationButton: UIButton = {
    let button = UIButton()
    button.setTitleColor(.systemBlue, for: .normal)
    button.setTitleColor(.blue, for: .highlighted)
    button.setTitle("애니메이션", for: .normal)
    button.addTarget(self, action: #selector(didTapAnimationButton), for: .touchUpInside)
    return button
  }()
  
  private let shakeAnimationButton: UIButton = {
    let button = UIButton()
    button.setTitleColor(.systemBlue, for: .normal)
    button.setTitleColor(.blue, for: .highlighted)
    button.setTitle("애니메이션(쉐이크)", for: .normal)
    button.addTarget(self, action: #selector(didTapShakeAnimationButton), for: .touchUpInside)
    return button
  }()
  
  private let alphaAnimationButton: UIButton = {
    let button = UIButton()
    button.setTitleColor(.systemBlue, for: .normal)
    button.setTitleColor(.blue, for: .highlighted)
    button.setTitle("애니메이션(알파)", for: .normal)
    button.addTarget(self, action: #selector(didTapAlphaAnimationButton), for: .touchUpInside)
    return button
  }()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    self.view.addSubview(self.sampleView)
    self.sampleView.translatesAutoresizingMaskIntoConstraints = false
    self.sampleView.heightAnchor.constraint(equalToConstant: 120).isActive = true
    self.sampleView.widthAnchor.constraint(equalToConstant: 200).isActive = true
    self.sampleView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
    self.sampleView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    
    self.view.addSubview(self.animationButton)
    self.animationButton.translatesAutoresizingMaskIntoConstraints = false
    self.animationButton.topAnchor.constraint(equalTo: self.sampleView.bottomAnchor, constant: 16).isActive = true
    self.animationButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
    
    self.view.addSubview(self.shakeAnimationButton)
    self.shakeAnimationButton.translatesAutoresizingMaskIntoConstraints = false
    self.shakeAnimationButton.topAnchor.constraint(equalTo: self.animationButton.bottomAnchor, constant: 16).isActive = true
    self.shakeAnimationButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
    
    self.view.addSubview(self.alphaAnimationButton)
    self.alphaAnimationButton.translatesAutoresizingMaskIntoConstraints = false
    self.alphaAnimationButton.topAnchor.constraint(equalTo: self.shakeAnimationButton.bottomAnchor, constant: 16).isActive = true
    self.alphaAnimationButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
  }
  
    @objc private func didTapAnimationButton() {
      let animation = CAKeyframeAnimation()
      animation.keyPath = "position.y"
      animation.values = [0, 500, 0]
      animation.keyTimes = [0, 0.5, 1]
      animation.duration = 2
      animation.isAdditive = true
//      animation.isRemovedOnCompletion = false // 애니메이션이 종료할 때 해당 애니메이션을 삭제시킬지 여부 (default: true)
//      animation.repeatCount = .infinity // 무한 반복
      
      self.sampleView.layer.add(animation, forKey: "move")
    }
  
  @objc private func didTapShakeAnimationButton() {
    let animation = CAKeyframeAnimation()
    animation.keyPath = "position.x"
    animation.values = [0.2, 0.4, 1]
    animation.keyTimes = [0, 0.7, 1]
    animation.duration = 3
    animation.isAdditive = true
    
    self.sampleView.layer.add(animation, forKey: "shake")
  }
  
  @objc private func didTapAlphaAnimationButton() {
    let animation = CAKeyframeAnimation()
    animation.keyPath = "opacity"
    animation.values = [0.2, 0.4, 1]
    animation.keyTimes = [0, 0.7, 1]
    animation.duration = 1
//    animation.repeatCount = .infinity
    
    self.sampleView.layer.add(animation, forKey: "alpha")
  }
}

 

* 참고

- 애니메이션 keyPath 종류: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/Key-ValueCodingExtensions/Key-ValueCodingExtensions.html#//apple_ref/doc/uid/TP40004514-CH12-SW8

- https://www.hackingwithswift.com/example-code/calayer/how-to-create-keyframe-animations-using-cakeyframeanimation

- https://aroundck.tistory.com/4761

Comments