> iPhone-iPad > iOS에서 애니메이션을 사용해 보자. (Core Animation)

iOS에서 애니메이션을 사용해 보자. (Core Animation)

최근에 Core Animation에 대해서 숙지하는 시간을 가졌습니다. 단순히 컨트롤이나 간단한 이미지에 대한 애니메이션 기능이라는 것은 알고 있었지만, 나중에 필요할 때에 찾아서 하면 되겠지라고 생각하고 있었는데, 마침 시간이 좀 있어서 정리를 해 보았습니다.
내용을 보면서 느낀 점은 Core Animation의 기능을 만드는 것은 마치 프리젠테이션 툴(파워포인트, 키노트 등)에서 오브젝트 애니메이션을 만드는 것과 비슷하다는 생각을 했습니다. 오브젝트를 움직이는 것도 중요하지만 잘 만들어진 애니메이션은 지나치지 않으면서도 꼭 필요한 곳에 적절하게 사용되는 것이 중요할 거라 생각되네요.

그럼 지금부터 간단한 설명과 효과에 대한 소스코드를 공유해 보려 합니다.

Core Animation을 이용하기 위한 기본적인 클래스는 ‘CAAnimation’ 입니다.. 그리고, CAAnimation에서 파생된 클래스가 아래와 같습니다.

  • CABasicAnimation:기본적인 애니메이션.(CAPPropertyAnimation의 파생클래스)
  • CAKeyframeAnimation:키프레임 애니메이션.(CAPPropertyAnimation의 파생클래스)
  • CATransition:레이어 전체에 대한 전환 효과.
  • CAAnimationGroup:여러 애니메이션을 같이 실행.

Core Animation classes and protocol

1. CABasicAnimation
CABasicAnimation은 레이어(CALayer)에 대해서 기본 애니메이션과 싱글 키프레임 애니메이션을 제공합니다.
아래 몇가지 프로퍼티를 가지고 있습니다.

  • fromValue: 애니메이션의 시작값
  • byValue: 애니메이션의 중간값
  • toValue: 애니메이션의 끝값

그럼 예제 소스를 하나 만들어 보겠습니다. 본 문서에서 예제들은 모두 뷰컨트롤러의 적당한 위치(viewDidLoad 등…)에 아래 소스를 넣어주면 됩니다.


    /* 움직이기 위한 대상 레이어를 만듭니다. */
    CALayer *layer1 = [CALayer layer];
    layer1.bounds = CGRectMake(0, 0, 40, 40);
    layer1.position = CGPointMake(0, 160);
    layer1.cornerRadius = 20;
    layer1.backgroundColor = [UIColor blackColor].CGColor;
    [self.view.layer addSublayer:layer1]; // 만든 레이어를 뷰 레이어에 올립니다.
    
    /* 이동할 위치 지정 */
    CGPoint pStart = CGPointMake(0, 160);
    CGPoint pEnd = CGPointMake(160,0);
    
    /* 애니메이션 작성 */
    CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"position"];
    ani.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    ani.fromValue = [NSValue valueWithCGPoint:pStart];
    ani.toValue = [NSValue valueWithCGPoint:pEnd];
    
    ani.repeatCount = HUGE_VAL;
    ani.duration = 10.0;
    [layer1 addAnimation:ani forKey:@"position"]; // 애니메이션을 원하는 레이어에 설정합니다.

위 소스를 통해 간단한 애니메이션을 구현할 수 있습니다. 검정색 원이 왼쪽 아래에서 오른쪽 위로 올라오는 것을 볼 수 있습니다. 위 소스의 애니메이션 작성 부분에서 아직 설명하지 않은 것은 세가지가 있습니다. timingFunction, repeatCount 그리고 duration 입니다. repeatCount와 duration은 이름과 같이 몇번 반복할 것인지와 애니메이션이 일어나는 시간을 설정하는 것 입니다.
timingFunction은 애니메이션이 일어나는 타이밍을 설정합니다. 타이밍 설정은 아래 네가지를 이용하여 설정할 수 있습니다.

  • kCAMediaTimingFunctionLinear : 일정한 속도로 재생
  • kCAMediaTimingFunctionEaseIn : 처음에 천천히 시작
  • kCAMediaTimingFunctionEaseOut : 마지막에 천천히 종료
  • kCAMediaTimingFunctionEaseInEaseOut : 천천히 시작하고 마지막에 다시 천천히 종료

이제 간단하게 객체를 이동하는 수준의 애니메이션을 작성할 수 있습니다.
이동 이외에도 Animation KeyPath의 동작은 아래와 같은 것도 있습니다.

2. CAKeyframeAnimation
키프레임 애니메이션을 만들어줍니다. 풀어서 얘기하면 정형적이지 않은 여러곳을 이동하는 프레임을 CGPathRef를 이용하여 설정하고, 그 위치를 특정 레이어가 이동하는 것 입니다.
기본적으로 사용하는 프로퍼티는 path, rotationMode가 있습니다.

간단한 예제를 보겠습니다.


    /* 움직이기 위한 대상 레이어를 만듭니다. */
    CALayer *layer1 = [CALayer layer];
    layer1.bounds = CGRectMake(0, 0, 20, 20);
    layer1.position = CGPointMake(200, 200);
    layer1.cornerRadius = 10;
    layer1.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:layer1]; // 만든 레이어를 뷰 레이어에 올립니다.
    
    /* 이동할 위치 지정 */
    CGMutablePathRef path1 = CGPathCreateMutable();
    CGPathMoveToPoint(path1,NULL,layer1.position.x, layer1.position.y);
    CGPathAddLineToPoint(path1, NULL, layer1.position.x, layer1.position.y + 200);
    CGPathAddLineToPoint(path1, NULL, layer1.position.x + 150, layer1.position.y + 150);
    CGPathAddLineToPoint(path1, NULL, layer1.position.x, layer1.position.y + 0);
    
    /* 애니메이션 작성 */
    CAKeyframeAnimation *moveAni1 = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    moveAni1.path = path1;
    moveAni1.rotationMode = kCAAnimationRotateAuto;
    moveAni1.duration = 5.0;
    [layer1 addAnimation:moveAni1 forKey:@"position"]; // 애니메이션을 원하는 레이어에 설정합니다.

fromValue, toValue를 여러 포인트를 지정하는 path로 변경하고, 방향이 바뀌는 것에 대응하는 rotationMode를 제외하면 이전에 기본 애니메이션과 큰 차이는 없습니다.

3. CATransition
레이어가 전환되는 것을 처리하는 애니메이션 클래스입니다.
기본적으로 사용하는 프로퍼티는 아래와 같습니다.

  • type : 전환 애니메이션 종류.
  • subtype : 전화 애니메이션 방향.
  • duration : 애니메이션 시간.

간단한 예제를 통해 알아 보겠습니다.


    /* 전환 레이어 생성 */
    CALayer *layer4 = [CALayer layer];
    layer4.bounds = CGRectMake(0, 0, 320, 480);
    layer4.position = CGPointMake(0, 0);
    layer4.anchorPoint = CGPointMake(0, 0);
    layer4.backgroundColor = [UIColor blueColor].CGColor;
    [self.view.layer addSublayer:layer4];

    /* 전환 애니메이션 생성 */
    CATransition *transition = [CATransition animation];
    transition.type = kCATransitionReveal;
    transition.subtype = kCATransitionFromTop;
    transition.duration = 2.0;
    transition.delegate = self;
    [layer4 addAnimation:transition forKey:nil];

type에 설정되는 속성은 네가지입니다.

  • kCATransitionFade : 레이어를 바로 표시
  • kCATransitionMoveIn : subtype에 설정된 방향으로 진행하며 나타남. 이전에 있던 레이어 위로 나타남
  • kCATransitionPush : subtype에 설정된 방향으로 진행하며 나타남. 이전에 있던 레이어를 밀어냄
  • kCATransitionReveal : 희미한 상태에서 서서히 나타냄

subtype에 설정되는 속성은 네가지가 있습니다.

  • kCATransitionFromRight : 오른쪽 방향에서 들어옴.
  • kCATransitionFromLeft : 왼쪽 방향에서 들어옴.
  • kCATransitionFromTop : 아래에서 위로 올라옴. (왜? 테스트 결과 그렇게 됨.)
  • kCATransitionFromBottom : 위에서 아래로 내려옴.??

4. CAAnimationGroup
여러 애니메이션을 동시에 실행하는 경우 사용합니다. 예를 들면, 사진을 삭제하면 작아지면서 쓰레기통으로 이동하는 것에서 CABasicAnimation을 통해 작아지면서, CAKeyframeAnimation을 통해 이동하는 것으로 처리가 가능합니다. 마지막에 쓰레기통이 흔들리는 것은 Delegate설정을 한 후에 animationDidStop에서 처리해 주면 됩니다.
역시, 예제를 통해 알아보겠습니다.


    /* 움직이기 위한 대상 레이어를 만듭니다. */
    CALayer *layer1 = [CALayer layer];
    layer1.bounds = CGRectMake(0, 0, 20, 20);
    layer1.position = CGPointMake(200, 200);
    layer1.cornerRadius = 10;
    layer1.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:layer1]; // 만든 레이어를 뷰 레이어에 올립니다.
    
    /* 이동할 위치 지정 */
    CGMutablePathRef path1 = CGPathCreateMutable();
    CGPathMoveToPoint(path1,NULL,layer1.position.x, layer1.position.y);
    CGPathAddLineToPoint(path1, NULL, layer1.position.x, layer1.position.y + 150);
    CGPathAddLineToPoint(path1, NULL, layer1.position.x + 100, layer1.position.y + 100);
    CGPathAddLineToPoint(path1, NULL, layer1.position.x, layer1.position.y + 0);
    
    /* 이동 애니메이션 작성 */
    CAKeyframeAnimation *moveAni1 = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    moveAni1.path = path1;
    moveAni1.rotationMode = kCAAnimationRotateAuto;
    moveAni1.duration = 5.0;
    
    /* 스케일 애니메이션 작성 */
    CABasicAnimation *scalAni1 = [CABasicAnimation animationWithKeyPath:@"transform"];
    scalAni1.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    scalAni1.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
    scalAni1.duration = 5.0;
    
    /* 투명 애니메이션 작성 */
    CABasicAnimation *opacityAni1 = [CABasicAnimation animationWithKeyPath:@"opacity"];
    opacityAni1.fromValue = [NSNumber numberWithFloat:1.0];
    opacityAni1.toValue = [NSNumber numberWithFloat:0.1];
    opacityAni1.duration = 5.0;
    
    /* 애니메이션 그룹 작성 */
    CAAnimationGroup *group = [CAAnimationGroup animation];
    group.animations = [NSArray arrayWithObjects:moveAni1, scalAni1, opacityAni1, nil];
    group.duration = 5.0;
    
    [layer1 addAnimation:group forKey:nil]; //레이어에 그룹애니메이션 적용

그룹 애니메이션은 animations속성에 NSArray타입의 여러 애니메이션을 적용해 주는 것 만으로 애니메이션 동작이 가능합니다.

이상 CAAnimation의 기본적인 동작에 대해서 알아보았습니다. 간단한 앱내의 컨트롤들의 효과는 가능해 보이며, 재미있는 앱을 만들어 내는데 양념 역할을 충분히 할 수 있을 거라 생각합니다.
하지만, 처음에도 언급했던 것 처럼 지나친 애니메이션 사용은 사용자에게 피로감을 줄 수 있으니 잘 기획되어서 사용 해야겠습니다.

긴글 읽어주셔서 감사합니다.

추)
본문을 보시고, 코드 실행이 안되신다는 분들이 있습니다.
아마도 프레임워크 추가와 헤더 import에 대한 언급이 없어서 그런거라 판단됩니다. 그래서 간단한 이미지를 몇가지 첨부하겠습니다.
1. 프로젝트에 QuartzCore.framework 추가

2. 소스코드 추가 부분에 ‘QuartzCore/QuartzCore.h’ 임포트

3. 구현 부분

  1. 최진영
    2011/09/14 06:28

    코드좀 올려 주시면 안될까요?…

    넣는다고 넣었는데.. 잘 안되네요….

  2. 2011/09/14 09:48

    첨부파일을 좀 올려볼까 했는데. 워드프레스에서 첨부파일을 올리기가 쉽지 않네요.
    잘 안되신다면, 제가 본문에서 프레임워크 추가와 헤더부분을 말씀 드리지 않았는데. 그 부분 때문이라 생각됩니다.

    본문 아랫 부분에 관련해서 캡쳐를 첨부하겠습니다.

  3. ㅇㄱㅇ
    2012/04/30 17:54

    너무감사합니다!!!
    잘읽고가요!!

  4. 2012/07/20 09:29

    저에게 도움되는 글이었습니다. 잘 봤습니다. 감사합니다. ^^

    • 2012/08/08 17:25

      도움이 되셨다니 기쁩니다. 그런데, 이 글도 좀 업데이트를 해야 하는데. 좀 정체되어 있어 죄송하네요.
      앞으로도 많은 응원 부탁드립니다.

  5. meong-seok
    2014/06/19 11:31

    이미지를 여러개 붙여서 애니메이션효과를 주려고 하는대 이 코딩으로 할수 있는건가요??
    그런 효과를 한 View에 여러개 올리려고 생각중인대 이걸로는 모르겟어요.ㅜ^ㅜ

  1. No trackbacks yet.

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중

%d 블로거가 이것을 좋아합니다: