[ios/tutorial] Core Animation 모든 것!!
참고 : https://www.objc.io/issues/12-animations/animations-explained/
-
Animation 을 수행하는 방법은 크게 2가지.
1. UIView 의 class method “animateWithDuration:” 을 사용하는 방법
2. Core Animation 을 사용하는 방법.
Simple Animation 이 아니라면 Core Animation 을 사용하는 것이 추천된다.
훨씬 코드의 가독성이 좋고, 더 많은 기능을 제공한다.
But, 더 많은 학습을 필요로 한다.
물론 애플의 권장사항은 할수만 있다면 항상 UIKit 에서 제공되는 Animation 을 사용하길 원한다.
-
Core Animation 은 iOS 의 Animation framework.
Cached Bitmap 과 Hardware 를 내부에서 사용하여 성능 짱짱!
Animation 자체는 다른 thread 에서 작동한다.
-
Core Animation 을 이해하려면 우선 CALayer 라는 녀석을 알아야 한다.
CALayer 는 UIView 에는 최소 1개씩 다 있는 녀석으로 rendering 을 관장한다.
“content” 라는 property 가 핵심이며, 결국 여러 방법 중 하나로 그려진 bitmap 을 가지고 있는 녀석이라고 보면 된다.
Stand alone 가능하고, View 처럼 Layer tree 를 갖는다.
심화학습 (DIY)
CALayer 를 상속한 CATiledLayer, CAEAGLLayer 등이 있는데, 상황에 따라 rendering performance 를 높일 수 있다.
-
중요!!
Core Animation Framework 는 CALayer 의 property 들을 직접 modify 하지 않는다.
Core Animation 은 2개의 Layer tree를 관리하는데,
하나는 Model layer tree, // 이 녀석이 CALayer, [CALayer modelLayer]
다른 하나는 Presentation layer tree. // 이 녀석이 Animation 중에만 관리되는 녀석, [CALayer presentationLayer]
-
CoreAnimation 에서 가장 많이 쓰이는 두 녀석은..
CABasicAnimation
CAKeyframeAnimation
-
이동시켜보자.
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@“position.x”]; // KVC
animation.fromValue = @77; // NSValue 로 wrapping 해야함.
animation.toValue = @455;
animation.duration = 1; // CGFloat 으로 초단위임
animation.beginTime = CACurrentMediaTime() + 1; // 현재에서 1초 후
[rocket.layer addAnimation:animation forKey:@“basic”]; // copy 됨
심화학습 (DIY)
fromValue, byValue, toValue 가 있는데 이 중 2개는 보통 채워져야 한다.
각각의 case 에 대해 어떻게 작동하는가가 다르다.
-
기본적으로 Animation 이 끝나면 Layer 에서 Animation 이 사라지면서 Presentation Layer 의 값이 Model Layer 값으로 변한다.
즉 Animation 이 끝나는 시점에 본래 CALayer 의 property 값으로 reset 되는 것이다.
이를 해결하는 방법은 2가지
1. 끝나는 값으로 Model Layer 값을 바꿔준다.
2. CABasicAnimation 의 fillMode 를 kCAFillModeForwards 로 하고 && removedOnCompletion = NO 를 설정해준다. // 편하지만 단점도 있다. (User Interaction)
animation.fillMode = kCAFillModeForward;
animation.removedOnCompletion = NO;
-
CAKeyframeAnimation 을 보자.
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@“position.x"];
animation.values = @[ @0, @10, @-10, @10, @0 ];
animation.keyTimes = @[ @0, @(1 / 6.0), @(3 / 6.0), @(5 / 6.0), @1 ]; // values 와 갯수가 같아야 한다. 0~1 사이의 값으로 각 frame 에 대한 시간
animation.duration = 0.4;
animation.additive = YES; // set 이 아닌 add
[form.layer addAnimation:animation forKey:@"shake"];
-
KeyframeAnimation 의 진가는 Path 에 있다.
CGRect boundingRect = CGRectMake(150, 150, 300, 300);
CAKeyframeAnimation *orbit = [CAKeyframeAnimation animationWithKeyPath:@“position"];
orbit.path = CFAutorelease(CGPathCreateWithEllipseInRect(boundingRect, NULL)); // circular path
orbit.duration = 4;
orbit.additive = YES;
orbit.repeatCount = HUGE_VALF;
orbit.calculationMode = kCAAnimationPaced; // linear, keyTimes 를 대체
orbit.rotationMode = kCAAnimationRotateAuto;
[satellite.layer addAnimation:orbit forKey:@"orbit"];
rotationMode 가 nil 인 경우 위성이 반대로 돈다.
-
Keyframe 에 사용할 Path 는 아래와 같이 만들어 사용할 수 있다.
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path1, NULL, layer1.position.x, layer1.position.y);
CGPathAddLineToPoint(path1, NULL, layer1.position.x, layer1.position.y + 200);
-
CAMediaTimingFunction 을 사용해서 Ease 함수를 전달할 수 있다.
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
-
kCAMediaTimingFunctionEaseIn
kCAMediaTimingFunctionEaseOut
kCAMediaTimingFunctionEaseInEaseOut
kCAMediaTimingFunctionDefault
-
CAMediaTimingFunction functionWithControlPoints:::: 를 통해서도 구체적인 timing function 을 구할 수 있다.
이 녀석은 Bezier curve
-
여러개의 Animation 을 한번에 관리하고 싶다면 CAAnimationGroup
CAAnimationGroup *groupAni = [[CAAnimationGroup alloc] init];
groupAni.animations = @[ positionAni, rotateAni, zOrderAni ];
groupAni.duration = 1.2;
groupAni.beginTime = 0.5;
[view.layer addAnimation:groupAni forKey:@“groupAnimation"];
-
CATransaction 으로도 처리 가능하다.
[CATransaction begin];
...
[CATransaction commit];
-
Animation Finish Callback 을 설정하고 싶다!!
CAAnimation 의 delegate 에 object 를 전달하고,
animationDidStart: 와 animationDidStop:finished: 를 구현한다.
이들은 protocol 이 아닌 selector 방식.
-
그럼 Animation 가능한 layer 의 property 들은 뭐가 있는가?
Geometry Properties
bounds
position
frame
anchorPoint
cornerRadius
transform
zPosition
Background Properties
backgroundColor
Layer Content
contents
contentsGravity
masksToBounds
Sublayers Content
sublayers
masksToBounds
sublayerTransform
Border Attributes
borderColor
borderWidth
Shadow Properties
shadowColor
shadowOffset
shadowOpacity
shadowRadius
shadowPath
Opacity Property
opacity
Mask Properties
mask
-
Animation 성능 향상
Opaque layer 사용
같은 내용물을 보여주는 Layer 라면 Layer Contents 를 명시적으로 setting 해라.
Layer 의 사이즈를 항상 정수형으로 가져가라.
직접 그리는 Animation 의 경우, Async Layer Rendering 기능을 사용하라.
Shadow 를 사용할 경우에는 Shadow Path 를 지정하라
-
기타 학습 내용
CATransition ( type, subType 값으로 fade, moveIn, push, reveal animation 가능 )
CATransform3D
Implicit Animation
Spring Animation ( 9.0 에서는 CASpringAnimation 이 나왔다능.. )
-
정리
Core Animation
CABasicAnimation
CAKeyframeAnimation
CAGroupAnimation
CALayer
Model layer tree
Presentation layer tree
CABasicAnimation
fromValue
toValue
duration
beginTime
fillMode
removedOnCompletion
timingFunction
…
CAKeyframeAnimation
values
keyTimes
path
...
'프로그래밍 놀이터 > iOS' 카테고리의 다른 글
[ios] Objective-C 와 Swift 동시에 사용하기 (0) | 2017.12.02 |
---|---|
[ios/tutorial] CABasicAnimation, CATransition, CAKeyframeAnimation, CALayer, CAAnimationGroup ( Core Animation ) (0) | 2017.12.01 |
[ios/reference] Advanced Animation Tricks (0) | 2017.11.29 |
[ios/tutorial] Implicit Animation (0) | 2017.11.28 |
[ios] Umbrella Framework? Umbrella Header? (0) | 2017.11.27 |
댓글