이 문서에서는 iOS에서 CA Animations를 사용하여 부드러운 애니메이션을 만드는 방법에 중점을 둡니다.
iOS 작업을 처음 하는 동안 디자이너가 작업 중인 앱에서 나에게 다가와 애니메이션을 요청할 때마다 매우 긴장했습니다.
예전에는 애니메이션을 위한 디자인을 구상하는 것이 쉽다고 생각했지만, 반면에 그것을 구현하는 것은 매우 어려운 작업이었습니다.
구현을 위해 Google, StackOverflow 및 동료들로부터 도움을 받을 것입니다.
그 과정에서 애니메이션 공포증이 생겨 항상 피하려고 노력했습니다. 하지만 하루아침에 모든 것이 바뀌었습니다.
CAAnimation 찾기
한 번은 뷰에서 일련의 이미지를 애니메이션해야 했습니다. 그래서 나의 첫걸음은 무엇이었습니까? 당연히 StackOverflow!
첫 번째 링크에 코드가 있습니다.
let image_1 = UIImage(named: "image-1")!
let image_2 = UIImage(named: "image-2")!
let image_3 = UIImage(named: "image-3")!
let images = [image_1, image_2, image_3]
let animatedImage = UIImage.animatedImage(with: images, duration: 2.0)
imageView.image = animatedImage
꽤 직관적인 것 같죠? 그렇게 간단했다면 이 글을 쓰지 않았을 것입니다.
이것은 필요한 애니메이션입니다:
그리고 분명히 밝혀진 바와 같이, 나는 그것에 가까이 있지 않았습니다. 나는 붙어 있었다. 어떻게 그 애니메이션에서 그렇게 많은 사용자 정의를 수행하고 모든 것을 동기화해야 했을까요?
그런 다음 동료가 CAAnimation을 사용해 보라고 했습니다. 나는 그것에 대해 읽고 샘플 프로젝트에서 그것을 시도했습니다. 놀랍게도 정말 강력하고 사용하기 쉬웠습니다.
코어 애니메이션이란 무엇입니까?
Core Animation을 사용하면 CPU 사용량이 거의 없이 여러 애니메이션을 실행할 수 있습니다.
매우 적은 코드로 사용할 수 있는 높은 프레임 속도와 많은 사용자 지정 기능을 제공합니다.
https://developer.apple.com/documentation/quartzcore
의 문서에서 자세한 내용을 찾을 수 있습니다.몇 시간 만에 기본 구현을 수행할 수 있었습니다.
func addAnimation(firstImageView: UIImageView, secondImageView: UIImageView) {
let basicAnimation1 = getBasicAnimation(withInitialPostion: centerPosition, finalPos: finalPosition)
firstImageView.layer.add(basicAnimation1, forKey: "position")
let basicAnimation2 = self.getBasicAnimation(withInitialPostion: self.initalPosition, finalPos: self.centerPosition)
secondImageView.layer.add(basicAnimation2, forKey: "position")
self.addNextImage(forImageView: firstImageView)
}
func getBasicAnimation(withInitialPostion initialPos: CGPoint, finalPos: CGPoint) -> CABasicAnimation {
let basicAnimation = CABasicAnimation(keyPath: "position")
basicAnimation.fromValue = NSValue(cgPoint: initialPos)
basicAnimation.toValue = NSValue(cgPoint: finalPos)
basicAnimation.duration = 1
basicAnimation.isRemovedOnCompletion = false
basicAnimation.fillMode = CAMediaTimingFillMode.forwards
basicAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
return basicAnimation
}
이 구현을 위해 CABasicAnimation을 사용했습니다. .
CABasicAnimation 클래스를 사용하면 두 값 사이의 레이어 속성(배경색, 불투명도, 위치, 크기 등)에 애니메이션 효과를 줄 수 있습니다. 시작 값과 끝 값만 지정하면 나머지는 알아서 처리됩니다. 애니메이션은 여기에 자세히 설명된 대로 다음 실행 루프에서 즉시 시작됩니다.
이제 우리의 문제로 돌아가십시오.
이를 구현하기 위해 두 개의 이미지 보기를 가져와 두 개의 개별 이미지를 추가했습니다. 그런 다음 CAAnimation을 사용하여 계속해서 애니메이션을 적용했습니다.
여기에서 소스 코드를 찾을 수 있습니다.
마지막 gif를 살펴보면 무언가가 꺼져 있음을 알 수 있습니다. 선물 상자의 첫 번째 이미지가 사라지기 전에 헤드폰이 잠시 깜박인 다음 이미지가 위로 이동합니다.
왜 이런 일이 발생합니까?
이미지 보기에 애니메이션을 추가하는 즉시 해당 보기에 다음 이미지를 추가하기 때문입니다(라인 번호 5 및 6).
private func addAnimation(firstImageView: UIImageView, secondImageView: UIImageView) {
let basicAnimation1 = getBasicAnimation(withInitialPostion: centerPosition, finalPos: finalPosition)
firstImageView.layer.add(basicAnimation1, forKey: "position")
let basicAnimation2 = self.getBasicAnimation(withInitialPostion: self.initalPosition, finalPos: self.centerPosition)
secondImageView.layer.add(basicAnimation2, forKey: "position")
self.addNextImage(forImageView: firstImageView)
}
여기서 우리는 애니메이션에서 두 이미지를 동기화하는 방법에 대한 문제로 고심하고 있습니다. 하지만 CAAnimation에는 항상 솔루션이 있습니다.
CA 거래
CA Transactions는 여러 애니메이션을 함께 동기화하는 데 도움이 됩니다. 함께 묶인 모든 애니메이션이 동시에 시작되도록 합니다.
또한 하나의 번들에 있는 모든 애니메이션이 완료될 때 실행되는 완료 블록을 애니메이션에 부여할 수 있습니다.
여기에서 자세한 내용을 읽을 수 있습니다.
private func addAnimation(firstImageView: UIImageView, secondImageView: UIImageView) {
CATransaction.begin()
CATransaction.setCompletionBlock {
self.addNextImage(forImageView: firstImageView)
}
let basicAnimation1 = getBasicAnimation(withInitialPostion: centerPosition, finalPos: finalPosition)
firstImageView.layer.add(basicAnimation1, forKey: "position")
CATransaction.commit()
let basicAnimation2 = self.getBasicAnimation(withInitialPostion: self.initalPosition, finalPos: self.centerPosition)
secondImageView.layer.add(basicAnimation2, forKey: "position")
}
CATransaction.begin()
을 작성하여 시작합니다. . 그런 다음 동기화하려는 모든 애니메이션을 작성하십시오. 마지막으로 CATransaction.commit()
을 호출합니다. 블록에서 애니메이션을 시작합니다.
이제 애니메이션이 어떻게 보이는지 봅시다.
마지막으로 해야 할 일은 애니메이션에 Spring 효과를 추가하는 것이었습니다. 고맙게도 CAAnimation에도 이에 대한 솔루션이 있었습니다.
CA 스프링 애니메이션
CA Spring Animation은 레이어에 추가될 때 스프링과 같은 효과를 주어 스프링에 의해 대상을 향해 당겨지는 것처럼 보입니다.
레이어가 대상에서 멀어질수록 대상을 향한 가속도가 커집니다.
스프링의 감쇠 및 강성과 같은 물리적 기반 속성을 제어할 수 있습니다. – 문서
Apple 설명서에서 이에 대한 자세한 내용을 읽을 수 있습니다. https://developer.apple.com/documentation/quartzcore/caspringanimation
기존 코드에 구현해 보겠습니다.
private func getSpringAnimation(withInitialPostion initialPos: CGPoint, finalPos: CGPoint) -> CASpringAnimation {
let basicAnimation = CASpringAnimation(keyPath: "position")
basicAnimation.fromValue = NSValue(cgPoint: initialPos)
basicAnimation.toValue = NSValue(cgPoint: finalPos)
basicAnimation.duration = basicAnimation.settlingDuration
basicAnimation.damping = 14
basicAnimation.initialVelocity = 5
basicAnimation.isRemovedOnCompletion = false
basicAnimation.fillMode = CAMediaTimingFillMode.forwards
return basicAnimation
}
내 작업은 여기에서 완료됩니다.
요약하면 다음은 CA Animations 사용의 몇 가지 이점입니다.
- 사용 및 구현이 간편합니다.
- 많은 사용자 정의가 가능합니다.
- 여러 애니메이션 동기화 가능
- CPU 사용량이 거의 없음
이것들은 단지 몇 가지 장점입니다. 가능성은 무한합니다.
이제 애니메이션에 대한 요구 사항이 있을 때마다 이를 디자인하고 구현하는 데 자신감을 느낍니다. 그리고 이 글을 읽고 여러분도 같은 마음이 되었으면 합니다.
제안이나 피드백을 자유롭게 남겨주세요.