動き続けるCALayer

CoreAnimationでCALayerを動かし続けたい時の方法です。プロパティ変更での暗黙的なアニメーションだといろいろと不都合なので、CABasicAnimationを使ってやってみました。

以下がそのサンプルです。カスタムビューにアウトレットをつなげて実行してください。

//
//  EndlessCoreAnimationTest.h
//

#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>

@interface EndlessCoreAnimationTest : NSObject {

    IBOutlet NSView *view;
    CALayer *moveLayer;
    NSTimer *timer;
    NSDate *startDate;
}

- (void)changeAnimation;

@end


//
//  EndlessCoreAnimationTest.m
//

#import "EndlessCoreAnimationTest.h"


@implementation EndlessCoreAnimationTest

- (void)awakeFromNib
{
    NSRect viewRect = [view bounds];
    CGFloat viewWidth = viewRect.size.width;
    CGFloat viewHeight = viewRect.size.height;
    CGFloat minSize = (viewWidth > viewHeight) ? viewHeight : viewWidth;
    
    CALayer *baseLayer = [CALayer layer];
    CGColorRef baseColor = CGColorCreateGenericRGB(0.0, 0.0, 0.0, 1.0);
    baseLayer.backgroundColor = baseColor;
    CGColorRelease(baseColor);
    
    moveLayer = [CALayer layer];
    moveLayer.anchorPoint = CGPointMake(0.5, - 9.0);
    moveLayer.bounds = CGRectMake(0, 0, minSize * 0.05, minSize * 0.05);
    moveLayer.position = CGPointMake(viewWidth * 0.5, viewHeight * 0.5);
    CGColorRef moveColor = CGColorCreateGenericRGB(1.0, 0.0, 0.0, 1.0);
    moveLayer.backgroundColor = moveColor;
    CGColorRelease(moveColor);
    
    [view setLayer:baseLayer];
    [view setWantsLayer:YES];
    [baseLayer addSublayer:moveLayer];
    
    [self performSelector:@selector(startTimer) 
        withObject:nil afterDelay:1.0];
}

- (void)startTimer
{
    startDate = [[NSDate date] retain];
    [self changeAnimation];
    timer = [NSTimer scheduledTimerWithTimeInterval:1.0 
        target:self selector:@selector(changeAnimation) 
        userInfo:nil repeats:YES];
}

- (void)changeAnimation
{
    CGFloat currentTime = [startDate timeIntervalSinceNow];
    CGFloat duration = 2.0;
    
    CABasicAnimation *anim = 
        [CABasicAnimation animationWithKeyPath:@"transform"];
    CATransform3D fromTrans = 
        CATransform3DMakeRotation(currentTime * M_PI / 4.0, 0.0, 0.0, 1.0);
    CATransform3D toTrans = 
        CATransform3DMakeRotation((currentTime - duration) * M_PI / 4.0, 
        0.0, 0.0, 1.0);
	
    anim.fromValue = [NSValue valueWithCATransform3D:fromTrans];
    anim.toValue = [NSValue valueWithCATransform3D:toTrans];
    anim.duration = duration;
    
    [moveLayer addAnimation:anim forKey:@"transformAnimation"];
}


- (void) dealloc
{
    [timer invalidate];
    [startDate release];
    
    [super dealloc];
}

@end

durationを2秒にしてtoValueを2秒後の値にしたCABasicAnimationを、NSTimerで1秒ごとに途切れる事無く追加しています。追加する時に動いているアニメーションの位置が新たなアニメーションのfromValueと一致するようになっていればスムーズにつながります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です