'coreanimation'에 해당되는 글 1건

  1. 2013.11.28 iOS CoreAnimation정리 (2)

iOS에서 애니메이션 효과를 줄수 있는 방법은 세가지가 있다. 


UIView를 이용한 애니메이션. 제일 간단하고 쓰기 편하다.

    [UIView animateWithDuration:0.5f animations:^() {

        //애니메이션 내용코딩


    } completion:^(BOOL finished) {

        //애니메이션 끝난 처리


    }];





CABasicAnimation을 이용한 애니메이션. UIView애니메이션 보다 다양한 옵션을 줄 수있다. 기본 제공해주는 애니메이션 옵션이 많으므로 구현하기도 편하다.


1.QuartzCore.framework를 프로젝트에 추가하고 QuartzCore/QuartzCore.h를 사용할 클래스에 임포트 해준다.


#import <QuartzCore/QuartzCore.h>


2.CABasicAnimation의 인스턴스를 생성하고 애니매이션을 등록해 준다.

animationWithKeyPath: 메소드를 사용해서CABasicAnimation 의 인스턴스를 생성한다. 생성할 때에 keyPath에 사용할 키를 지정한다.


예를 들어 이동하는 애니메이션의 경우 position프로퍼티를 지정해 준다.

CABasicAnimation *animation =

    [CABasicAnimation animationWithKeyPath:@"position"];



3.애니메이션 옵션을 설정한다. 

*옵션종류

 duration

 애니메이션 재생시간

 repeatCount

 반복횟수

 beginTime

 애니메이션 시작설정

애니메이션 시작을 늦추려면 CACurrentMediaTime() + 초

의 형식으로 지정해 준다.

 timingFunction

 애니메이션 속도 변화지정

 autoreverses

 애니메이션 종료 후 역순으로 실행할지를 지정

 

 


아래와 같이 사용하면 된다.

animation.duration = 2.5; 

animation.repeatCount = 1; 

animation.beginTime = CACurrentMediaTime() + 2;

animation.autoreverses = YES;

animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];



4.애니메이션 시작과 종료를 지정한다. 지정값은 키패스(keyPath)에 의해서 변한다.


 fromValue

 시작값

 toValue

종료값(절대치) 

 byValue

종료값 (상대치)


아래와 같은 형식으로 이용할 수 있다.

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];

animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];

animation.toValue = [NSValue valueWithCGPoint:CGPointMake(320, 480)];



5.작성한 애니메이션은 레이어에 추가할 수 있는데 그때에는 임의의 키패스(keyPath)를 지정한다.


[myView.layer addAnimation:animation forKey:@"testani"];


재생이 끝나면 처음상태로 되돌아 온다. 만약 애니매이션이 끝난상태 되돌아가지 않게 하려면 아래와 같이 코딩해 준다.

애니메이션이 끝난상태(completed)에서 아래의 코딩을 해준다.

animation.removedOnCompletion = NO;

animation.fillMode = kCAFillModeForwards;


CABasicAnimation사용예

/* 이동 */

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];

animation.duration = 2.5;

animation.repeatCount = 1;

animation.fromValue = [NSValue valueWithCGPoint:myView.layer.position];

animation.toValue = [NSValue valueWithCGPoint:CGPointMake(320, 480)];

[myView.layer addAnimation:animation forKey:@"move-layer"];


/* 회전 */

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];

animation.duration = 2.5;

animation.repeatCount = 1;

animation.fromValue = [NSNumber numberWithFloat:0.0]; 

animation.toValue = [NSNumber numberWithFloat:2 * M_PI]; //회전각도

[myView.layer addAnimation:animation forKey:@"rotate-layer"];


/* 확대, 축소 */

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

animation.duration = 2.5;

animation.repeatCount = 1;

animation.autoreverses = YES;

animation.fromValue = [NSNumber numberWithFloat:1.0]; //1배

animation.toValue = [NSNumber numberWithFloat:2.0]; // 2배

[myView.layer addAnimation:animation forKey:@"scale-layer"];


복수개의 애니메이션처리를 할경우에는 아래와 같이 처리해 준다.


/* 애니메이션1(x축방향으로 이동) */

CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];

animation1.toValue = [NSNumber numberWithFloat:80];

 

/* 애니메이션2(z축으로 중심이동회전) */

CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

animation2.fromValue = [NSNumber numberWithFloat:0.0]; //시작각도 

animation2.toValue = [NSNumber numberWithFloat:4 * M_PI]; //360도(90*4)

 

/* 애니메이션그룹 */

CAAnimationGroup *group = [CAAnimationGroup animation];

group.duration = 3.0;

group.repeatCount = 1;

group.animations = [NSArray arrayWithObjects:animation1, animation2, nil];

[myView.layer addAnimation:group forKey:@"move-rotate-layer"];



애니메이션 시작과 종료시 이벤트를 취득할 경우에는 델리게이트를 지정해 준다.

animation.delegate = self; 

 

딜리게이트 메소드

/**

 * 애니메이션 시작

 */

- (void)animationDidStart:(CAAnimation *)theAnimation

{

    NSLog(@"시작");

}

 

/**

 * 애니메이션 종료

 */

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag

{

    NSLog(@"종료");

}





마지막으로 CAKeyframeAnimation 이다. 전에 설명했던 애니메이션보다 더 세밀한 애니메이션을 지정할 수 있다.


CAAnimation를 사용하기 위해서는 <QuartzCore/QuartzCore.h> 프레임워크를 추가하고 해당 클래스에 임포트해 주어야 할 필요가 있다.


아래와 예제를 보자.



CAAnimation에 있는 Keyframe을 사용한다.


// scaleX와scaleY의 변화량을 키프레임(keyframe)형식으로 지정한다.

// array의갯수는 다음에 코딩할 timing과 숫자가 일치해야 한다.

NSArray *values = [NSArray arrayWithObjects:

                   [NSNumber numberWithFloat:0.1],

                   [NSNumber numberWithFloat:1.0],

                   [NSNumber numberWithFloat:1.0],

                   [NSNumber numberWithFloat:7.0],

                   nil];


// 투명도의 변화량을 키프레임(keyframe)형식으로 지정한다.

//array의갯수는 다음에 코딩할 timing과 일치 해야 한다.

NSArray *values2 = [NSArray arrayWithObjects:

                   [NSNumber numberWithFloat:0.1],

                   [NSNumber numberWithFloat:1.0],

                   [NSNumber numberWithFloat:1.0],

                   [NSNumber numberWithFloat:0.0],

                   nil];    


// Keyframe에 이용할 시간을 지정한다.(0.0~1.0)

// 0부터 1까지 지정하는걸 몰라서 한참 해맷는데.. 이걸로 CABasicAnimation에서 할수 없었던 세밀하게 속도조절이 가능하다.

NSArray *timing = [NSArray arrayWithObjects:

                   [NSNumber numberWithFloat:0.0],

                   [NSNumber numberWithFloat:0.25],

                   [NSNumber numberWithFloat:0.85],

                   [NSNumber numberWithFloat:1.0],

                   nil];


// 전체 애니메이션 시간

float duration = 1.5f;


// scaleX의keyframe의 애니메이션 지정

CAKeyframeAnimation *keyframe = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale.x"];

keyframe.values = values;

keyframe.keyTimes = timing;

keyframe.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

keyframe.duration = duration;


// scaleY의keyframe의 애니메이션 지정

CAKeyframeAnimation *keyframe2 = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale.y"];

keyframe2.values = values;

keyframe2.keyTimes = timing;

keyframe2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

keyframe2.duration = duration;


// 투명도 애니메이션 지정

CAKeyframeAnimation *keyframe3 = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];

keyframe3.values = values2;

keyframe3.keyTimes = timing;

keyframe3.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

keyframe3.duration = duration;



// CATransaction를 이용해 3개의 애니메이션을 동시에 실행

[CATransaction begin];

[CATransaction setCompletionBlock:^{

    NSLog(@"animation end.");

    [animationView removeFromSuperview];

}];

[animationView.layer addAnimation:keyframe forKey:@"transform.scale.x"];

[animationView.layer addAnimation:keyframe2 forKey:@"transform.scale.y"];

[animationView.layer addAnimation:keyframe3 forKey:@"opacity"];

[CATransaction commit];


애니메이션은 commit하는 동시에 실행되며 CATransaction을 사용하지 않고 addAnimation만 사용했을경우  addAnimation을 호출한 시점에서 실행된다.



이외에도 상세한 설정을 할수도 있는데 그건 귀찮아서 나중에 정리...할 생각이다. 

아래 소스를 참조해서 연구하면 될듯.

https://github.com/nakiwo/KeyFrameSample


아래는 Core Animation 애플문서(일본어)

https://developer.apple.com/jp/devcenter/ios/library/documentation/CoreAnimation_guide.pdf

Posted by 악당잰 트랙백 0 : 댓글 2

댓글을 달아 주세요

  1. addr | edit/del | reply 개발초보 2015.03.14 02:14

    효율은 어떻게되죠?

    왜인지는 모르겠지만 첫번째 방법으로 하는 것보다 2번째 방법이나 3번째 방법이 효율이 더 좋을것같은데.

    • addr | edit/del BlogIcon 악당잰 2015.03.14 12:02 신고

      코드작성면에서의 효율로 보자면 간단한 애니메이션(알파값조정, 프레임 위치조정)의경우 첫번째가 효율이 좋지 않을까 생각합니다.
      두번째 세번째는 다양한 애니메이션이 가능하므로 복잡한 애니메이션의 경우에 유리하겠죠.