.Sched 3 で予定をタップした時の背景をぼかすアニメーションの実装方法

.Sched 3 で予定をタップした時に、背景をぼかすアニメーションを実装してるのですが、今回はこの実装方法について紹介します。

紹介ビデオの 0:12,0:35,0:45あたりのやつです。


.Sched 2 の時も、メニュー表示時にこのアニメーションを利用してました。

 

どうやっているかというと、CALayerのCABasicAnimationで、rasterizationScaleの値を変化させています。

ボカシたいタイミング、ボカシをもどしたいタイミングで以下を実行します。

ボカシ処理開始時。

layer.shouldRasterize = YES;
CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"rasterizationScale"];
myAnimation.fromValue = [NSNumber numberWithFloat:1.0];
myAnimation.toValue = [NSNumber numberWithFloat:0.07];
myAnimation.duration = 0.3;
//アニメーション終了時にエフェクトが元に戻らないようにしておく
myAnimation.removedOnCompletion = NO;
myAnimation.fillMode = kCAFillModeForwards;
[layer addAnimation:myAnimation forKey:@"myAnimation"];

 

ボカシを終了して戻す時

CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"rasterizationScale"];
myAnimation.fromValue = [NSNumber numberWithFloat:0.07];
myAnimation.toValue = [NSNumber numberWithFloat:1.0];
myAnimation.duration = 0.3;
myAnimation.removedOnCompletion = NO;
myAnimation.fillMode = kCAFillModeForwards;
[layer addAnimation:myAnimation forKey:@"myAnimation"];

これだけです。

アニメーション適用対象レイヤーのレイヤーツリー配下の全てレイヤーがアニメーション対象となるため、フォーカスしたい部分は、指定レイヤーのレイヤーツリー配下にないようにしておく必要があります。

当初、予定詳細表示時のアニメーションとして、画面がパカーンと割れてスライドするアニメーション(iPhoneのフォルダを開いた時のアニメ)を実装したんですが、上下に割れる形にすると、パフォーマンス的にいまいちだし、思ったほどマッチしなかったので、今回のアニメーションに変更しました。

 

CALayerの描画チューニングとshadow表示

.Sched 3 の日表示モードでは、予定をドラッグ移動できるようになっています。

予定のドラッグ操作時にタッチポジションに合わせ、予定単体のUIViewもしくはCALayerを移動させるのであれば、どうってことはないのですが、既存の予定と重なったときに、ぐにゃぐにゃとアニメーションさせたかったので、逐次描画計算してアニメーションするようにしています。

最初に実装した時点では、パフォーマンスが全く出ずカクカクなアニメーションで実用に耐えない状況でしたが、チューニングしてなんとか使えるレベルのパフォーマンスを出せるようになりました。

 

まずは、iOSシミュレータでデバッグ

iOSシミュレータのデバッグメニューで、
  • ブレンドレイヤー
  • コピーイメージ
  • 不揃いのイメージ
  • オフスクリーンレンダリング
をチェックすると、シミュレータ上の画面が色付きで表示されます。


上のイメージのように、ブレンドレイヤーをチェックすると、シミュレータ上で、アルファチャネルがある箇所が赤く表示されます。

この赤い部分を極力減らしていくのが、チューニングステップ1です。だたし、これだけでは、体感レベルでの効果は得られませんでした。(これは、もちろんアプリの処理内容によるかと思います。)

このあたりは、フェンリルさんのブログエントリiPhone / iPad アプリのアニメーションをなめらかにするためのポイント3つを参考にさせて頂きました。

 

オフラインレンダリングを減らす(shadow描画)

上記のフェンリルさんのブログエントリにもありますが、iOSの自動オフラインレンダリングが発生するとFPSが低下するとのことで、特にCALayerのshadowプロパティを使用していると、オフラインレンダリングが発生し、激しくFPSが低下することがわかりました。

CALayerのshadowプロパティは、

layer.shadowRadius = 3;
layer.shadowColor = [UIColor blackColor].CGColor;
layer.shadowOpacity = 0.5;
layer.shadowOffset = CGSizeMake(1, 3);

とすると、CALayerに影をつけてくれる便利機能なので、できればそのまま使いたいと思い、いろいろと調べていたところ、以下のBlogのエントリにたどり着きました。

iPad drop shadow performance

shadow描画のパフォーマンスを、いろいろな描画方式で比較されてます。CALayerのshadowを利用していても、shadowPathを使うとよいとのことなので、

layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;

を追加してみたところ、劇的に早くなりました。
ということで、CALayerのshadowを使う際には、shadowPath指定をお忘れなく!