UIView Animation
가장 간단한 애니메이션 기법은 UIView의 정적 메소드인 animationWithDuration을 사용합니다.
iOS 7.0에서 추가된 새로운 애니메이션 메소드는 제외하고, 기본 애니메이션 문법은 다음과 같습니다.
[UIView animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations]
[UIView animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion]
[UIView animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion]
앞의 두 메소드는 3번째의 축약형이므로 마지막 것만 설명합니다.
duration은 애니메이션이 재생되는 총 시간(초 단위)입니다.
delay는 애니메이션이 시작되기 전에 줄 딜레이(초 단위)입니다.
options는 애니메이션에 들어가는 옵션들입니다. UIViewAnimationOptions를 참고하세요.
animations 블록에서는 애니메이션이 일어날 속성들을 적어줍니다.
completion은 애니메이션의 수행이 끝난 후 일어날 일들을 적어줍니다.
여기에 추가적으로 애니메이션 코드 중첩시켜 연속적인 변화를 줄 수 있습니다.
다음은 간단한 예제입니다. itemView를 2초간 y축으로 500까지 이동시킨 후,
0.5초 후에 2초간 itemView의 색상을 파랑으로 바꿉니다.
모든 애니메이션이 끝나면 itemView의 속성들을 원래대로 되돌립니다.
CGFloat y = self.itemView.y;
UIColor* color = self.itemView.backgroundColor;
[UIView animateWithDuration:2.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.itemView.y = 500;
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.0 delay:0.5 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.itemView.backgroundColor = [UIColor blueColor];
} completion:^(BOOL finished) {
self.itemView.y = y;
self.itemView.backgroundColor = color;
}];
}];
Easing Functions
UIViewAnimationOptions 항목 중 다음 네 가지가 있습니다.
UIViewAnimationOptionCurveEaseInOut = 0 << 16,
UIViewAnimationOptionCurveEaseIn = 1 << 16,
UIViewAnimationOptionCurveEaseOut = 2 << 16,
UIViewAnimationOptionCurveLinear = 3 << 16,
Easing은 시작값과 끝값으로 이루어지는 애니메이션의 중간 흐름을 조절합니다.
EaseIn은 느리게 시작해서 점점 빨라지는 흐름이며, EaseOut은 빠르게 시작해서 점점 느려지는 흐름입니다.
EaseInOut 은 느리게 시작해서 점점 빨라졌다가, 애니메이션의 종반부에선 다시 느려지면서 끝납니다.
Linear은 애니메이션의 흐름 속도가 일정합니다.
보통 가장 자연스러운 흐름은 EaseInOut이지만 보여주고 싶은 애니메이션에 따라 바뀔 수 있습니다.
4가지밖에 안되는 Easing Function은 UIView Animation의 주요 제한점 중 하나입니다.
Animation Properties
애니메이션 가능한 UIView의 프로퍼티는 다음과 같습니다.
* UIView의 transform 속성은 CGAffineTransform으로, 2차원 변환만을 지원합니다.
아래 설명할 CALayer의 transform과는 다른 구조체입니다.
이 외에, 뷰와 연결된 layer의 애니메이션 가능한 프로퍼티 역시 모두 사용할 수 있습니다.
티몬앱에서 layer의 속성을 바꾸는 방법으로 애니메이션을 구현한 경우가 있습니다.
레이어를 사용하면 다음과 같은 애니메이션이 가능합니다.
The size and position of the layer
The center point used when performing transformations
Transformations to the layer or its sublayers in 3D space
The addition or removal of a layer from the layer hierarchy
The layer’s Z-order relative to other sibling layers
The layer’s shadow
The layer’s border (including whether the layer’s corners are rounded)
The portion of the layer that stretches during resizing operations
The layer’s opacity
The clipping behavior for sublayers that lie outside the layer’s bounds
The current contents of the layer
The rasterization behavior of the layer
CALayer 사용하기
앞에서 알아본 것 같이, UIView의 애니메이션 속성은 제한적인 데 비해 layer를 사용하면 더 다양한 애니메이션을 사용할 수 있습니다.
레이어는 UIView.layer 속성으로 접근할 수 있으며, CALayer 타입입니다.
CALayer는 UIView의 요소 중 ‘그리기’를 담당하는 클래스이며, UIView에 노출된 것 보다 풍부한 기능을 가지고 있습니다.
iOS에서 UIView와 CALayer는 1:1로 대응하며 하나의 속성을 바꾸면 다른쪽의 속성도 바뀝니다.
이러한 구현을 Layer-Backed View라고 합니다. OS X에서는 Layer-Hosting View라는 것도 있으며, 이 경우 구현이 다르므로
검색할 때 유의하시기 바랍니다.
CALayer를 이용할 때는 한가지 문제가 있는데, 원래 CALayer의 애니메이션은 Core Animation의 일부이므로,
[UIView animatedXX] 를 이용할 경우 정상적으로 애니메이션 되지 않는 속성이 많다는 것입니다.
이부분은 뒤에 Core Animation을 이용하는 부분에서 다루며, 우선 UIView 애니메이션에서 사용가능한 CATransform3D를 설명합니다.
CALayer에서 애니메이션 가능한 프로퍼티 목록을 다음 링크에서 볼 수 있습니다.
CATransform3D 사용하기
UIView와 CALayer는 둘다 transform속성을 가지고 있지만, UIView의 transform과는 달리,
CALayer의 transform 속성은 3D 변환이 가능한 CATransform3D형이며, 4x4 행렬을 의미하는 구조체입니다.
3D변환 행렬에 대한 기본적인 내용은 다음을 참고하세요.
http://blog.naver.com/ojh6t3k/20194968081
행렬을 이용해서 수행할 수 있는 기본 변환은 회전(rotate), 이동(translation), 크기조정(scale)의 세가지입니다.
세가지를 혼합해서 좀더 다양한 애니메이션을 만들게 됩니다.
기본 transform 속성의 값은 4x4 단위행렬입니다. 단위행렬은 CATransform3DIdentity로 액세스할 수 있습니다.
CATransform3DMakeXXX 함수를 이용하면 변환행렬을 만들 수 있습니다. 다음 코드는 z축으로 30도를 회전시키는 행렬을 만들어 적용하는 애니메이션입니다.
(angle이 음수인 경우 회전방향이 반대가 됩니다.)
[UIView animateWithDuration:3.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
CATransform3D rotateX = CATransform3DMakeRotation(M_PI / 6, 1.0, 0, 0);
self.itemView.layer.transform = rotateX;
} completion:nil];
여러개의 변환을 동시에 하기 위해서는, 하나의 변환에 다른 변환을 더합니다. CATransform3DXXX 함수를 사용하면 됩니다.
아래는 2배 확대와 이동을 동시에 적용시킨 애니메이션입니다.
- (void)scaleAndTranslate3D
{
[UIView animateWithDuration:3.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
CATransform3D scaleX = CATransform3DMakeScale(2.0, 2.0, 2.0);
CATransform3D scaleAndTranslateX = CATransform3DTranslate(scaleX, 100.0, 0, 0);
self.itemView.layer.transform = scaleAndTranslateX;
} completion:^(BOOL finished) {
self.itemView.layer.transform = CATransform3DIdentity;
}];
}
3D 애니메이션에서 빼놓을 수 없는 것이 하나 있는데, 원근법입니다.
원근법이 정의되지 않으면 개체가 멀어지거나 가까워지는 모습을 제대로 표현할 수가 없습니다.
아래의 예제는 객체를 60도 회전시키는 예제이지만, 원근이 표현되지 않았기 때문에 회전이 아니라 짜부라지는 것처럼 보입니다.
- (void)rotateWithoutPerspective
{
CATransform3D transform = CATransform3DMakeRotation(M_PI / 3, 0.5, 0, 0);
[UIView animateWithDuration:3.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.itemView.layer.transform = transform;
} completion:nil];
}
객체에 원근감을 주는 변환의 계산은 어렵지만, 결론은 단순합니다.
위 페이지의 맨 하단에 “Adding Perspective to Your Animations” 항목에서 변환에 원근감을 주는 방법을 설명하고 있습니다.
위 예제에서는 CATransform3D에 m34를 세팅한 다음 sublayerTransform에 넣는 방법을 사용하지만,
변환을 수행할 CATransform3D의 m34가 해당 내용처럼 들어있기만 하면 됩니다.
아래 예제에서 850은 눈의 위치이며, 숫자를 크게 하면 원근도 커집니다.
- (void)rotateWithPerspective
{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = - 1.0f / 850;
transform = CATransform3DRotate(transform, M_PI / 3, 0, 0.5f, 0);
[UIView animateWithDuration:3.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.itemView.layer.transform = transform;
} completion:nil];
}
CALayer의 anchorPoint 사용하기
CALayer에는 UIView에 없는 중요한 속성 두가지가 있습니다.
하나는 position, 하나는 anchorPoint이며, CALayer의 위치를 잡는 것은 이 두가지 프로퍼티입니다.
position은 layer의 위치를 표현하는데, UIView의 position이 frame의 좌측 최상단 점인데 비해,
layer에서는 position이 기본적으로 layer의 중점입니다. position이 정확하게 layer 내의 어디를 의미하는지
결정하는 것이 anchorPoint이며, 기본값이 (0.5, 0.5)입니다.
layer를 회전시킬 경우 anchorPoint가 중점이 되므로 이 값이 중요합니다.
anchorPoint를 변경하면 그에 맞추어 layer가 이동하게 되는데, 보통은 이를 의도하지 않기 때문에
anchorPoint로 인해 이동하는 레이어를 원래 위치로 돌려놓는 코드를 작성하게 됩니다.
티몬 앱에서 이 코드는 [UIView setAnchorPoint:]로, UIView+Helper 카테고리에 정의되어 있습니다.
다음 예제는 나머지 부분에서 위의 rotateWithPerspective와 동일하지만, anchorPoint를 오른쪽 끝으로 설정한 것입니다.
- (void)rotateWithAnchorPoint
{
[self.itemView setAnchorPoint:CGPointMake(1.0f, 0.5f)];
CATransform3D transform = CATransform3DIdentity;
transform.m34 = - 1.0f / 850;
transform = CATransform3DRotate(transform, M_PI / 3, 0, 0.5f, 0);
[UIView animateWithDuration:3.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.itemView.layer.transform = transform;
} completion:nil];
}
Evernote Data:
{"source": "missing value", "created": "2014년 3월 17일 월요일 오후 5:39:11", "modified": "2014년 5월 22일 목요일 오후 4:24:43", "tags": "", "altitude": "missing value", "latitude": "missing value", "longitude": "missing value" }