CoreAnimation 활용해서 버튼 회전시키기

marisol👩🏻‍💻·2022년 6월 20일
0

저번에 Core Graphics를 이용해서 버튼을 그려보는걸 했었는데,
(CoreGraphics 활용해서 +버튼 그려보기)
이번에는 CoreAnimation을 활용해서 그 + 버튼을 클릭하면 40도 회전시켰다가, 다시 클릭하면 원래 상태로 돌아오는 것을 구현해보았다


🦄 Core Animation

Core Animation은 iOS와 OS X 모두에서 사용할 수 있는 그래픽 랜더링 및 애니메이션 인프라를 말하며,
앱의 뷰 및 기타 시각적 요소를 애니메이션화 하는데 사용된다고 한다.

애플 아카이브 문서의 Core Animation Basics를 보면, 가장 먼저 Layers Provide the Basis for Drawing and Animations라는 파트가 나온다.

그래서 그 파트를 다루기 전에 먼저 layer의 공식문서를 살펴보자면,

layer는 렌더링에 사용되는 뷰의 Core Animation layer라고 정의되어 있다.
그리고 Discussion에 layer는 절대 0이 될 수 없고, 뷰는 layer의 delegate(위임자)라고 되어 있다.

Discussion 밑에 빨간색 경고로,
🚫 뷰가 layer의 위임자니까, view를 다른 CALayer 객체의 위임자로 만들지 말아라..
🚫 그리고 이 layer 객체의 위임자를 변경하지 말아라.. 라고 경고하고 있다

그러니까 모든 뷰 객체는 Core Animation Layer를 가지고 있는데, 이 Core Animation Layer는 뷰의 컨텐츠를 관리하고, 애니메이션화 해주는 역할을 한다는 것 같다.

다시 애플 아카이브 문서를 살펴보면,

대부분의 layers는 앱에서 실제 drawing을 수행하지 않는다. 대신 layer는 앱이 제공하는 컨텐츠를 캡처하여 비트맵에 캐시한다.
나중에 layer의 프로퍼티를 변경하면, layer 객체와 연관된 상태 정보만 변경된다.
변경 사항이 애니메이션을 트리거하면, Core Animation은 layer의 비트맵과 상태 정보를 그래픽 하드웨어에 전달한다.
그래픽 하드웨어는 새로운 정보를 사용해서 비트맵을 렌더링하는 작업을 수행한다.
하드웨어에서 비트맵을 조작하는 것은 소프트웨어에서 하는 것보다 훨씬 더 빠른 애니메이션을 생성한다.

라고 되어있는데, 그림을 보면 좀 더 이해가 쉽다.

Layer는 App Window에서 제공하는 컨텐츠를 캡쳐해서 비트맵 (Backing Store)에 캐싱
-> 캡쳐해둔 것과 변경사항이 발생해서 애니메이션이 트리거
-> Core Animation이 Layer의 비트맵과 상태 정보를 그래픽 하드웨어에 전달
-> 그래픽 하드웨어가 새 정보를 사용해서 비트맵을 렌더링

요런 프로세스인것 같다. layer가 직접 뭘 그리는게 아니라, layer가 캡쳐해서 캐싱해둔 비트맵과 상태 정보를 Core Animation이 그래픽 하드웨어한테 전달하면 그래픽 하드웨어가 렌더링을 한다는 것 같다.

그리고 layer에서 수행할 수 있는 애니메이션 유형은 다양한데, 오늘은 Rotate을 써볼거다!

♻️ Core Animation으로 버튼 회전시켜보기

📌 1. 회전된 상태인지 여부를 나타내는 bool 타입의 flag 생성

회전된 상태에서 버튼을 클릭했을 때 -> 원래 상태로 돌아오기
원래 상태에서 버튼을 클릭했을 때 -> 회전하기

이렇게 구현하기 위해서 먼저 flag를 설정해주었다

var isRotated: Bool = false

📌 2. 버튼 클릭 Action 메서드 내부에 회전 코드 작성

1) 애니메이션 제공하는 CABasicAnimation 객체 생성
2) 애니메이션 시작할 값을 정의
3) 애니메이션 끝날 값을 정의
4) 애니메이션 지속 시간 정의
5) 애니메이션이 끝날 상태로 고정
6) 버튼 layer의 render tree에 위 애니메이션 객체 추가

let rotation = CABasicAnimation(keyPath: "transform.rotation")
rotation.fromValue = 0 
rotation.toValue = Double.pi / 4.5
rotation.duration = 0.25
rotation.fillMode = .forwards
rotation.isRemovedOnCompletion = false
plusButton.layer.add(rotation, forKey: "rotationAnimation")

📌 3. 1번의 flag 값으로 분기처리

1) false일 때 위 2번을 실행하고, 마지막에 isRotated = true로 할당해주는 코드를 추가
2) 다시 되돌리는 기능은 rotation.fromValue와 rotation.toValue의 값을 바꿔서 구현 + isRotated = false로 할당

그러면 처음 버튼을 눌렀을때는 40도 회전하고, 다시 버튼을 누르면 원래 상태로 돌아오게 된다🤓


참고자료

0개의 댓글