POPに触発されて作ったとのこと。UIControlに紐づくようなアニメーションコードを書くのにとても参考になる。このライブラリ自体はカテゴリとして CALayerなどに紐付けるようにできてる。
CHAnimation is a project used to demonstrate how to write your own animation engine, inspired by Facebook Pop, with only 600 lines of Objective-C you can understand.
利用はこんなイメージ
#import "CHAnimation.h" CHAnimation *animation = [CHAnimation new]; animation.duration = 0.4; animation.writeBlock = ^(id obj, id value) { button.center = [value CGPointValue]; }; animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(70, 70)]; animation.toValue = [NSValue valueWithCGPoint:CGPointMake(170, 170)]; [button ch_addAnimation:animation forKey:@"animation"];
内部を見ると CHAnimation, CHAnimationState, CHAnimator の3つから構成されていて、CHAnimationがアニメーションの定義、CHAnimationStateがアニメーションの状態管理と実行、CHAnimatorがアニメーションの管理(複数紐付けできるので)となっている。
まずCHAnimatorの -init で CADisplayLinkに描画メソッドを登録しておく(初期は停止)。
- (id)init { self = [super init]; if (self) { _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render)]; _displayLink.paused = YES; [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; :任意のタイミングで paused =NO にすればアニメーションするわけだ。
アニメーションのレンダリングは CHAnimator の -renderTime: で制御する。
- (void)renderTime:(CFTimeInterval)time { [CATransaction begin]; [CATransaction setDisableActions:YES]; NSMutableArray *doneAnimations = [NSMutableArray new]; for (CHAnimatorItem *item in _list) { CHAnimationState *state = CHAnimationGetState(item.animation); if ([state startIfNeeded:item.animation atTime:time]) { [state applyAnimation:item.animation atTime:time]; if ([state isDone]) { [doneAnimations addObject:item]; :
登録されているアニメーションを取り出して描画していく。この時直接 CHAnimationを呼ぶのではなくタイミング等を管理する CHAnimationStateが状態を管理しつつ描画を行う(-[CHAnimationState applyAnimation:]→この中で -[CHAnimation writeBlock]を呼び出す)。